I am currently developing a VoIP application and one of the libraries I am using requires me to send the frames in the input call back. The requirements is that I must send a sample count which is defined as the number of samples in a frame. This callback will get called whenever the microphone takes in new samples.
Valid numbers are (sample rate) * (audio length) / 1000. Where audio length can be 2.5, 5, 10, 20, 40 or 60 millseconds.
Before using kAudioUnitProperty_MaximumFramesPerSlice to limit my inNumberFrames to 960, it was bringing in consistently around 1115 inNumberFrames. So I decided to limit it by setting that property. However when I do, it brings the inNumberFrames count down to 512??? Am I approaching this problem the wrong way?
static OSStatus inputRenderCallBack(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames, //512
AudioBufferList *ioData)
{
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = kNumberOfChannels;
bufferList.mBuffers[0].mData = NULL;
bufferList.mBuffers[0].mDataByteSize = inNumberFrames * sizeof(SInt16) * kNumberOfChannels;
OCTAudioEngine *engine = (__bridge OCTAudioEngine *)(inRefCon);
OSStatus status = AudioUnitRender(engine.ioUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
&bufferList);
NSError *error;
[engine.toxav sendAudioFrame:bufferList.mBuffers[0].mData
sampleCount:kSampleCount //960
channels:kNumberOfChannels //2
sampleRate:[engine currentAudioSampleRate] //24000
toFriend:engine.friendNumber
error:&error];
return status;
}
You can (and should) use
kAudioUnitProperty_MaximumFramesPerSlice
to specify the maximum number of samples per frame, not the preferred number; please refer to Apple's Technical Q&A QA1533 and QA1606. To set the preferred number of samples per frame, use thesetPreferredIOBufferDuration:error:
method ofAVAudioSession
. For example, if the sample rate is 32,000, you can use:to set your frame length to 256, because 32,000 * 0.008 = 256.
Note, however, that the
setPreferredIOBufferDuration:error:
method sets the preferred number, not the exact number. You can suggest a frame length to the operating system, but sometimes, due to hardware limits, you may not get exactly what you want, but something close to it instead.