From 14469d959f576479e47eff74a43b07f282253a90 Mon Sep 17 00:00:00 2001 From: Respirant Date: Sun, 10 Jan 2021 16:59:27 +0300 Subject: [PATCH] function to export soundwave to wav file --- .../RuntimeAudioImporter.uplugin | 2 +- .../Private/RuntimeAudioImporterLibrary.cpp | 44 +++++++++++++++++++ .../Public/RuntimeAudioImporterLibrary.h | 12 +++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/RuntimeAudioImporter/RuntimeAudioImporter.uplugin b/RuntimeAudioImporter/RuntimeAudioImporter.uplugin index 4dfd899..49686b2 100644 --- a/RuntimeAudioImporter/RuntimeAudioImporter.uplugin +++ b/RuntimeAudioImporter/RuntimeAudioImporter.uplugin @@ -14,7 +14,7 @@ "IsBetaVersion": false, "IsExperimentalVersion": false, "Installed": true, - "EngineVersion": "4.26.0", + "EngineVersion": "4.24.0", "Modules": [ { "Name": "RuntimeAudioImporter", diff --git a/RuntimeAudioImporter/Source/RuntimeAudioImporter/Private/RuntimeAudioImporterLibrary.cpp b/RuntimeAudioImporter/Source/RuntimeAudioImporter/Private/RuntimeAudioImporterLibrary.cpp index f33be6a..74bdaec 100644 --- a/RuntimeAudioImporter/Source/RuntimeAudioImporter/Private/RuntimeAudioImporterLibrary.cpp +++ b/RuntimeAudioImporter/Source/RuntimeAudioImporter/Private/RuntimeAudioImporterLibrary.cpp @@ -77,6 +77,50 @@ void unreal_free(void* p, void* pUserData) FMemory::Free(p); } +bool URuntimeAudioImporterLibrary::ExportSoundWaveToFile(USoundWave* SoundWaveToExport, FString PathToExport, bool Faster) +{ + uint8* PCMData = SoundWaveToExport->RawPCMData; + size_t PCMDataSize = SoundWaveToExport->RawPCMDataSize; + + uint32 SampleRate; + uint16 ChannelCount; + + drwav_allocation_callbacks allocationCallbacksDecoding; + allocationCallbacksDecoding.pUserData = NULL; + allocationCallbacksDecoding.onMalloc = unreal_malloc; + allocationCallbacksDecoding.onRealloc = unreal_realloc; + allocationCallbacksDecoding.onFree = unreal_free; + + drwav_uint64 framesToWrite = PCMDataSize / sizeof(DR_WAVE_FORMAT_PCM) / SoundWaveToExport->NumChannels; + + if (Faster) { + ChannelCount = SoundWaveToExport->NumChannels; + SampleRate = FGenericPlatformMath::RoundToInt((framesToWrite / (float)SoundWaveToExport->GetDuration() * ChannelCount)); + } + else { + TArray NeedlessPCMData; //Needless PCMData array, but without it, it is not possible to get SampleRate + SoundWaveToExport->GetImportedSoundWaveData(*&NeedlessPCMData, *&SampleRate, *&ChannelCount); + NeedlessPCMData.Empty(); + } + drwav wavEncode; + + drwav_data_format format; + format.container = drwav_container_riff; + format.format = DR_WAVE_FORMAT_PCM; + format.channels = ChannelCount; + format.sampleRate = SampleRate; + format.bitsPerSample = 16; + + if (!drwav_init_file_write(&wavEncode, TCHAR_TO_UTF8(*PathToExport), &format, &allocationCallbacksDecoding)) { + return false; + } + + drwav_write_pcm_frames(&wavEncode, framesToWrite, PCMData); + drwav_uninit(&wavEncode); + + return true; +} + URuntimeAudioImporterLibrary* URuntimeAudioImporterLibrary::GetUSoundWaveFromAudioFile_Internal(const FString& filePath, TEnumAsByte < AudioFormat > Format, bool DefineFormatAutomatically) { TEnumAsByte < TranscodingStatus > Status; diff --git a/RuntimeAudioImporter/Source/RuntimeAudioImporter/Public/RuntimeAudioImporterLibrary.h b/RuntimeAudioImporter/Source/RuntimeAudioImporter/Public/RuntimeAudioImporterLibrary.h index 91c5b11..2b3f4bc 100644 --- a/RuntimeAudioImporter/Source/RuntimeAudioImporter/Public/RuntimeAudioImporterLibrary.h +++ b/RuntimeAudioImporter/Source/RuntimeAudioImporter/Public/RuntimeAudioImporterLibrary.h @@ -101,6 +101,18 @@ public: UFUNCTION(BlueprintCallable, meta = (Keywords = "MP3, FLAC, WAV, Destroy"), Category = "RuntimeAudioImporter") static bool DestroySoundWave(USoundWave * ReadySoundWave); + /** + * Export (save) SoundWave object to .WAV audio file to device memory. So far beta and it is not recommended to use due to the fact that the engine can clear the sound data itself + * + * @param SoundWaveToExport SoundWave object need to be exported + * @param PathToExport Path where to save audio file + * @param Faster Get SampleRate faster. Less clear, but fast. The difference is very insignificant, True is recommended + * @return Whether the save was successfull or not + * @warning It is very important that USoundWave should not used by the engine so that it can be read from physical memory. + */ + UFUNCTION(BlueprintCallable, meta = (Keywords = "Exporter, Export, Save, Runtime, WAV"), Category = "RuntimeAudioImporter") + static bool ExportSoundWaveToFile(USoundWave * SoundWaveToExport, FString PathToExport, bool Faster = true); + private: /** * Internal main audio transcoding function