VoIP limiting the number of frames in rendercallback

584 views Asked by At

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;
}
1

There are 1 answers

0
ycsun On BEST ANSWER

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 the setPreferredIOBufferDuration:error: method of AVAudioSession. For example, if the sample rate is 32,000, you can use:

NSError *error = nil;
NSTimeInterval bufferDuration = 0.008;
[session setPreferredIOBufferDuration:bufferDuration error:&error];

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.