We are using the AudioUnits input callback to process the incoming buffer. The audio unit setup is taken mostly from
https://github.com/robovm/apple-ios-samples/blob/master/aurioTouch/Classes/AudioController.mm
I have added some sanity check in the audio callback. It looks like this
/// The audio input callback
static OSStatus audioInputCallback(void __unused *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 __unused inBusNumber,
UInt32 inNumberFrames,
AudioBufferList __unused *ioData)
{
OSStatus err = noErr;
if(!*callbackData.audioChainIsBeingReconstructed)
{
// we are calling AudioUnitRender on the input bus of AURemoteIO
// this will store the audio data captured by the microphone in cd.audioBufferList
err = AudioUnitRender(callbackData.audioUnit, ioActionFlags, inTimeStamp, kInputBus, inNumberFrames, &callbackData.audioBufferList);
// check if the sample count is set correctly
assert(callbackData.audioBufferList.mBuffers[0].mDataByteSize == inNumberFrames * sizeof(float));
// Assert that we only received one buffer
assert(callbackData.audioBufferList.mNumberBuffers == 1);
// Copy buffer
TPCircularBufferCopyAudioBufferList(callbackData.buffer, &callbackData.audioBufferList, inTimeStamp, kTPCircularBufferCopyAll, NULL);
}
return err;
}
Now sometimes the statement assert(callbackData.audioBufferList.mBuffers[0].mDataByteSize == inNumberFrames * sizeof(float));
fails as the buffers are not the same.
Does anybody have an explanation to this phenomena?
This is normal behavior on iOS. An iOS Audio Unit callback can change the number of frames provided in the buffer size, to be different from the original buffer size. This can happen when the OS state changes, or when the audio hardware state changes, or when the hardware format available doesn't exactly match your audio format request.
So all Audio Unit callbacks must be written to handle a variable number of inNumberFrames from the requested value, or the previous callback value.