Get the audio unit output buffer size and use that as the rendering

quantum, as the callback wants us to provide exactly the amount of
samples needed.

This is incomplete because core audio may ask for less than the full
buffer size (for me, typically 1484 or 1488 bytes of a 2048 byte
buffer). As a quick hack until I read the rather impenetrable core
audio documentation, assume that each callback request will want
about the same number of samples as the preceeding one.

This makes sound bearable.

Also various cleanup.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5543 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Soren Jorvang 2010-05-30 04:21:01 +00:00
parent a88e09edc2
commit 7f50bb5579

View File

@ -17,34 +17,35 @@
#include "CoreAudioSoundStream.h" #include "CoreAudioSoundStream.h"
volatile unsigned int numBytesToRender; /* XXX */
typedef struct internal typedef struct internal
{ {
AudioUnit audioUnit; AudioUnit audioUnit;
short realtimeBuffer[1024 * 1024]; short realtimeBuffer[1024]; /* XXX */
}; };
OSStatus callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
OSStatus callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
UInt32 inNumberFrames, AudioBufferList *ioData)
{
internal *soundStruct = (internal *)inRefCon; internal *soundStruct = (internal *)inRefCon;
for (int i=0; i < (int)ioData->mNumberBuffers; i++) for (int i=0; i < (int)ioData->mNumberBuffers; i++)
{ {
memcpy(ioData->mBuffers[i].mData, &soundStruct->realtimeBuffer, ioData->mBuffers[i].mDataByteSize); memcpy(ioData->mBuffers[i].mData, &soundStruct->realtimeBuffer,
ioData->mBuffers[i].mDataByteSize);
} }
numBytesToRender = ioData->mBuffers[0].mDataByteSize; /* XXX */
return 0; return 0;
} }
void CoreAudioSound::SoundLoop() void CoreAudioSound::SoundLoop()
{ {
CoreAudioInit(); CoreAudioInit();
} }
CoreAudioSound::CoreAudioSound(CMixer *mixer) : SoundStream(mixer) CoreAudioSound::CoreAudioSound(CMixer *mixer) : SoundStream(mixer)
{ {
} }
@ -52,6 +53,7 @@ CoreAudioSound::CoreAudioSound(CMixer *mixer) : SoundStream(mixer)
CoreAudioSound::~CoreAudioSound() CoreAudioSound::~CoreAudioSound()
{ {
} }
bool CoreAudioSound::CoreAudioInit() bool CoreAudioSound::CoreAudioInit()
{ {
ComponentDescription desc; ComponentDescription desc;
@ -59,10 +61,12 @@ bool CoreAudioSound::CoreAudioInit()
UInt32 enableIO; UInt32 enableIO;
AURenderCallbackStruct callback_struct; AURenderCallbackStruct callback_struct;
AudioStreamBasicDescription format; AudioStreamBasicDescription format;
UInt32 numBytesToRender = 512; UInt32 numSamplesPerSlice;
UInt32 numSamplesPerSliceSize = sizeof numSamplesPerSlice;
internal *soundStruct = (internal *)malloc(sizeof(internal)); internal *soundStruct = (internal *)malloc(sizeof(internal));
memset(soundStruct->realtimeBuffer, 0, sizeof(soundStruct->realtimeBuffer)); memset(soundStruct->realtimeBuffer, 0,
sizeof soundStruct->realtimeBuffer);
desc.componentType = kAudioUnitType_Output; desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_HALOutput; desc.componentSubType = kAudioUnitSubType_HALOutput;
@ -72,7 +76,7 @@ bool CoreAudioSound::CoreAudioInit()
Component component = FindNextComponent(NULL, &desc); Component component = FindNextComponent(NULL, &desc);
if (component == NULL) if (component == NULL)
printf("error finding component\n"); printf("error finding audio component\n");
err = OpenAComponent(component, &soundStruct->audioUnit); err = OpenAComponent(component, &soundStruct->audioUnit);
if (err) if (err)
@ -82,41 +86,44 @@ bool CoreAudioSound::CoreAudioInit()
enableIO = 1; enableIO = 1;
AudioUnitSetProperty(soundStruct->audioUnit, AudioUnitSetProperty(soundStruct->audioUnit,
kAudioOutputUnitProperty_EnableIO, kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output, kAudioUnitScope_Output, 0, &enableIO,
0, sizeof enableIO);
&enableIO,
sizeof(enableIO));
//set audio format
format.mBitsPerChannel = 16; FillOutASBDForLPCM(format, m_mixer->GetSampleRate(),
format.mChannelsPerFrame = 2; 2, 16, 16, false, false, false);
format.mBytesPerPacket = 4; err = AudioUnitSetProperty(soundStruct->audioUnit,
format.mBytesPerFrame = 4; kAudioUnitProperty_StreamFormat,
format.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; kAudioUnitScope_Input, 0, &format,
format.mFormatID = kAudioFormatLinearPCM; sizeof(AudioStreamBasicDescription));
format.mFramesPerPacket = 1;
format.mSampleRate = m_mixer->GetSampleRate();
//set format to output scope
err = AudioUnitSetProperty(soundStruct->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof(AudioStreamBasicDescription));
if (err) if (err)
printf("error when setting output format\n"); printf("error setting audio format\n");
callback_struct.inputProc = callback; callback_struct.inputProc = callback;
callback_struct.inputProcRefCon = soundStruct; callback_struct.inputProcRefCon = soundStruct;
err = AudioUnitSetProperty(soundStruct->audioUnit,
err = AudioUnitSetProperty(soundStruct->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &callback_struct, sizeof(callback_struct)); kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &callback_struct,
sizeof callback_struct);
if (err) if (err)
printf("error when setting input callback\n"); printf("error setting audio callback\n");
err = AudioUnitGetProperty(soundStruct->audioUnit,
kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global, 0,
&numSamplesPerSlice, &numSamplesPerSliceSize);
if (err)
printf("error getting audio buffer size\n");
numBytesToRender = numSamplesPerSlice * 4;
err = AudioUnitInitialize(soundStruct->audioUnit); err = AudioUnitInitialize(soundStruct->audioUnit);
if (err) if (err)
printf("error when initiaising audiounit\n"); printf("error initializing audiounit\n");
err = AudioOutputUnitStart(soundStruct->audioUnit); err = AudioOutputUnitStart(soundStruct->audioUnit);
if (err) if (err)
printf("error when starting audiounit\n"); printf("error starting audiounit\n");
do do
{ {
@ -128,19 +135,18 @@ bool CoreAudioSound::CoreAudioInit()
err = AudioOutputUnitStop(soundStruct->audioUnit); err = AudioOutputUnitStop(soundStruct->audioUnit);
if (err) if (err)
printf("error when sopping audiounit\n"); printf("error stopping audiounit\n");
err = AudioUnitUninitialize(soundStruct->audioUnit); err = AudioUnitUninitialize(soundStruct->audioUnit);
if (err) if (err)
printf("Error uninitializing audiounit\n"); printf("error uninitializing audiounit\n");
err = CloseComponent(soundStruct->audioUnit); err = CloseComponent(soundStruct->audioUnit);
if (err) if (err)
printf("Error while closing component\n"); printf("error while closing audio component\n");
free(soundStruct); free(soundStruct);
return true; return true;
} }
void *coreAudioThread(void *args) void *coreAudioThread(void *args)
@ -150,16 +156,13 @@ void *coreAudioThread(void *args)
return NULL; return NULL;
} }
bool CoreAudioSound::Start() bool CoreAudioSound::Start()
{ {
soundSyncEvent.Init(); soundSyncEvent.Init();
thread = new Common::Thread(coreAudioThread, (void *)this); thread = new Common::Thread(coreAudioThread, (void *)this);
return true; return true;
} }
void CoreAudioSound::Stop() void CoreAudioSound::Stop()
{ {
threadData = 1; threadData = 1;
@ -168,10 +171,9 @@ void CoreAudioSound::Stop()
thread = NULL; thread = NULL;
return; return;
} }
void CoreAudioSound::Update() void CoreAudioSound::Update()
{ {
soundSyncEvent.Set(); soundSyncEvent.Set();
} }