Files
UnrealEngineUWP/Engine/Source/Runtime/ALAudio/Private/ALAudioBuffer.cpp
bob tellez 73f3d19f1f Back out changelist 11119764, 11119772, 11119809, 11119849, 11121802, 11125895, 11124508. AutoTest assert
[FYI] Rob.Gay


#ROBOMERGE-SOURCE: CL 11125898 via CL 11126424
#ROBOMERGE-BOT: (v640-11091645)

[CL 11126508 by bob tellez in Main branch]
2020-01-28 05:18:04 -05:00

183 lines
5.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CoreMinimal.h"
#include "Stats/Stats.h"
#include "Audio.h"
#include "ALAudioDevice.h"
#include "AudioDecompress.h"
/*------------------------------------------------------------------------------------
FALSoundBuffer.
------------------------------------------------------------------------------------*/
/**
* Constructor
*
* @param AudioDevice audio device this sound buffer is going to be attached to.
*/
FALSoundBuffer::FALSoundBuffer( FALAudioDevice* InAudioDevice )
: FSoundBuffer(InAudioDevice),
BufferId(0)
{
}
/**
* Destructor
*
* Frees wave data and detaches itself from audio device.
*/
FALSoundBuffer::~FALSoundBuffer( void )
{
// Delete AL buffers.
alDeleteBuffers(1, &BufferId);
}
/**
* Static function used to create a buffer.
*
* @param InWave USoundNodeWave to use as template and wave source
* @param AudioDevice audio device to attach created buffer to
* @param bIsPrecacheRequest Whether this request is for precaching or not
* @return FALSoundBuffer pointer if buffer creation succeeded, NULL otherwise
*/
FALSoundBuffer* FALSoundBuffer::Init(FALAudioDevice* AudioDevice, USoundWave* InWave)
{
// Can't create a buffer without any source data
if (InWave == nullptr || InWave->NumChannels == 0)
{
return nullptr;
}
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
check(AudioDeviceManager != nullptr);
FALSoundBuffer *Buffer = nullptr;
switch (static_cast<EDecompressionType>(InWave->DecompressionType))
{
case DTYPE_Setup:
// Has circumvented pre-cache mechanism - pre-cache now
AudioDevice->Precache(InWave, true, false);
// Recall this function with new decompression type
return Init(AudioDevice, InWave);
case DTYPE_Native:
if (InWave->ResourceID)
{
Buffer = static_cast<FALSoundBuffer*>(AudioDeviceManager->WaveBufferMap.FindRef(InWave->ResourceID));
}
if (!Buffer || !Buffer->BufferId)
{
CreateNativeBuffer(AudioDevice, InWave, Buffer);
}
break;
// Always create a new buffer for streaming ogg vorbis data
//Buffer = CreateQueuedBuffer(AudioDevice, InWave);
//break;
case DTYPE_Invalid:
case DTYPE_Preview:
case DTYPE_Procedural:
case DTYPE_RealTime:
default:
// Invalid will be set if the wave cannot be played
UE_LOG(LogALAudio, Warning, TEXT("ALSoundBuffer wave '%s' has an invalid decompression type %d."),
*InWave->GetName(), static_cast<EDecompressionType>(InWave->DecompressionType));
break;
}
if (Buffer == nullptr)
{
UE_LOG(LogALAudio, Warning, TEXT("ALSoundBuffer init failed for wave '%s', decompression type %d."),
*InWave->GetName(), static_cast<EDecompressionType>(InWave->DecompressionType));
}
return Buffer;
}
void FALSoundBuffer::CreateNativeBuffer(FALAudioDevice* AudioDevice, USoundWave* Wave, FALSoundBuffer* &Buffer)
{
// Check if Buffer already exists
if (Buffer)
{
// Assign the new AudioDevice
Buffer->AudioDevice = AudioDevice;
}
else
{
SCOPE_CYCLE_COUNTER( STAT_AudioResourceCreationTime );
check(Wave->GetPrecacheState() == ESoundWavePrecacheState::Done);
// Create new buffer.
Buffer = new FALSoundBuffer(AudioDevice);
Buffer->InternalFormat = AudioDevice->GetInternalFormat(Wave->NumChannels);
Buffer->NumChannels = Wave->NumChannels;
Buffer->SampleRate = Wave->GetSampleRateForCurrentPlatform();
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
check(AudioDeviceManager != nullptr);
AudioDeviceManager->TrackResource(Wave, Buffer);
}
// Generate the new OpenAL buffer
alGenBuffers(1, &Buffer->BufferId);
AudioDevice->alError(TEXT("RegisterSound"));
if (Wave->RawPCMData)
{
// upload it
Buffer->BufferSize = Wave->RawPCMDataSize;
alBufferData(Buffer->BufferId, Buffer->InternalFormat, Wave->RawPCMData, Wave->RawPCMDataSize, Buffer->SampleRate);
// Free up the data if necessary
if (Wave->bDynamicResource)
{
FMemory::Free( Wave->RawPCMData );
Wave->RawPCMData = nullptr;
Wave->bDynamicResource = false;
}
}
else
{
// get the raw data
const uint8* SoundData = reinterpret_cast<const uint8*>(Wave->RawData.Lock(LOCK_READ_ONLY));
// it's (possibly) a pointer to a wave file, so skip over the header
int SoundDataSize = Wave->RawData.GetBulkDataSize();
// is there a wave header?
FWaveModInfo WaveInfo;
if (WaveInfo.ReadWaveInfo(SoundData, SoundDataSize))
{
// if so, modify the location and size of the sound data based on header
SoundData = WaveInfo.SampleDataStart;
SoundDataSize = WaveInfo.SampleDataSize;
}
// let the Buffer know the final size
Buffer->BufferSize = SoundDataSize;
// upload it
alBufferData( Buffer->BufferId, Buffer->InternalFormat, SoundData, Buffer->BufferSize, Buffer->SampleRate );
// unload it
Wave->RawData.Unlock();
}
if (AudioDevice->alError(TEXT( "RegisterSound (buffer data)")) || (Buffer->BufferSize == 0))
{
Buffer->InternalFormat = 0;
}
if (Buffer->InternalFormat == 0)
{
UE_LOG(LogAudio, Log,TEXT( "Audio: sound format not supported for '%s' (%d)" ), *Wave->GetName(), Wave->NumChannels);
UE_LOG(LogALAudio, Warning, TEXT("ALSoundBuffer: sound format not supported for wave '%s'"), *Wave->GetName());
delete Buffer;
Buffer = nullptr;
}
}