You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#codereview Marc.Audy, Mike.Fricker #lockdown Zachary.EdgertonJones [CL 2522019 by Dmitry Rekman in Main branch]
210 lines
5.8 KiB
C++
210 lines
5.8 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "ALAudioDevice.h"
|
|
#include "AudioEffect.h"
|
|
#include "Engine.h"
|
|
#include "IAudioFormat.h"
|
|
#include "AudioDecompress.h"
|
|
#include "ContentStreaming.h"
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
FALSoundBuffer.
|
|
------------------------------------------------------------------------------------*/
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param AudioDevice audio device this sound buffer is going to be attached to.
|
|
*/
|
|
FALSoundBuffer::FALSoundBuffer( FALAudioDevice* InAudioDevice )
|
|
: FSoundBuffer(InAudioDevice)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* 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 = CreateNativeBuffer(AudioDevice, InWave);
|
|
}
|
|
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;
|
|
}
|
|
|
|
FALSoundBuffer* FALSoundBuffer::CreateNativeBuffer( FALAudioDevice* AudioDevice, USoundWave* Wave)
|
|
{
|
|
SCOPE_CYCLE_COUNTER( STAT_AudioResourceCreationTime );
|
|
|
|
// Check to see if thread has finished decompressing on the other thread
|
|
if (Wave->AudioDecompressor)
|
|
{
|
|
Wave->AudioDecompressor->EnsureCompletion();
|
|
|
|
// Remove the decompressor
|
|
delete Wave->AudioDecompressor;
|
|
Wave->AudioDecompressor = nullptr;
|
|
}
|
|
|
|
// Can't create a buffer without any source data
|
|
if (Wave == nullptr)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
if (Wave->NumChannels == 0)
|
|
{
|
|
UE_LOG(LogALAudio, Warning, TEXT("ALSoundBuffer: cannot create buffer for wave '%s' with 0 channels"),
|
|
*Wave->GetName());
|
|
return nullptr;
|
|
}
|
|
|
|
Wave->InitAudioResource(AudioDevice->GetRuntimeFormat(Wave));
|
|
FALSoundBuffer* Buffer = nullptr;
|
|
|
|
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
|
|
check(AudioDeviceManager != nullptr);
|
|
|
|
// Find the existing buffer if any
|
|
if (Wave->ResourceID)
|
|
{
|
|
Buffer = static_cast<FALSoundBuffer*>(AudioDeviceManager->WaveBufferMap.FindRef(Wave->ResourceID));
|
|
}
|
|
|
|
if (Buffer == nullptr)
|
|
{
|
|
// Create new buffer.
|
|
Buffer = new FALSoundBuffer(AudioDevice);
|
|
|
|
alGenBuffers(1, &Buffer->BufferId);
|
|
AudioDevice->alError(TEXT("RegisterSound"));
|
|
|
|
AudioDeviceManager->TrackResource(Wave, Buffer);
|
|
|
|
Buffer->InternalFormat = AudioDevice->GetInternalFormat(Wave->NumChannels);
|
|
Buffer->NumChannels = Wave->NumChannels;
|
|
Buffer->SampleRate = Wave->SampleRate;
|
|
|
|
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
|
|
uint8* SoundData = reinterpret_cast<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;
|
|
}
|
|
}
|
|
|
|
return Buffer;
|
|
}
|