Is there a way to get raw byte data from USoundWave?

Hi everyone
Is there a way to get raw byte data from USoundWave asset ? I know there is RawData variable but it is a FByteBulkData and this is not what I am looking for - at least I think so, please prove me wrong. I would like to use this data for example to recreate wave file using default c++ way - of course there are other ways to use this data. Any ideas ? Thanks!

I know this is a little old, but it showed up while I was searching for similar topics. I think it needs a little attention.

I want to point out that the RawData variable you mention is only good in the editor. If thats all you care about, then Inside that variable is the entire sound file byte by byte in PCM format.

If you happened to have found a better way to access audio data, can you please share it? I’m looking for a way to access the same raw audio data after a game has been published. so far what I’ve found is all protected or encoded (compressed) and its quite a pain in the…

I don’t even need the entire file, a small buffer of whats currently playing is perfect for my use.

Well I did it some time ago but its not pretty . First You need to know your uasset (USoundWave) file path. Then You need to phrase it old school byte way:

       fstream myFileAsset;
		myFileAsset.unsetf(ios_base::skipws);		
		myFileAsset.open([full path + .uasset], ios::binary);

		bool bIcan = false;

		char prevByte = ' ';
		char prevErByte = ' ';

		if (myFileAsset.is_open())
		{
			ofstream newWav;
			mkdir([tempFileDir].c_str());
			newWav.open([tempFile].c_str(), ios::binary);

			while (!myFileAsset.eof())
			{
				char byte;
				byte = myFileAsset.get();

				if (byte == 'F' && prevByte == 'I' && prevErByte == 'R' && !bIcan)
				{
					bIcan = true;
					newWav.put(prevErByte);
					newWav.put(prevByte);

				}
				else
				{
					prevErByte = prevByte;
					prevByte = byte;
				}

				if (bIcan)
				{
					newWav.put(byte);
				}
			}

			myFileAsset.close();
			newWav.close();

This way we are getting rid off meta data from uasset and we are getting pure .wav file. Have fun

Do you run this in a packaged build? Are you getting actual pcm data from this? I was pretty sure the engine compresses the files and sends them into the sound system for playback directly (all based on platform) . I’m wondering how this works out.

I finally found a way. Basically, Trying to access already decompressed data in the engine is a no no. It’s all buried deep in the engine in a packaged build. I think the best way is to take the resource data which has raw compressed data (usually OGG vorbis), and have the engine decompress it again into the RawPCMData buffer. then you can access it in a packaged game. I just tried it and it’s actually a super fast process too. The nice part is, when the USoundWave gets destroyed, there is already a check in there to clean up that buffer if it exists. very handy.

Hi xdbxdbx -

Can you post a code snippet of your solution described above? Thanks!!

YEH PLEASE share how you did the decompression cant figure out the correct way :S

Hi, I forgot about this post. Sorry. I’ll be happy to share what I’ve found.
I would love to see what you guys are working on with this stuff.

My experience has been that even after you extract the data it’s still a pain to work with in UE4 because the engine doesnt track song timing well. You might be better off with an external code base to play sound and query every aspect of the sound precicely. I’m a hair away from just writing my own. ie: If you ask the engine for the current sound position, it will not match up with whats playing. its only an approximation which goes out of sync if you so much as click outside the editor / hit a lag spike / or pause the song. I’ll fix it eventually… anywho…

Ive made a few changes since I was last on here. To decompress audio… I keep a variable named AudioSample in my class which is a pointer to the selected USoundWave, I also keep a separate structure in my class called CurrentSongBuffer which I decompress my data to now. the reason being, I found instances where the game would clean up the UWavedata while I was in the middle of reading it (ex: pressing stop in the editor). So I realized what a terrible idea it was to decompress the data it into the USoundwave again. I found that TSharedPtr works wonders for this which is accessed on about 12 different analysis threads. So now I can clean up any time by just picking a new song and letting the old buffer work its way out of my pipeline.

if (AudioAnalysisHelper::DecompressUSoundWave(this->AudioSample, Manager->CurrentSongBuffer))
	{
// ... prep work here or whatever
}

and then, here is that function:

bool AudioAnalysisHelper::DecompressUSoundWave(USoundWave * soundWave, TSharedPtr<SongBufferData> & Out_SongBufferData)
{
	FAudioDevice * audioDevice = GEngine ? GEngine->GetAudioDevice() : nullptr;

	if (!audioDevice)
		return false;

	if (!soundWave)
		return false;

	if (soundWave->GetName() == TEXT("None"))
		return false;

	bool breturn = false;

	// erase whatever was previously here.
	Out_SongBufferData = nullptr;

	// ensure we have the sound data. compressed format is fine
	soundWave->InitAudioResource(audioDevice->GetRuntimeFormat(soundWave));

	// create a decoder for this audio. we want the PCM data.
	ICompressedAudioInfo* AudioInfo = audioDevice->CreateCompressedAudioInfo(soundWave);

	// decompress complete audio to this buffer 
	FSoundQualityInfo QualityInfo = { 0 };
	if (AudioInfo->ReadCompressedInfo(soundWave->ResourceData, soundWave->ResourceSize, &QualityInfo))
	{
		Out_SongBufferData = TSharedPtr<SongBufferData>(new SongBufferData(QualityInfo.SampleDataSize,
			QualityInfo.NumChannels,
			QualityInfo.Duration,
			QualityInfo.SampleRate));

		// Decompress all the sample data into preallocated memory now
		AudioInfo->ExpandFile(Out_SongBufferData->RawPCMData.GetData(), &QualityInfo);

		breturn = true;
	}

	// clean up.
	delete AudioInfo;

	return breturn;
}

and finally,

// This struct contains information about the sound buffer.
struct SongBufferInfo
{
	int32 NumChannels;
	float Duration;
	int32 SampleRate;
	int32 RawPCMDataSize;

	SongBufferInfo()
		: RawPCMDataSize(0), NumChannels(0), Duration(0), SampleRate(0)
	{ }

	SongBufferInfo(int32 PCMDataSize, int32 numChannels, float duration, int32 sampleRate)
		: RawPCMDataSize(PCMDataSize), NumChannels(numChannels), Duration(duration), SampleRate(sampleRate)
	{	}
};

// this struct contains the sound buffer + information about it.
struct SongBufferData
{
	TArray<uint8> RawPCMData;
	SongBufferInfo BufferInfo;

	// default to nothing.
	SongBufferData() : SongBufferData(0, 0, 0, 0) {	}

	// allocate memory as we populate the structure.
	SongBufferData(int32 PCMDataSize, int32 numChannels, float duration, int32 sampleRate)
		: BufferInfo(PCMDataSize, numChannels, duration, sampleRate)
	{
		// create the space
		//RawPCMData = (uint8*)FMemory::Malloc(RawPCMDataSize);
		//RawPCMData = new uint8[PCMDataSize];
		RawPCMData.SetNumZeroed(PCMDataSize);
	}
};

ah yeah, one last note. This WILL decompress an entire soundwave. If you call this in the game thread, expect a small hiccup. For me, a 1 hour long song will take about 10-20 seconds. I recommend a separate thread.

If one of you wants to write a streaming version of this and share it, I would love to have it. :wink:

This is really amazing stuff, thank you so much for posting it!

You say above that the Unreal Engine doesn’t do a good job keeping track of the current play time of the sound. I have two questions regarding that:

  1. How/where can you query the current play time?

  2. Did you ever create a solution for audio playback that bypasses unreal’s setup so that we can get accurate real-time data about the audio?

Thanks so much!

its something like this…

if (GEngine->GetAudioDevice())
		{
			FActiveSound * activeSound = GEngine->GetAudioDevice()->FindActiveSound(AudioPlayer);
			if (activeSound != nullptr)
			{
				CurrentSongPlaybackTime = activeSound->PlaybackTime;
...

Last I checked, it was a float that was incremented by delta time each frame. The right way to do this is to calculate the time based on the position of the read cursor in the actual audio buffer. there is no way that I know to access that.

my audio solution currently for development is to listen to windows stereo mix. that way I can play whatever I want out of winamp and my system will listen in Real-time for analysis. :wink: In the future I hope to integrate things like web radio or maybe even sound cloud streaming and such. To get truly precise data, you have to play the sound yourself unless epic changes the way they track audio time.

Hello everyone! , I know this is very old but I’m really desperate for answers, I’ll be honest, I don’t use unreal engine but I would like to decode .raw files from a 2010 game, the situation that you presented is quite similar to mine, yes anyone Could you help me I would appreciate it, without getting too involved in Unreal, what should I do? Really Thx

Hello everyone! , I know this is very old but I’m really desperate for answers, I’ll be honest, I don’t use unreal engine but I would like to decode .raw files from a 2010 game, the situation that you presented is quite similar to mine, yes anyone Could you help me I would appreciate it, without getting too involved in Unreal, what should I do? Really Thx

Hello,

“raw” files can pretty much be anything so first of all you have to figure out what’s in it.
I would advise you to rely on a hex editor (typically https://awesomeopensource.com/project/WerWolv/ImHex) and try to decode it manually first - is it audio, image data, something else? The header of the file or its FourCC if there is one might give a hint.

Also keep in mind that if it’s compressed or encrypted it will look random and there is not much you can do about it.

Hi,

Just in case someone is still having the problem, I was able to fix it by using the function GetImportedSoundWaveData() and by recreating the header bytes myself.

Please see How to get imported file bytes from USoundWave ? - #4 by xand449.