Loading audio from file in 5.6

I’m trying to load .wav files at runtime from files on disk, i.e. not packaged by the game. I was using this code, which worked in 5.3:

USoundWave* USoundManager::LoadSoundFromFile(const FString& path) {
	USoundWave* sw = NewObject<USoundWave>(USoundWave::StaticClass());
	TArray<uint8> fileBytes;
	if (!FFileHelper::LoadFileToArray(fileBytes, *path)) {
		UE_LOG(LogTemp, Error, TEXT("Failed to read file at %s!"), *path);
		return sw;
	}

	sw->VirtualizationMode = EVirtualizationMode::PlayWhenSilent;
	// Based heavily on
	// https://forums.unrealengine.com/t/loading-raw-wav-in-runtime-into-usoundwave/126017/6
	FWaveModInfo wavInfo;
	if (!wavInfo.ReadWaveInfo(fileBytes.GetData(), fileBytes.Num())) {
		UE_LOG(LogTemp, Error, TEXT("Couldn't read .wav info from file at %s!"), *path);
		return nullptr;
	}
	sw->GetRuntimeFormat();
	sw->SetSampleRate(*wavInfo.pSamplesPerSec);
	sw->NumChannels = *wavInfo.pChannels;
	const auto bytesPerSec = *wavInfo.pChannels * (*wavInfo.pBitsPerSample / 8.0) * (*wavInfo.pSamplesPerSec);
	if (bytesPerSec > .01) {
		sw->Duration = wavInfo.SampleDataSize / bytesPerSec;
	}
	sw->RawPCMDataSize = wavInfo.SampleDataSize;
	sw->RawPCMData = static_cast<uint8*>(FMemory::Malloc(wavInfo.SampleDataSize));
	FMemory::Memcpy(sw->RawPCMData, wavInfo.SampleDataStart, wavInfo.SampleDataSize);
	return sw;
}

In 5.6, while this code still runs, the sounds refuse to play. I get this warning in the log: “FMixerBuffer::CreateStreamingBuffer failed to StreamCompressedInfo on SoundWave ‘SoundWave_210’. Invalidating wave resource data (asset now requires re-cook).” Digging into the engine code, the issue appears to be that the USoundWave’s “SoundWaveDataPtr” property is not being initialized. That causes the engine to think that the sound has an invalid format. However, all code paths that I can find that actually write to “SoundWaveDataPtr” appear to be editor-only, and it’s a private property.

I haven’t had any luck figuring out what changed between 5.3 and 5.6 to break my code. Does anyone have any advice for how to get my C++ runtime audio loading working? I know that there’s a “Runtime Audio Importer” plugin, but it’s expensive, and I don’t really want to splash out a couple hundred bucks if it turns out that my problem is just that I need to set another property on my USoundWave, or something like that.

Thanks for your time!

EDIT: I figured out how to get runtime-loaded sounds working IN THE EDITOR, but not in packaged builds. This code, inserted at the end of the above function, will make the sounds work, but the RawData property and PostImport function appear to be editor-only, and thus if you include calls to them in your game code, it won’t package properly.

	// Some magic that I'm trying to get sounds to work in 5.6...
	sw->RawData.UpdatePayload(FSharedBuffer::Clone(fileBytes.GetData(), fileBytes.Num()));
	sw->SetImportedSampleRate(*wavInfo.pSamplesPerSec);
	sw->SetSampleRate(*wavInfo.pSamplesPerSec);
	sw->NumChannels = *wavInfo.pChannels;
	sw->TotalSamples = *wavInfo.pSamplesPerSec * sw->Duration;
	sw->InvalidateCompressedData(true);
	sw->LoadZerothChunk();
	sw->PostImport();

Surely it can’t be this complicated to just load a .wav file from disk so you can play it? Surely?