2014-03-14 14:13:41 -04:00
|
|
|
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
/*=============================================================================
|
|
|
|
|
IOSAudioBuffer.cpp: Unreal IOSAudio buffer interface object.
|
|
|
|
|
=============================================================================*/
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
|
|
|
Includes
|
|
|
|
|
------------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
#include "IOSAudioDevice.h"
|
|
|
|
|
#include "AudioEffect.h"
|
|
|
|
|
#include "Engine.h"
|
|
|
|
|
#include "IAudioFormat.h"
|
|
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
|
|
|
FIOSAudioSoundBuffer
|
|
|
|
|
------------------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
FIOSAudioSoundBuffer::FIOSAudioSoundBuffer(FIOSAudioDevice* InAudioDevice, ESoundFormat InSoundFormat):
|
|
|
|
|
FSoundBuffer(),
|
|
|
|
|
SoundFormat(InSoundFormat),
|
|
|
|
|
SampleData(NULL),
|
|
|
|
|
SampleRate(0),
|
|
|
|
|
CompressedBlockSize(0),
|
|
|
|
|
UncompressedBlockSize(0),
|
|
|
|
|
BufferSize(0)
|
|
|
|
|
{
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FIOSAudioSoundBuffer::~FIOSAudioSoundBuffer(void)
|
|
|
|
|
{
|
|
|
|
|
if (bAllocationInPermanentPool)
|
|
|
|
|
{
|
|
|
|
|
UE_LOG(LogIOSAudio, Fatal, TEXT("Can't free resource '%s' as it was allocated in permanent pool."), *ResourceName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FMemory::Free(SampleData);
|
|
|
|
|
SampleData = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32 FIOSAudioSoundBuffer::GetSize(void)
|
|
|
|
|
{
|
|
|
|
|
int32 TotalSize = 0;
|
|
|
|
|
|
|
|
|
|
switch (SoundFormat)
|
|
|
|
|
{
|
|
|
|
|
case SoundFormat_LPCM:
|
|
|
|
|
case SoundFormat_ADPCM:
|
|
|
|
|
TotalSize = BufferSize;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TotalSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FIOSAudioSoundBuffer* FIOSAudioSoundBuffer::CreateNativeBuffer(FIOSAudioDevice* IOSAudioDevice, USoundWave* InWave)
|
|
|
|
|
{
|
|
|
|
|
FWaveModInfo WaveInfo;
|
|
|
|
|
|
2014-06-09 11:13:16 -04:00
|
|
|
InWave->InitAudioResource(IOSAudioDevice->GetRuntimeFormat(InWave));
|
2014-03-14 14:13:41 -04:00
|
|
|
if (!InWave->ResourceData || InWave->ResourceSize <= 0 || !WaveInfo.ReadWaveInfo(InWave->ResourceData, InWave->ResourceSize))
|
|
|
|
|
{
|
|
|
|
|
InWave->RemoveAudioResource();
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 UncompressedBlockSize = 0;
|
|
|
|
|
uint32 CompressedBlockSize = 0;
|
|
|
|
|
const uint32 PreambleSize = 7;
|
|
|
|
|
const uint32 BlockSize = *WaveInfo.pBlockAlign;
|
|
|
|
|
|
|
|
|
|
switch (*WaveInfo.pFormatTag)
|
|
|
|
|
{
|
|
|
|
|
case SoundFormat_ADPCM:
|
|
|
|
|
// (BlockSize - PreambleSize) * 2 (samples per byte) + 2 (preamble samples)
|
|
|
|
|
UncompressedBlockSize = (2 + (BlockSize - PreambleSize) * 2) * sizeof(int16);
|
|
|
|
|
CompressedBlockSize = BlockSize;
|
|
|
|
|
|
|
|
|
|
if ((WaveInfo.SampleDataSize % CompressedBlockSize) != 0)
|
|
|
|
|
{
|
|
|
|
|
InWave->RemoveAudioResource();
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case SoundFormat_LPCM:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create new buffer
|
|
|
|
|
FIOSAudioSoundBuffer* Buffer = new FIOSAudioSoundBuffer(IOSAudioDevice, static_cast<ESoundFormat>(*WaveInfo.pFormatTag));
|
|
|
|
|
|
|
|
|
|
Buffer->NumChannels = InWave->NumChannels;
|
|
|
|
|
Buffer->SampleRate = InWave->SampleRate;
|
|
|
|
|
Buffer->UncompressedBlockSize = UncompressedBlockSize;
|
|
|
|
|
Buffer->CompressedBlockSize = CompressedBlockSize;
|
|
|
|
|
Buffer->BufferSize = WaveInfo.SampleDataSize;
|
|
|
|
|
|
|
|
|
|
Buffer->SampleData = static_cast<int16*>(FMemory::Malloc(Buffer->BufferSize));
|
|
|
|
|
FMemory::Memcpy(Buffer->SampleData, WaveInfo.SampleDataStart, Buffer->BufferSize);
|
|
|
|
|
|
|
|
|
|
IOSAudioDevice->TrackResource(InWave, Buffer);
|
|
|
|
|
InWave->RemoveAudioResource();
|
|
|
|
|
|
|
|
|
|
return Buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FIOSAudioSoundBuffer* FIOSAudioSoundBuffer::Init(FIOSAudioDevice* IOSAudioDevice, USoundWave* InWave)
|
|
|
|
|
{
|
|
|
|
|
// Can't create a buffer without any source data
|
|
|
|
|
if (InWave == NULL || InWave->NumChannels == 0)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FIOSAudioSoundBuffer *Buffer = NULL;
|
|
|
|
|
|
|
|
|
|
switch (static_cast<EDecompressionType>(InWave->DecompressionType))
|
|
|
|
|
{
|
|
|
|
|
case DTYPE_Setup:
|
|
|
|
|
// Has circumvented pre-cache mechanism - pre-cache now
|
|
|
|
|
IOSAudioDevice->Precache(InWave, true, false);
|
|
|
|
|
|
|
|
|
|
// Recall this function with new decompression type
|
|
|
|
|
return Init(IOSAudioDevice, InWave);
|
|
|
|
|
|
|
|
|
|
case DTYPE_Native:
|
|
|
|
|
if (InWave->ResourceID)
|
|
|
|
|
{
|
|
|
|
|
Buffer = static_cast<FIOSAudioSoundBuffer*>(IOSAudioDevice->WaveBufferMap.FindRef(InWave->ResourceID));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Buffer)
|
|
|
|
|
{
|
|
|
|
|
Buffer = CreateNativeBuffer(IOSAudioDevice, 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
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Buffer;
|
|
|
|
|
}
|