bool USoundWave::IsCachedCookedPlatformDataLoaded( const ITargetPlatform* TargetPlatform ) { if (TargetPlatform->SupportsFeature(ETargetPlatformFeatures::AudioStreaming) && IsStreaming()) { // Retrieve format to cache for targetplatform. FName PlatformFormat = TargetPlatform->GetWaveFormat(this); // find format data by comparing derived data keys. FString DerivedDataKey; GetStreamedAudioDerivedDataKeySuffix(*this, PlatformFormat, DerivedDataKey); FStreamedAudioPlatformData *PlatformData = CookedPlatformData.FindRef(DerivedDataKey); if (PlatformData == NULL) { // we havne't called begincache return false; } if (PlatformData->AsyncTask && PlatformData->AsyncTask->IsWorkDone()) { PlatformData->FinishCache(); } return PlatformData->IsFinishedCache(); } return true; }
/** * Computes the derived data key for 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 OutKey - The derived data key. */ static void GetStreamedAudioDerivedDataKey( const USoundWave& SoundWave, FName AudioFormatName, FString& OutKey ) { FString KeySuffix; GetStreamedAudioDerivedDataKeySuffix(SoundWave, AudioFormatName, KeySuffix); GetStreamedAudioDerivedDataKeyFromSuffix(KeySuffix, OutKey); }
void USoundWave::ClearCachedCookedPlatformData( const ITargetPlatform* TargetPlatform ) { Super::ClearCachedCookedPlatformData(TargetPlatform); if (TargetPlatform->SupportsFeature(ETargetPlatformFeatures::AudioStreaming) && IsStreaming()) { // Retrieve format to cache for targetplatform. FName PlatformFormat = TargetPlatform->GetWaveFormat(this); // find format data by comparing derived data keys. FString DerivedDataKey; GetStreamedAudioDerivedDataKeySuffix(*this, PlatformFormat, DerivedDataKey); if ( CookedPlatformData.Contains(DerivedDataKey) ) { FStreamedAudioPlatformData *PlatformData = CookedPlatformData.FindAndRemoveChecked( DerivedDataKey ); delete PlatformData; } } }
void USoundWave::BeginCacheForCookedPlatformData(const ITargetPlatform *TargetPlatform) { if (TargetPlatform->SupportsFeature(ETargetPlatformFeatures::AudioStreaming) && IsStreaming()) { // Retrieve format to cache for targetplatform. FName PlatformFormat = TargetPlatform->GetWaveFormat(this); uint32 CacheFlags = EStreamedAudioCacheFlags::Async | EStreamedAudioCacheFlags::InlineChunks; // If source data is resident in memory then allow the streamed audio to be built // in a background thread. if (GetCompressedData(PlatformFormat)->IsBulkDataLoaded()) { CacheFlags |= EStreamedAudioCacheFlags::AllowAsyncBuild; } // find format data by comparing derived data keys. FString DerivedDataKey; GetStreamedAudioDerivedDataKeySuffix(*this, PlatformFormat, DerivedDataKey); FStreamedAudioPlatformData *PlatformData = CookedPlatformData.FindRef(DerivedDataKey); if (PlatformData == NULL) { PlatformData = new FStreamedAudioPlatformData(); PlatformData->Cache( *this, PlatformFormat, CacheFlags ); CookedPlatformData.Add(DerivedDataKey, PlatformData); } } Super::BeginCacheForCookedPlatformData(TargetPlatform); }
/** 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() ); } }