bool USoundWave::IsReadyForFinishDestroy() { const bool bIsStreamingInProgress = IStreamingManager::Get().GetAudioStreamingManager().IsStreamingInProgress(this); // Wait till streaming and decompression finishes before deleting resource. if ( !bIsStreamingInProgress && (( AudioDecompressor == nullptr ) || AudioDecompressor->IsDone()) ) { if (ResourceState == ESoundWaveResourceState::NeedsFree) { DECLARE_CYCLE_STAT(TEXT("FAudioThreadTask.FreeResources"), STAT_AudioFreeResources, STATGROUP_AudioThreadCommands); USoundWave* SoundWave = this; ResourceState = ESoundWaveResourceState::Freeing; FAudioThread::RunCommandOnAudioThread([SoundWave]() { SoundWave->FreeResources(); }, GET_STATID(STAT_AudioFreeResources)); } } return ResourceState == ESoundWaveResourceState::Freed; }
UObject* UMP3SoundFactory::FactoryCreateBinary(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn) { FEditorDelegates::OnAssetPreImport.Broadcast(this, Class, InParent, Name, Type); if (mpg123_init == nullptr) { Warn->Logf(ELogVerbosity::Error, TEXT("Function pointer was null. Was %s found?"), DLL_NAME); FEditorDelegates::OnAssetPostImport.Broadcast(this, nullptr); return nullptr; } // if the sound already exists, remember the user settings USoundWave* ExistingSound = FindObject<USoundWave>(InParent, *Name.ToString()); // stop playing the file, if it already exists (e.g. reimport) TArray<UAudioComponent*> ComponentsToRestart; FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager(); if (AudioDeviceManager && ExistingSound) { AudioDeviceManager->StopSoundsUsingResource(ExistingSound, ComponentsToRestart); } // Read the mp3 header and make sure we have valid data UMP3Decoder Decoder(Warn); Decoder.Init(Buffer, BufferEnd); if (Decoder.BitsPerSample != 16) { Warn->Logf(ELogVerbosity::Error, TEXT("Unreal only supports 16bit WAVE data (%s)."), *Name.ToString()); FEditorDelegates::OnAssetPostImport.Broadcast(this, nullptr); return nullptr; } if (Decoder.Channels != 1 && Decoder.Channels != 2) { Warn->Logf(ELogVerbosity::Error, TEXT("Unreal only supports 1-2 channel WAVE data (Mono/Stereo). (%s)."), *Name.ToString()); FEditorDelegates::OnAssetPostImport.Broadcast(this, nullptr); return nullptr; } //on reimport, reuse settings, wipe data. otherwise create new. (UE4 WAVE import has some more checks, maybe implement, too?) USoundWave* Sound; if (ExistingSound && bMP3SoundFactoryIsReimport) { Sound = ExistingSound; Sound->FreeResources(); Sound->InvalidateCompressedData(); } else { Sound = NewObject<USoundWave>(InParent, Name, Flags); } Sound->AssetImportData->Update(GetCurrentFilename()); TArray<uint8> RawWavBuffer; RawWavBuffer.Reserve((BufferEnd - Buffer) * 16); //actual decoding Decoder.Decode(RawWavBuffer); Sound->RawData.Lock(LOCK_READ_WRITE); void* LockedData = Sound->RawData.Realloc(RawWavBuffer.Num() * RawWavBuffer.GetTypeSize()); FMemory::Memcpy(LockedData, RawWavBuffer.GetData(), RawWavBuffer.Num() * RawWavBuffer.GetTypeSize()); Sound->RawData.Unlock(); RawWavBuffer.Empty(); // Calculate duration. Sound->Duration = (float)Decoder.SizeInBytes / Decoder.Samplerate / Decoder.Channels / (BITS_PER_SAMPLE / 8); Sound->SampleRate = Decoder.Samplerate; Sound->NumChannels = Decoder.Channels; Sound->RawPCMDataSize = Decoder.SizeInBytes; FEditorDelegates::OnAssetPostImport.Broadcast(this, Sound); if (ExistingSound) { Sound->PostEditChange(); } for (int32 ComponentIndex = 0; ComponentIndex < ComponentsToRestart.Num(); ++ComponentIndex) { ComponentsToRestart[ComponentIndex]->Play(); } return Sound; }