/** * Computes the derived data key suffix for a SoundWave's Streamed Audio. * @param SoundWave - The SoundWave for which to compute the derived data key. * @param AudioFormatName - The audio format we're creating the key for * @param OutKeySuffix - The derived data key suffix. */ static void GetStreamedAudioDerivedDataKeySuffix( const USoundWave& SoundWave, FName AudioFormatName, FString& OutKeySuffix ) { uint16 Version = 0; // get the version for this soundwave's platform format ITargetPlatformManagerModule* TPM = GetTargetPlatformManager(); if (TPM) { const IAudioFormat* AudioFormat = TPM->FindAudioFormat(AudioFormatName); if (AudioFormat) { Version = AudioFormat->GetVersion(AudioFormatName); } } // build the key OutKeySuffix = FString::Printf(TEXT("%s_%d_%s"), *AudioFormatName.ToString(), Version, *SoundWave.CompressedDataGuid.ToString() ); }
FDerivedAudioDataCompressor::FDerivedAudioDataCompressor(USoundWave* InSoundNode, FName InFormat) : SoundNode(InSoundNode) , Format(InFormat) , Compressor(NULL) { ITargetPlatformManagerModule* TPM = GetTargetPlatformManager(); if (TPM) { Compressor = TPM->FindAudioFormat(InFormat); } }
/** Build the streamed audio. This function is safe to call from any thread. */ void BuildStreamedAudio() { GetStreamedAudioDerivedDataKeySuffix(SoundWave, AudioFormatName, KeySuffix); DerivedData->Chunks.Empty(); ITargetPlatformManagerModule* TPM = GetTargetPlatformManager(); const IAudioFormat* AudioFormat = NULL; if (TPM) { AudioFormat = TPM->FindAudioFormat(AudioFormatName); } if (AudioFormat) { DerivedData->AudioFormat = AudioFormatName; FByteBulkData* CompressedData = SoundWave.GetCompressedData(AudioFormatName); TArray<uint8> CompressedBuffer; CompressedBuffer.Empty(CompressedData->GetBulkDataSize()); CompressedBuffer.AddUninitialized(CompressedData->GetBulkDataSize()); void* BufferData = CompressedBuffer.GetData(); CompressedData->GetCopy(&BufferData, false); TArray<TArray<uint8>> ChunkBuffers; if (AudioFormat->SplitDataForStreaming(CompressedBuffer, ChunkBuffers)) { for (int32 ChunkIndex = 0; ChunkIndex < ChunkBuffers.Num(); ++ChunkIndex) { FStreamedAudioChunk* NewChunk = new(DerivedData->Chunks) FStreamedAudioChunk(); NewChunk->DataSize = ChunkBuffers[ChunkIndex].Num(); NewChunk->BulkData.Lock(LOCK_READ_WRITE); void* NewChunkData = NewChunk->BulkData.Realloc(ChunkBuffers[ChunkIndex].Num()); FMemory::Memcpy(NewChunkData, ChunkBuffers[ChunkIndex].GetData(), ChunkBuffers[ChunkIndex].Num()); NewChunk->BulkData.Unlock(); } } else { // Could not split so copy compressed data into a single chunk FStreamedAudioChunk* NewChunk = new(DerivedData->Chunks) FStreamedAudioChunk(); NewChunk->DataSize = CompressedBuffer.Num(); NewChunk->BulkData.Lock(LOCK_READ_WRITE); void* NewChunkData = NewChunk->BulkData.Realloc(CompressedBuffer.Num()); FMemory::Memcpy(NewChunkData, CompressedBuffer.GetData(), CompressedBuffer.Num()); NewChunk->BulkData.Unlock(); } DerivedData->NumChunks = DerivedData->Chunks.Num(); // Store it in the cache. PutDerivedDataInCache(DerivedData, KeySuffix); } if (DerivedData->Chunks.Num()) { bool bInlineChunks = (CacheFlags & EStreamedAudioCacheFlags::InlineChunks) != 0; bSucceeded = !bInlineChunks || DerivedData->TryInlineChunkData(); } else { UE_LOG(LogAudio, Warning, TEXT("Failed to build %s derived data for %s"), *AudioFormatName.GetPlainNameString(), *SoundWave.GetPathName() ); } }