mirror of
https://github.com/storytold/RuntimeAudioImporter.git
synced 2026-10-15 00:04:13 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ecfcee44d | |||
| a3bb87a497 | |||
| 3ff7ed6fba |
@@ -14,7 +14,7 @@
|
|||||||
"IsBetaVersion": false,
|
"IsBetaVersion": false,
|
||||||
"IsExperimentalVersion": false,
|
"IsExperimentalVersion": false,
|
||||||
"Installed": true,
|
"Installed": true,
|
||||||
"EngineVersion": "4.26.0",
|
"EngineVersion": "4.25.0",
|
||||||
"Modules": [
|
"Modules": [
|
||||||
{
|
{
|
||||||
"Name": "RuntimeAudioImporter",
|
"Name": "RuntimeAudioImporter",
|
||||||
|
|||||||
+74
-25
@@ -11,11 +11,23 @@
|
|||||||
#include "OpusCompressor.h"
|
#include "OpusCompressor.h"
|
||||||
#include "AdvancedPCMCompressor.h"
|
#include "AdvancedPCMCompressor.h"
|
||||||
|
|
||||||
|
#include "PreimportedSoundAsset.h"
|
||||||
|
|
||||||
|
#include "Misc/FileHelper.h"
|
||||||
|
|
||||||
|
|
||||||
URuntimeAudioImporterLibrary* URuntimeAudioImporterLibrary::CreateRuntimeAudioImporter()
|
URuntimeAudioImporterLibrary* URuntimeAudioImporterLibrary::CreateRuntimeAudioImporter()
|
||||||
{
|
{
|
||||||
URuntimeAudioImporterLibrary* Importer = NewObject<URuntimeAudioImporterLibrary>();
|
URuntimeAudioImporterLibrary* Importer = NewObject<URuntimeAudioImporterLibrary>();
|
||||||
Importer->AddToRoot();
|
Importer->bUseOfAdvancedBuffersInfo = false;
|
||||||
|
return Importer;
|
||||||
|
}
|
||||||
|
|
||||||
|
URuntimeAudioImporterLibrary* URuntimeAudioImporterLibrary::CreateAdvancedRuntimeAudioImporter(
|
||||||
|
const bool UseOfAdvancedBufferInfo)
|
||||||
|
{
|
||||||
|
URuntimeAudioImporterLibrary* Importer = NewObject<URuntimeAudioImporterLibrary>();
|
||||||
|
Importer->bUseOfAdvancedBuffersInfo = UseOfAdvancedBufferInfo;
|
||||||
return Importer;
|
return Importer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,9 +36,6 @@ void URuntimeAudioImporterLibrary::ImportAudioFromFile(
|
|||||||
{
|
{
|
||||||
if (!FPaths::FileExists(FilePath))
|
if (!FPaths::FileExists(FilePath))
|
||||||
{
|
{
|
||||||
// Trying to get a file inside packaged build
|
|
||||||
IPlatformFile& FileManager = FPlatformFileManager::Get().GetPlatformFile();
|
|
||||||
|
|
||||||
OnResult_Internal(nullptr, ETranscodingStatus::AudioDoesNotExist);
|
OnResult_Internal(nullptr, ETranscodingStatus::AudioDoesNotExist);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -47,6 +56,7 @@ void URuntimeAudioImporterLibrary::ImportAudioFromFile(
|
|||||||
ImportAudioFromBuffer(AudioBuffer, Format, BuffersDetails);
|
ImportAudioFromBuffer(AudioBuffer, Format, BuffersDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void URuntimeAudioImporterLibrary::ImportAudioFromPreimportedSound(UPreimportedSoundAsset* PreimportedSoundAssetRef,
|
void URuntimeAudioImporterLibrary::ImportAudioFromPreimportedSound(UPreimportedSoundAsset* PreimportedSoundAssetRef,
|
||||||
const FBuffersDetailsStruct& BuffersDetails)
|
const FBuffersDetailsStruct& BuffersDetails)
|
||||||
{
|
{
|
||||||
@@ -145,7 +155,8 @@ USoundWave* URuntimeAudioImporterLibrary::DefineSoundWave()
|
|||||||
OnProgress_Internal(45);
|
OnProgress_Internal(45);
|
||||||
|
|
||||||
// Whether to fill the compressed buffer or not. If not filled, it is necessary to fill Raw (Wave) data so that the engine will automatically generate compressed data.
|
// Whether to fill the compressed buffer or not. If not filled, it is necessary to fill Raw (Wave) data so that the engine will automatically generate compressed data.
|
||||||
if (BuffersDetailsInfo.CompressionFormat == ECompressionFormat::RawData)
|
if (BuffersDetailsInfo.CompressionFormat == ECompressionFormat::RawData || (bUseOfAdvancedBuffersInfo &&
|
||||||
|
AdvancedBuffersInfo.FillRawData))
|
||||||
{
|
{
|
||||||
// Callback Dispatcher OnProgress
|
// Callback Dispatcher OnProgress
|
||||||
OnProgress_Internal(60);
|
OnProgress_Internal(60);
|
||||||
@@ -157,8 +168,11 @@ USoundWave* URuntimeAudioImporterLibrary::DefineSoundWave()
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// free unneeded PCM Data
|
if (!bUseOfAdvancedBuffersInfo || (bUseOfAdvancedBuffersInfo && !AdvancedBuffersInfo.FillPCMData))
|
||||||
FMemory::Free(TranscodingFillInfo.PCMInfo.RawPCMData);
|
{
|
||||||
|
// free unneeded PCM Data
|
||||||
|
FMemory::Free(TranscodingFillInfo.PCMInfo.RawPCMData);
|
||||||
|
}
|
||||||
|
|
||||||
// Callback Dispatcher OnProgress
|
// Callback Dispatcher OnProgress
|
||||||
OnProgress_Internal(75);
|
OnProgress_Internal(75);
|
||||||
@@ -166,16 +180,18 @@ USoundWave* URuntimeAudioImporterLibrary::DefineSoundWave()
|
|||||||
// Fill Raw (Wave) Data
|
// Fill Raw (Wave) Data
|
||||||
FillRawWaveData(SoundWaveRef);
|
FillRawWaveData(SoundWaveRef);
|
||||||
|
|
||||||
|
// Fill PCM Data if needed
|
||||||
|
if (bUseOfAdvancedBuffersInfo && AdvancedBuffersInfo.FillPCMData)
|
||||||
|
{
|
||||||
|
FillPCMData(SoundWaveRef);
|
||||||
|
}
|
||||||
|
|
||||||
// Callback Dispatcher OnProgress
|
// Callback Dispatcher OnProgress
|
||||||
OnProgress_Internal(95);
|
OnProgress_Internal(95);
|
||||||
|
|
||||||
return SoundWaveRef;
|
return SoundWaveRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't need to fill RawPCMData buffer since it is not used at runtime during audio playback. But in case you want to fill this buffer - uncomment the code below (you should also remove some RawPCMData cleanups in code before it is executed)
|
|
||||||
sw->RawPCMData = static_cast<uint8*>(FMemory::Malloc(sw->RawPCMDataSize));
|
|
||||||
FMemory::Memmove(sw->RawPCMData, TranscodingFillInfo.PCMInfo.RawPCMData, sw->RawPCMDataSize);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Set a new sound compression quality
|
// Set a new sound compression quality
|
||||||
SoundWaveRef->CompressionQuality = BuffersDetailsInfo.SoundCompressionQuality;
|
SoundWaveRef->CompressionQuality = BuffersDetailsInfo.SoundCompressionQuality;
|
||||||
@@ -186,20 +202,30 @@ USoundWave* URuntimeAudioImporterLibrary::DefineSoundWave()
|
|||||||
// Callback Dispatcher OnProgress
|
// Callback Dispatcher OnProgress
|
||||||
OnProgress_Internal(60);
|
OnProgress_Internal(60);
|
||||||
|
|
||||||
// Transcode Raw PCM data to Compressed data
|
if (!bUseOfAdvancedBuffersInfo || (bUseOfAdvancedBuffersInfo && AdvancedBuffersInfo.FillCompressedData &&
|
||||||
if (!TranscodePCMToCompressedData(SoundWaveRef))
|
AdvancedBuffersInfo.CompressionFormat != ECompressionFormat::RawData))
|
||||||
{
|
{
|
||||||
return nullptr;
|
// Transcode Raw PCM data to Compressed data
|
||||||
|
if (!TranscodePCMToCompressedData(SoundWaveRef))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback Dispatcher OnProgress
|
||||||
|
OnProgress_Internal(75);
|
||||||
|
|
||||||
|
SoundWaveRef->SetPrecacheState(ESoundWavePrecacheState::NotStarted);
|
||||||
|
|
||||||
|
// Fill the compressed data
|
||||||
|
FillCompressedData(SoundWaveRef);
|
||||||
|
|
||||||
|
// Fill PCM Data if needed
|
||||||
|
if (bUseOfAdvancedBuffersInfo && AdvancedBuffersInfo.FillPCMData)
|
||||||
|
{
|
||||||
|
FillPCMData(SoundWaveRef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback Dispatcher OnProgress
|
|
||||||
OnProgress_Internal(75);
|
|
||||||
|
|
||||||
SoundWaveRef->SetPrecacheState(ESoundWavePrecacheState::NotStarted);
|
|
||||||
|
|
||||||
// Fill the compressed data
|
|
||||||
FillCompressedData(SoundWaveRef);
|
|
||||||
|
|
||||||
// Callback Dispatcher OnProgress
|
// Callback Dispatcher OnProgress
|
||||||
OnProgress_Internal(95);
|
OnProgress_Internal(95);
|
||||||
|
|
||||||
@@ -227,6 +253,9 @@ void URuntimeAudioImporterLibrary::FillRawWaveData(USoundWave* SoundWaveRef) con
|
|||||||
FMemory::Memmove(SoundWaveRef->RawData.Realloc(TranscodingFillInfo.WAVInfo.WaveDataSize),
|
FMemory::Memmove(SoundWaveRef->RawData.Realloc(TranscodingFillInfo.WAVInfo.WaveDataSize),
|
||||||
TranscodingFillInfo.WAVInfo.WaveData, TranscodingFillInfo.WAVInfo.WaveDataSize);
|
TranscodingFillInfo.WAVInfo.WaveData, TranscodingFillInfo.WAVInfo.WaveDataSize);
|
||||||
SoundWaveRef->RawData.Unlock();
|
SoundWaveRef->RawData.Unlock();
|
||||||
|
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("RawData has been filled successfully, Raw data size: %d"),
|
||||||
|
TranscodingFillInfo.WAVInfo.WaveDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void URuntimeAudioImporterLibrary::FillCompressedData(USoundWave* SoundWaveRef)
|
void URuntimeAudioImporterLibrary::FillCompressedData(USoundWave* SoundWaveRef)
|
||||||
@@ -247,6 +276,18 @@ void URuntimeAudioImporterLibrary::FillCompressedData(USoundWave* SoundWaveRef)
|
|||||||
CompressedBulkData->Unlock();
|
CompressedBulkData->Unlock();
|
||||||
|
|
||||||
SoundWaveRef->SetPrecacheState(ESoundWavePrecacheState::Done);
|
SoundWaveRef->SetPrecacheState(ESoundWavePrecacheState::Done);
|
||||||
|
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("Compressed data has been filled successfully, Cmpressed data size: %d"),
|
||||||
|
TranscodingFillInfo.CompressedInfo.CompressedFormatData.Num());
|
||||||
|
}
|
||||||
|
|
||||||
|
void URuntimeAudioImporterLibrary::FillPCMData(USoundWave* SoundWaveRef)
|
||||||
|
{
|
||||||
|
SoundWaveRef->RawPCMData = static_cast<uint8*>(FMemory::Malloc(SoundWaveRef->RawPCMDataSize));
|
||||||
|
FMemory::Memmove(SoundWaveRef->RawPCMData, TranscodingFillInfo.PCMInfo.RawPCMData,
|
||||||
|
SoundWaveRef->RawPCMDataSize);
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("PCM Data has been filled successfully, PCMData size: %d"),
|
||||||
|
TranscodingFillInfo.PCMInfo.RawPCMDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool URuntimeAudioImporterLibrary::TranscodePCMToCompressedData(USoundWave* SoundWaveToGetData)
|
bool URuntimeAudioImporterLibrary::TranscodePCMToCompressedData(USoundWave* SoundWaveToGetData)
|
||||||
@@ -258,6 +299,11 @@ bool URuntimeAudioImporterLibrary::TranscodePCMToCompressedData(USoundWave* Soun
|
|||||||
// Sound quality information for compression purposes
|
// Sound quality information for compression purposes
|
||||||
FSoundQualityInfo SoundQualityInfo = GenerateSoundQualityInfo(SoundWaveToGetData);
|
FSoundQualityInfo SoundQualityInfo = GenerateSoundQualityInfo(SoundWaveToGetData);
|
||||||
|
|
||||||
|
if (bUseOfAdvancedBuffersInfo)
|
||||||
|
{
|
||||||
|
BuffersDetailsInfo.CompressionFormat = AdvancedBuffersInfo.CompressionFormat;
|
||||||
|
}
|
||||||
|
|
||||||
switch (BuffersDetailsInfo.CompressionFormat)
|
switch (BuffersDetailsInfo.CompressionFormat)
|
||||||
{
|
{
|
||||||
case OggVorbis:
|
case OggVorbis:
|
||||||
@@ -315,9 +361,12 @@ bool URuntimeAudioImporterLibrary::TranscodePCMToCompressedData(USoundWave* Soun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the compressed data is generated, RawPCMData is no longer needed.
|
if (!bUseOfAdvancedBuffersInfo || (bUseOfAdvancedBuffersInfo && !AdvancedBuffersInfo.FillPCMData))
|
||||||
RawPCMArray.Empty();
|
{
|
||||||
FMemory::Free(TranscodingFillInfo.PCMInfo.RawPCMData);
|
// When the compressed data is generated, RawPCMData is no longer needed
|
||||||
|
RawPCMArray.Empty();
|
||||||
|
FMemory::Free(TranscodingFillInfo.PCMInfo.RawPCMData);
|
||||||
|
}
|
||||||
|
|
||||||
// Callback Dispatcher OnProgress
|
// Callback Dispatcher OnProgress
|
||||||
OnProgress_Internal(85);
|
OnProgress_Internal(85);
|
||||||
|
|||||||
+43
-7
@@ -5,8 +5,6 @@
|
|||||||
#include "Sound/SoundWave.h"
|
#include "Sound/SoundWave.h"
|
||||||
#include "Async/Async.h"
|
#include "Async/Async.h"
|
||||||
|
|
||||||
#include "PreimportedSoundAsset.h"
|
|
||||||
|
|
||||||
#include "RuntimeAudioImporterLibrary.generated.h"
|
#include "RuntimeAudioImporterLibrary.generated.h"
|
||||||
|
|
||||||
/** Possible audio importing results */
|
/** Possible audio importing results */
|
||||||
@@ -79,7 +77,7 @@ enum ECompressionFormat
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Information about which buffers to fill */
|
/** Information about which buffers to fill */
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType, Category = "RuntimeAudioImporter")
|
||||||
struct FBuffersDetailsStruct
|
struct FBuffersDetailsStruct
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
@@ -155,15 +153,34 @@ struct FTranscodingFillStruct
|
|||||||
FCompressedStruct CompressedInfo;
|
FCompressedStruct CompressedInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Advanced CPP only structure which contains information about which buffers to fill */
|
||||||
|
struct FAdvancedBuffersStruct
|
||||||
|
{
|
||||||
|
/** Needed compression format. Do not select RawData here! If you want to fill Raw (Wav) Data, check the "FillRawData" parameter */
|
||||||
|
TEnumAsByte<ECompressionFormat> CompressionFormat;
|
||||||
|
|
||||||
|
/** Whether to fill the compressed data or not */
|
||||||
|
bool FillCompressedData = false;
|
||||||
|
|
||||||
|
/** Whether to fill PCM Data or not */
|
||||||
|
bool FillPCMData = false;
|
||||||
|
|
||||||
|
/** Whether to fill Raw (Wav) data */
|
||||||
|
bool FillRawData = false;
|
||||||
|
};
|
||||||
|
|
||||||
// Forward declaration of the FSoundQualityInfo structure
|
// Forward declaration of the FSoundQualityInfo structure
|
||||||
struct FSoundQualityInfo;
|
struct FSoundQualityInfo;
|
||||||
|
|
||||||
|
// Forward declaration of the UPreimportedSoundAsset class
|
||||||
|
class UPreimportedSoundAsset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare delegate which will be called during the transcoding process
|
* Declare delegate which will be called during the transcoding process
|
||||||
*
|
*
|
||||||
* @param Percentage Percentage of importing completed (0-100%)
|
* @param Percentage Percentage of importing completed (0-100%)
|
||||||
*/
|
*/
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnProgress, const int32, Percentage);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAudioProgress, const int32, Percentage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare a delegate that will be called on the transcoding result
|
* Declare a delegate that will be called on the transcoding result
|
||||||
@@ -172,7 +189,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnProgress, const int32, Percentage
|
|||||||
* @param ReadySoundWave Ready SoundWave object reference
|
* @param ReadySoundWave Ready SoundWave object reference
|
||||||
* @param Status TranscodingStatus Enum in case an error occurs
|
* @param Status TranscodingStatus Enum in case an error occurs
|
||||||
*/
|
*/
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnResult, class URuntimeAudioImporterLibrary*,
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnAudioResult, class URuntimeAudioImporterLibrary*,
|
||||||
RuntimeAudioImporterObjectRef,
|
RuntimeAudioImporterObjectRef,
|
||||||
const USoundWave*, SoundWaveRef,
|
const USoundWave*, SoundWaveRef,
|
||||||
const TEnumAsByte < ETranscodingStatus >&, Status);
|
const TEnumAsByte < ETranscodingStatus >&, Status);
|
||||||
@@ -189,11 +206,11 @@ public:
|
|||||||
|
|
||||||
/** Bind to know when the transcoding is on progress */
|
/** Bind to know when the transcoding is on progress */
|
||||||
UPROPERTY(BlueprintAssignable, Category = "RuntimeAudioImporter")
|
UPROPERTY(BlueprintAssignable, Category = "RuntimeAudioImporter")
|
||||||
FOnProgress OnProgress;
|
FOnAudioProgress OnProgress;
|
||||||
|
|
||||||
/** Bind to know when the transcoding is complete (even if it fails) */
|
/** Bind to know when the transcoding is complete (even if it fails) */
|
||||||
UPROPERTY(BlueprintAssignable, Category = "RuntimeAudioImporter")
|
UPROPERTY(BlueprintAssignable, Category = "RuntimeAudioImporter")
|
||||||
FOnResult OnResult;
|
FOnAudioResult OnResult;
|
||||||
|
|
||||||
/** Transcoding fill info. CPP use only */
|
/** Transcoding fill info. CPP use only */
|
||||||
FTranscodingFillStruct TranscodingFillInfo = FTranscodingFillStruct();
|
FTranscodingFillStruct TranscodingFillInfo = FTranscodingFillStruct();
|
||||||
@@ -201,6 +218,10 @@ public:
|
|||||||
/** Buffers details info. CPP use only */
|
/** Buffers details info. CPP use only */
|
||||||
FBuffersDetailsStruct BuffersDetailsInfo = FBuffersDetailsStruct();
|
FBuffersDetailsStruct BuffersDetailsInfo = FBuffersDetailsStruct();
|
||||||
|
|
||||||
|
/** Advanced buffer details info. CPP use only (even as an input parameter) */
|
||||||
|
FAdvancedBuffersStruct AdvancedBuffersInfo = FAdvancedBuffersStruct();
|
||||||
|
bool bUseOfAdvancedBuffersInfo = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a RuntimeAudioImporter object
|
* Instantiates a RuntimeAudioImporter object
|
||||||
*
|
*
|
||||||
@@ -211,6 +232,14 @@ public:
|
|||||||
"RuntimeAudioImporter")
|
"RuntimeAudioImporter")
|
||||||
static URuntimeAudioImporterLibrary* CreateRuntimeAudioImporter();
|
static URuntimeAudioImporterLibrary* CreateRuntimeAudioImporter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you want to select a separate formats to fill (using of "FAdvancedBuffersStruct"), then use this method in CPP
|
||||||
|
*
|
||||||
|
* @param UseOfAdvancedBufferInfo Whether to use the advanced buffer info or not
|
||||||
|
*/
|
||||||
|
UFUNCTION()
|
||||||
|
static URuntimeAudioImporterLibrary* CreateAdvancedRuntimeAudioImporter(const bool UseOfAdvancedBufferInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transcode audio file to SoundWave object
|
* Transcode audio file to SoundWave object
|
||||||
*
|
*
|
||||||
@@ -296,6 +325,13 @@ private:
|
|||||||
*/
|
*/
|
||||||
void FillCompressedData(USoundWave* SoundWaveRef);
|
void FillCompressedData(USoundWave* SoundWaveRef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill SoundWave PCM data buffer
|
||||||
|
*
|
||||||
|
* @param SoundWaveRef SoundWave object reference
|
||||||
|
*/
|
||||||
|
void FillPCMData(USoundWave* SoundWaveRef);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transcode Audio from PCM to 16-bit WAV data
|
* Transcode Audio from PCM to 16-bit WAV data
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user