#include "oalOSX.h"
#define LOG_RING_BUFFER 0
#pragma mark ***** UTILITY *****
uintptr_t GetNewPtrToken (void)
{
static uintptr_t currentToken = 24;
uintptr_t returnedToken;
returnedToken = currentToken;
currentToken++;
return (returnedToken);
}
ALuint GetNewToken (void)
{
static ALuint currentToken = 2400;
ALuint returnedToken;
returnedToken = currentToken;
currentToken++;
return (returnedToken);
}
const char kPathDelimiter[] = "/";
const UInt32 kPathDelimiterLength = 1;
bool IsRelativePath(const char* inPath)
{
return inPath[0] != kPathDelimiter[0];
}
void MakeAbsolutePath(const char* inRelativePath, char* outAbsolutePath, UInt32 inMaxAbsolutePathLength)
{
getcwd(outAbsolutePath, inMaxAbsolutePathLength);
if ((strlen(outAbsolutePath) + kPathDelimiterLength) <= inMaxAbsolutePathLength - 1)
{
strcat(outAbsolutePath, kPathDelimiter);
if ((strlen(outAbsolutePath) + strlen(inRelativePath)) <= inMaxAbsolutePathLength - 1)
{
strcat(outAbsolutePath, inRelativePath);
}
}
}
UInt32 GetOALFormatFromASBD(CAStreamBasicDescription &inASBD)
{
switch (inASBD.mFormatID)
{
case kAudioFormatLinearPCM:
if (inASBD.mFormatFlags & kAudioFormatFlagIsFloat)
{
if (inASBD.NumberChannels() == 1 && inASBD.mBitsPerChannel == 32)
{
if(alIsExtensionPresent("AL_EXT_float32"))
return alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
}
if (inASBD.NumberChannels() == 2 && inASBD.mBitsPerChannel == 32)
{
if(alIsExtensionPresent("AL_EXT_float32"))
return alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
}
}
else
{
if (inASBD.NumberChannels() == 1 && inASBD.mBitsPerChannel == 16)
return AL_FORMAT_MONO16;
else if (inASBD.NumberChannels() == 2 && inASBD.mBitsPerChannel == 16)
return AL_FORMAT_STEREO16;
else if (inASBD.NumberChannels() == 1 && inASBD.mBitsPerChannel == 8)
return AL_FORMAT_MONO8;
else if (inASBD.NumberChannels() == 2 && inASBD.mBitsPerChannel == 8)
return AL_FORMAT_STEREO8;
}
break;
default:
return (0);
break;
}
return (0);
}
const char* GetFormatString(UInt32 inToken)
{
switch(inToken)
{
case AL_FORMAT_MONO16:
return "16-Bit/Mono";
break;
case AL_FORMAT_STEREO16:
return "16-Bit/Stereo";
break;
case AL_FORMAT_MONO8:
return "8-Bit/Mono";
break;
case AL_FORMAT_STEREO8:
return "8-Bit/Stereo";
break;
}
return "UNKNOWN FORMAT";
}
const char* GetALAttributeString(UInt32 inToken)
{
switch(inToken)
{
case AL_SOURCE_RELATIVE: return "AL_SOURCE_RELATIVE"; break;
case AL_CONE_INNER_ANGLE: return "AL_CONE_INNER_ANGLE"; break;
case AL_CONE_OUTER_ANGLE: return "AL_CONE_OUTER_ANGLE"; break;
case AL_CONE_OUTER_GAIN: return "AL_CONE_OUTER_GAIN"; break;
case AL_PITCH: return "AL_PITCH"; break;
case AL_POSITION: return "AL_POSITION"; break;
case AL_DIRECTION: return "AL_DIRECTION"; break;
case AL_VELOCITY: return "AL_VELOCITY"; break;
case AL_LOOPING: return "AL_LOOPING"; break;
case AL_BUFFER: return "AL_BUFFER"; break;
case AL_GAIN: return "AL_GAIN"; break;
case AL_MIN_GAIN: return "AL_MIN_GAIN"; break;
case AL_MAX_GAIN: return "AL_MAX_GAIN"; break;
case AL_ORIENTATION: return "AL_ORIENTATION"; break;
case AL_REFERENCE_DISTANCE: return "AL_REFERENCE_DISTANCE"; break;
case AL_ROLLOFF_FACTOR: return "AL_ROLLOFF_FACTOR"; break;
case AL_MAX_DISTANCE: return "AL_MAX_DISTANCE"; break;
case AL_SOURCE_STATE: return "AL_SOURCE_STATE"; break;
case AL_BUFFERS_QUEUED: return "AL_BUFFERS_QUEUED"; break;
case AL_BUFFERS_PROCESSED: return "AL_BUFFERS_PROCESSED"; break;
case AL_SEC_OFFSET: return "AL_SEC_OFFSET"; break;
case AL_SAMPLE_OFFSET: return "AL_SAMPLE_OFFSET"; break;
case AL_BYTE_OFFSET: return "AL_BYTE_OFFSET"; break;
case AL_SOURCE_TYPE: return "AL_SOURCE_TYPE"; break;
case AL_NONE: return "AL_NONE"; break;
case AL_INVERSE_DISTANCE: return "AL_INVERSE_DISTANCE"; break;
case AL_INVERSE_DISTANCE_CLAMPED: return "AL_INVERSE_DISTANCE_CLAMPED"; break;
case AL_LINEAR_DISTANCE: return "AL_LINEAR_DISTANCE"; break;
case AL_LINEAR_DISTANCE_CLAMPED: return "AL_LINEAR_DISTANCE_CLAMPED"; break;
case AL_EXPONENT_DISTANCE: return "AL_EXPONENT_DISTANCE"; break;
case AL_EXPONENT_DISTANCE_CLAMPED: return "AL_EXPONENT_DISTANCE_CLAMPED"; break;
case AL_INVALID_NAME: return "AL_INVALID_NAME"; break;
}
return "UNKNOWN ATTRIBUTE - WARNING WARNING WARNING";
}
const char* GetALCAttributeString(UInt32 inToken)
{
switch(inToken)
{
case ALC_DEFAULT_DEVICE_SPECIFIER: return "ALC_DEFAULT_DEVICE_SPECIFIER"; break;
case ALC_DEVICE_SPECIFIER: return "ALC_DEVICE_SPECIFIER"; break;
case ALC_EXTENSIONS: return "ALC_EXTENSIONS"; break;
case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: return "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER"; break;
case ALC_CAPTURE_DEVICE_SPECIFIER: return "ALC_CAPTURE_DEVICE_SPECIFIER"; break;
case ALC_NO_ERROR: return "ALC_NO_ERROR"; break;
case ALC_INVALID_DEVICE: return "ALC_INVALID_DEVICE"; break;
case ALC_INVALID_CONTEXT: return "ALC_INVALID_CONTEXT"; break;
case ALC_INVALID_ENUM: return "ALC_INVALID_ENUM"; break;
case ALC_INVALID_VALUE: return "ALC_INVALID_VALUE"; break;
case ALC_ASA_REVERB_ON: return "ALC_ASA_REVERB_ON"; break;
case ALC_ASA_REVERB_ROOM_TYPE: return "ALC_ASA_REVERB_ROOM_TYPE"; break;
case ALC_ASA_REVERB_SEND_LEVEL: return "ALC_ASA_REVERB_SEND_LEVEL"; break;
case ALC_ASA_REVERB_GLOBAL_LEVEL: return "ALC_ASA_REVERB_GLOBAL_LEVEL"; break;
case ALC_ASA_OCCLUSION: return "ALC_ASA_OCCLUSION"; break;
case ALC_ASA_ROGER_BEEP_ENABLE: return "ALC_ASA_ROGER_BEEP_ENABLE"; break;
case ALC_ASA_ROGER_BEEP_ON: return "ALC_ASA_ROGER_BEEP_ON"; break;
case ALC_ASA_ROGER_BEEP_GAIN: return "ALC_ASA_ROGER_BEEP_GAIN"; break;
case ALC_ASA_ROGER_BEEP_SENSITIVITY: return "ALC_ASA_ROGER_BEEP_SENSITIVITY"; break;
case ALC_ASA_ROGER_BEEP_TYPE: return "ALC_ASA_ROGER_BEEP_TYPE"; break;
case ALC_ASA_ROGER_BEEP_PRESET: return "ALC_ASA_ROGER_BEEP_PRESET"; break;
case ALC_ASA_DISTORTION_ENABLE: return "ALC_ASA_DISTORTION_ENABLE"; break;
case ALC_ASA_DISTORTION_ON: return "ALC_ASA_DISTORTION_ON"; break;
case ALC_ASA_DISTORTION_MIX: return "ALC_ASA_DISTORTION_MIX"; break;
case ALC_ASA_DISTORTION_TYPE: return "ALC_ASA_DISTORTION_TYPE"; break;
case ALC_ASA_DISTORTION_PRESET: return "ALC_ASA_DISTORTION_PRESET"; break;
}
return "UNKNOWN ATTRIBUTE - WARNING WARNING WARNING";
}
bool IsValidRenderQuality (UInt32 inRenderQuality)
{
switch (inRenderQuality)
{
case ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_HIGH:
case ALC_MAC_OSX_SPATIAL_RENDERING_QUALITY_LOW:
return (true);
break;
default:
return (false);
break;
}
return (false);
}
bool IsFormatSupported(UInt32 inFormatID)
{
switch(inFormatID)
{
case AL_FORMAT_MONO16:
case AL_FORMAT_STEREO16:
case AL_FORMAT_MONO8:
case AL_FORMAT_STEREO8:
return true;
break;
case AL_FORMAT_MONO_FLOAT32:
case AL_FORMAT_STEREO_FLOAT32:
return alIsExtensionPresent("AL_EXT_float32");
break;
default:
return false;
break;
}
return false;
}
OSStatus FillInASBD(CAStreamBasicDescription &inASBD, UInt32 inFormatID, UInt32 inSampleRate)
{
OSStatus err = noErr;
switch (inFormatID)
{
case AL_FORMAT_STEREO16:
inASBD.mSampleRate = inSampleRate * 1.0;
inASBD.mFormatID = kAudioFormatLinearPCM;
inASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
inASBD.mBytesPerPacket = 4;
inASBD.mBytesPerFrame = 4;
inASBD.mFramesPerPacket = 1;
inASBD.mBitsPerChannel = 16;
inASBD.mChannelsPerFrame = 2;
inASBD.mReserved = 0;
break;
case AL_FORMAT_MONO16:
inASBD.mSampleRate = inSampleRate * 1.0;
inASBD.mFormatID = kAudioFormatLinearPCM;
inASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
inASBD.mBytesPerPacket = 2;
inASBD.mBytesPerFrame = 2;
inASBD.mFramesPerPacket = 1;
inASBD.mBitsPerChannel = 16;
inASBD.mChannelsPerFrame = 1;
inASBD.mReserved = 0;
break;
case AL_FORMAT_STEREO8:
inASBD.mSampleRate = inSampleRate * 1.0;
inASBD.mFormatID = kAudioFormatLinearPCM;
inASBD.mFormatFlags = kAudioFormatFlagIsPacked;
inASBD.mBytesPerPacket = 2;
inASBD.mBytesPerFrame = 2;
inASBD.mFramesPerPacket = 1;
inASBD.mBitsPerChannel = 8;
inASBD.mChannelsPerFrame = 2;
inASBD.mReserved = 0;
break;
case AL_FORMAT_MONO8 :
inASBD.mSampleRate = inSampleRate * 1.0;
inASBD.mFormatID = kAudioFormatLinearPCM;
inASBD.mFormatFlags = kAudioFormatFlagIsPacked;
inASBD.mBytesPerPacket = 1;
inASBD.mBytesPerFrame = 1;
inASBD.mFramesPerPacket = 1;
inASBD.mBitsPerChannel = 8;
inASBD.mChannelsPerFrame = 1;
inASBD.mReserved = 0;
break;
case AL_FORMAT_STEREO_FLOAT32 :
inASBD.mSampleRate = inSampleRate * 1.0;
inASBD.mFormatID = kAudioFormatLinearPCM;
inASBD.mFormatFlags = kLinearPCMFormatFlagIsFloat;
inASBD.mBytesPerPacket = 8;
inASBD.mBytesPerFrame = 8;
inASBD.mFramesPerPacket = 1;
inASBD.mBitsPerChannel = 32;
inASBD.mChannelsPerFrame = 2;
inASBD.mReserved = 0;
break;
case AL_FORMAT_MONO_FLOAT32 :
inASBD.mSampleRate = inSampleRate * 1.0;
inASBD.mFormatID = kAudioFormatLinearPCM;
inASBD.mFormatFlags = kLinearPCMFormatFlagIsFloat;
inASBD.mBytesPerPacket = 4;
inASBD.mBytesPerFrame = 4;
inASBD.mFramesPerPacket = 1;
inASBD.mBitsPerChannel = 32;
inASBD.mChannelsPerFrame = 1;
inASBD.mReserved = 0;
break;
default:
err = AL_INVALID_VALUE;
break;
}
return (err);
}
void GetDefaultDeviceName(ALCchar* outDeviceName, bool isInput)
{
UInt32 size = 0;
OSStatus result = noErr;
UInt32 deviceProperty = isInput ? kAudioHardwarePropertyDefaultInputDevice : kAudioHardwarePropertyDefaultOutputDevice;
try {
AudioDeviceID defaultDevice = 0;
size = sizeof(defaultDevice);
result = AudioHardwareGetProperty(deviceProperty, &size, &defaultDevice);
THROW_RESULT
result = AudioDeviceGetPropertyInfo( defaultDevice, 0, false, kAudioDevicePropertyDeviceName, &size, NULL);
THROW_RESULT
if (size > maxLen)
throw -1;
size = maxLen;
result = AudioDeviceGetProperty(defaultDevice, 0, false, kAudioDevicePropertyDeviceName, &size, outDeviceName);
THROW_RESULT
} catch (...) {
outDeviceName[0] = '\0'; }
return;
}
UInt32 CalculateNeededMixerBusses(const ALCint *attrList, UInt32 inDefaultBusCount)
{
UInt32 monoSources = 0;
UInt32 stereoSources = 0;
UInt32 returnValue = inDefaultBusCount; ALCint* currentAttribute = ( ALCint*) attrList;
if (attrList)
{
while (*currentAttribute != 0)
{
switch (*currentAttribute)
{
case ALC_MONO_SOURCES:
monoSources = currentAttribute[1];
break;
case ALC_STEREO_SOURCES:
stereoSources = currentAttribute[1];
break;
default:
break;
}
currentAttribute += 2;
}
if (monoSources == 0 && stereoSources == 0)
returnValue = inDefaultBusCount;
else if ((monoSources + stereoSources > kDefaultMaximumMixerBusCount) || (monoSources + stereoSources > inDefaultBusCount))
returnValue = monoSources + stereoSources;
}
return returnValue;
}
UInt32 GetDesiredRenderChannelsFor3DMixer(UInt32 inDeviceChannels)
{
UInt32 returnValue = inDeviceChannels;
if ((Get3DMixerVersion() < k3DMixerVersion_2_0) && (returnValue == 4))
{
returnValue = 2;
}
else if (inDeviceChannels < 4)
{
returnValue = 2;
}
else if ((inDeviceChannels > 5) && (Get3DMixerVersion() < k3DMixerVersion_2_3))
{
returnValue = 5;
}
else if (inDeviceChannels > 8)
{
returnValue = 8;
}
return returnValue;
}
#pragma mark ***** DEPRECATED ALUT *****
#ifdef __cplusplus
extern "C" {
#endif
#define ALUTAPI
#define ALUTAPIENTRY
ALUTAPI ALvoid ALUTAPIENTRY alutInit(ALint *argc,ALbyte **argv);
ALUTAPI ALvoid ALUTAPIENTRY alutExit(void);
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq);
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq);
ALUTAPI ALvoid ALUTAPIENTRY alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq);
typedef struct
{
ALubyte Id[4];
ALsizei Size;
ALubyte Type[4];
} WAVFileHdr_Struct;
typedef struct
{
ALushort Format;
ALushort Channels;
ALuint SamplesPerSec;
ALuint BytesPerSec;
ALushort BlockAlign;
ALushort BitsPerSample;
} WAVFmtHdr_Struct;
typedef struct
{
ALushort Size;
ALushort SamplesPerBlock;
} WAVFmtExHdr_Struct;
typedef struct
{
ALuint Manufacturer;
ALuint Product;
ALuint SamplePeriod;
ALuint Note;
ALuint FineTune;
ALuint SMPTEFormat;
ALuint SMPTEOffest;
ALuint Loops;
ALuint SamplerData;
struct
{
ALuint Identifier;
ALuint Type;
ALuint Start;
ALuint End;
ALuint Fraction;
ALuint Count;
} Loop[1];
} WAVSmplHdr_Struct;
typedef struct
{
ALubyte Id[4];
ALuint Size;
} WAVChunkHdr_Struct;
void SwapWords(unsigned int *puint);
void SwapBytes(unsigned short *pshort);
void SwapWords(unsigned int *puint)
{
unsigned int tempint;
char *pChar1, *pChar2;
tempint = *puint;
pChar2 = (char *)&tempint;
pChar1 = (char *)puint;
pChar1[0]=pChar2[3];
pChar1[1]=pChar2[2];
pChar1[2]=pChar2[1];
pChar1[3]=pChar2[0];
}
void SwapBytes(unsigned short *pshort)
{
unsigned short tempshort;
char *pChar1, *pChar2;
tempshort = *pshort;
pChar2 = (char *)&tempshort;
pChar1 = (char *)pshort;
pChar1[0]=pChar2[1];
pChar1[1]=pChar2[0];
}
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq)
{
WAVChunkHdr_Struct ChunkHdr;
WAVFmtExHdr_Struct FmtExHdr;
WAVFileHdr_Struct FileHdr;
WAVSmplHdr_Struct SmplHdr;
WAVFmtHdr_Struct FmtHdr;
ALbyte *Stream;
*format=AL_FORMAT_MONO16;
*data=NULL;
*size=0;
*freq=22050;
if (memory)
{
Stream=memory;
if (Stream)
{
memcpy(&FileHdr,Stream,sizeof(WAVFileHdr_Struct));
Stream+=sizeof(WAVFileHdr_Struct);
SwapWords((unsigned int*) &FileHdr.Size);
FileHdr.Size=((FileHdr.Size+1)&~1)-4;
while ((FileHdr.Size!=0)&&(memcpy(&ChunkHdr,Stream,sizeof(WAVChunkHdr_Struct))))
{
Stream+=sizeof(WAVChunkHdr_Struct);
SwapWords(&ChunkHdr.Size);
if ((ChunkHdr.Id[0] == 'f') && (ChunkHdr.Id[1] == 'm') && (ChunkHdr.Id[2] == 't') && (ChunkHdr.Id[3] == ' '))
{
memcpy(&FmtHdr,Stream,sizeof(WAVFmtHdr_Struct));
SwapBytes(&FmtHdr.Format);
if (FmtHdr.Format==0x0001)
{
SwapBytes(&FmtHdr.Channels);
SwapBytes(&FmtHdr.BitsPerSample);
SwapWords(&FmtHdr.SamplesPerSec);
SwapBytes(&FmtHdr.BlockAlign);
*format=(FmtHdr.Channels==1?
(FmtHdr.BitsPerSample==8?AL_FORMAT_MONO8:AL_FORMAT_MONO16):
(FmtHdr.BitsPerSample==8?AL_FORMAT_STEREO8:AL_FORMAT_STEREO16));
*freq=FmtHdr.SamplesPerSec;
Stream+=ChunkHdr.Size;
}
else
{
memcpy(&FmtExHdr,Stream,sizeof(WAVFmtExHdr_Struct));
Stream+=ChunkHdr.Size;
}
}
else if ((ChunkHdr.Id[0] == 'd') && (ChunkHdr.Id[1] == 'a') && (ChunkHdr.Id[2] == 't') && (ChunkHdr.Id[3] == 'a'))
{
if (FmtHdr.Format==0x0001)
{
*size=ChunkHdr.Size;
if(*data == NULL){
*data=malloc(ChunkHdr.Size + 31);
memset(*data,0,ChunkHdr.Size+31);
}
else{
realloc(*data,ChunkHdr.Size + 31);
memset(*data,0,ChunkHdr.Size+31);
}
if (*data)
{
memcpy(*data,Stream,ChunkHdr.Size);
memset(((char *)*data)+ChunkHdr.Size,0,31);
Stream+=ChunkHdr.Size;
if (FmtHdr.BitsPerSample == 16)
{
for (UInt32 i = 0; i < (ChunkHdr.Size / 2); i++)
{
SwapBytes(&(*(unsigned short **)data)[i]);
}
}
}
}
else if (FmtHdr.Format==0x0011)
{
}
else if (FmtHdr.Format==0x0055)
{
}
}
else if ((ChunkHdr.Id[0] == 's') && (ChunkHdr.Id[1] == 'm') && (ChunkHdr.Id[2] == 'p') && (ChunkHdr.Id[3] == 'l'))
{
memcpy(&SmplHdr,Stream,sizeof(WAVSmplHdr_Struct));
Stream+=ChunkHdr.Size;
}
else Stream+=ChunkHdr.Size;
Stream+=ChunkHdr.Size&1;
FileHdr.Size-=(((ChunkHdr.Size+1)&~1)+8);
}
}
}
}
ALUTAPI ALvoid ALUTAPIENTRY alutInit(ALint *argc,ALbyte **argv)
{
ALCcontext *Context;
ALCdevice *Device;
Device=alcOpenDevice(NULL);
if (Device != NULL) {
Context=alcCreateContext(Device,0);
if (Context != NULL) {
alcMakeContextCurrent(Context); }
}
}
ALUTAPI ALvoid ALUTAPIENTRY alutExit(void)
{
ALCcontext *Context;
ALCdevice *Device;
Context=alcGetCurrentContext();
Device=alcGetContextsDevice(Context);
alcDestroyContext(Context);
alcCloseDevice(Device);
}
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq)
{
OSStatus err = noErr;
AudioFileID audioFile = 0;
FSRef fsRef;
*data = NULL;
if (IsRelativePath(file))
{
char absolutePath[256];
MakeAbsolutePath(file, absolutePath, 256);
err = FSPathMakeRef ((const UInt8 *) absolutePath, &fsRef, NULL);
}
else
err = FSPathMakeRef ((const UInt8 *) file, &fsRef, NULL);
if (err == noErr)
{
err = AudioFileOpen(&fsRef, fsRdPerm, 0, &audioFile);
if (err == noErr)
{
UInt32 dataSize;
CAStreamBasicDescription asbd;
dataSize = sizeof(CAStreamBasicDescription);
AudioFileGetProperty(audioFile, kAudioFilePropertyDataFormat, &dataSize, &asbd);
*format = GetOALFormatFromASBD(asbd);
if (IsFormatSupported(*format))
{
*freq = (UInt32) asbd.mSampleRate;
SInt64 audioDataSize = 0;
dataSize = sizeof(audioDataSize);
err = AudioFileGetProperty(audioFile, kAudioFilePropertyAudioDataByteCount, &dataSize, &audioDataSize);
if (err == noErr)
{
*size = audioDataSize;
*data = NULL;
*data = calloc(1, audioDataSize);
if (*data)
{
dataSize = audioDataSize;
err = AudioFileReadBytes(audioFile, false, 0, &dataSize, *data);
#if TARGET_RT_BIG_ENDIAN
if ((asbd.mFormatID == kAudioFormatLinearPCM) && (asbd.mBitsPerChannel > 8))
{
AudioConverterRef converter;
CAStreamBasicDescription outFormat = asbd;
void * tempData = NULL;
outFormat.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
tempData = calloc(1 , audioDataSize);
err = AudioConverterNew(&asbd, &outFormat, &converter);
if ((err == noErr) && (tempData != NULL))
{
UInt32 bufferSize = audioDataSize;
err = AudioConverterConvertBuffer(converter, audioDataSize, *data, &bufferSize, tempData);
if (err == noErr)
memcpy(*data, tempData, audioDataSize);
AudioConverterDispose(converter);
}
if (tempData) free (tempData);
}
#endif // TARGET_RT_BIG_ENDIAN
}
}
}
err = AudioFileClose(audioFile);
}
}
else
alSetError(err);
}
ALUTAPI ALvoid ALUTAPIENTRY alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq)
{
if (data)
free(data);
}
AL_API ALvoid AL_APIENTRY alInit(ALint *argc, ALubyte **argv)
{
}
AL_API ALvoid AL_APIENTRY alExit(void)
{
}
#ifdef __cplusplus
}
#endif
#pragma mark ***** OALRingBuffer *****
static __inline__ int CountLeadingZeroes(int arg) {
#if TARGET_CPU_X86 || TARGET_CPU_X86_64
__asm__ volatile(
"bsrl %0, %0\n\t"
"movl $63, %%ecx\n\t"
"cmove %%ecx, %0\n\t"
"xorl $31, %0"
: "=r" (arg)
: "0" (arg)
);
#elif TARGET_CPU_PPC || TARGET_CPU_PPC64
__asm__ volatile("cntlzw %0, %1" : "=r" (arg) : "r" (arg));
#else
#error "ERROR - assembly instructions for counting leading zeroes not present"
#endif
return arg;
}
inline UInt32 Log2Ceil(UInt32 x)
{
return 32 - CountLeadingZeroes(x - 1);
}
inline UInt32 NextPowerOfTwo(UInt32 x)
{
return 1L << Log2Ceil(x);
}
OALRingBuffer::OALRingBuffer() : mBuffer(NULL), mCapacityFrames(0), mCapacityBytes(0)
{
}
OALRingBuffer::OALRingBuffer(UInt32 bytesPerFrame, UInt32 capacityFrames) :
mBuffer(NULL)
{
Allocate(bytesPerFrame, capacityFrames);
}
OALRingBuffer::~OALRingBuffer()
{
Deallocate();
}
void OALRingBuffer::Allocate(UInt32 bytesPerFrame, UInt32 capacityFrames)
{
Deallocate();
mBytesPerFrame = bytesPerFrame;
mCapacityFrames = capacityFrames;
mCapacityBytes = bytesPerFrame * capacityFrames;
mBuffer = (Byte *)malloc(mCapacityBytes);
Clear();
}
void OALRingBuffer::Deallocate()
{
if (mBuffer) {
free(mBuffer);
mBuffer = NULL;
}
mCapacityBytes = 0;
mCapacityFrames = 0;
Clear();
}
void OALRingBuffer::Clear()
{
if (mBuffer)
memset(mBuffer, 0, mCapacityBytes);
mStartOffset = 0;
mStartFrame = 0;
mEndFrame = 0;
}
bool OALRingBuffer::Store(const Byte *data, UInt32 nFrames, SInt64 startFrame)
{
if (nFrames > mCapacityFrames) return false;
SInt64 endFrame = startFrame + nFrames;
if (startFrame >= mEndFrame + mCapacityFrames)
Clear();
if (mStartFrame == 0) {
mStartOffset = 0;
mStartFrame = startFrame;
mEndFrame = endFrame;
memcpy(mBuffer, data, nFrames * mBytesPerFrame);
} else {
UInt32 offset0, offset1, nBytes;
if (endFrame > mEndFrame) {
if (startFrame > mEndFrame) {
offset0 = FrameOffset(mEndFrame);
offset1 = FrameOffset(startFrame);
if (offset0 < offset1)
memset(mBuffer + offset0, 0, offset1 - offset0);
else {
nBytes = mCapacityBytes - offset0;
memset(mBuffer + offset0, 0, nBytes);
memset(mBuffer, 0, offset1);
}
}
mEndFrame = endFrame;
SInt64 newStart = mEndFrame - mCapacityFrames;
if (newStart > mStartFrame) {
mStartOffset = (mStartOffset + (newStart - mStartFrame) * mBytesPerFrame) % mCapacityBytes;
mStartFrame = newStart;
}
}
offset0 = FrameOffset(startFrame);
offset1 = FrameOffset(endFrame);
if (offset0 < offset1)
memcpy(mBuffer + offset0, data, offset1 - offset0);
else {
nBytes = mCapacityBytes - offset0;
memcpy(mBuffer + offset0, data, nBytes);
memcpy(mBuffer, data + nBytes, offset1);
}
}
return true;
}
OSStatus OALRingBuffer::Fetch(Byte *data, UInt32 nFrames, SInt64 startFrame)
{
SInt64 endFrame = startFrame + nFrames;
if (startFrame < mStartFrame || endFrame > mEndFrame) {
return -1;
}
UInt32 offset0 = FrameOffset(startFrame);
UInt32 offset1 = FrameOffset(endFrame);
if (offset0 < offset1)
memcpy(data, mBuffer + offset0, offset1 - offset0);
else {
UInt32 nBytes = mCapacityBytes - offset0;
memcpy(data, mBuffer + offset0, nBytes);
memcpy(data + nBytes, mBuffer, offset1);
}
return noErr;
}
Byte * OALRingBuffer::GetFramePtr(SInt64 frameNumber, UInt32 &outNFrames)
{
if (frameNumber < mStartFrame || frameNumber >= mEndFrame) {
outNFrames = 0;
return NULL;
}
UInt32 offset0 = FrameOffset(frameNumber);
UInt32 offset1 = FrameOffset(mEndFrame);
if (offset0 < offset1) {
outNFrames = mEndFrame - frameNumber;
} else {
outNFrames = (mCapacityBytes - offset0) / mBytesPerFrame;
}
return mBuffer + offset0;
}