VoIP 限制 rendercallback 中的帧数

VoIP limiting the number of frames in rendercallback

我目前正在开发一个 VoIP 应用程序,我正在使用的库之一要求我在输入回调中发送帧。要求是我必须发送一个样本计数,该样本计数定义为帧中的样本数。每当麦克风接收新样本时,都会调用此回调。

有效数字为(采样率)*(音频长度)/1000。其中音频长度可以是 2.5、5、10、20、40 或 60 毫秒。

在使用 kAudioUnitProperty_MaximumFramesPerSlice 将我的 inNumberFrames 限制为 960 之前,它一直带来大约 1115 inNumberFrames。所以我决定通过设置 属性 来限制它。但是,当我这样做时,它会将 inNumberFrames 计数减少到 512???我是不是以错误的方式解决了这个问题?

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

您可以(并且应该)使用 kAudioUnitProperty_MaximumFramesPerSlice 来指定每帧的 最大 样本数,而不是 首选 数字;请参考Apple的技术问答QA1533 and QA1606。要设置每帧的首选样本数,请使用 AVAudioSessionsetPreferredIOBufferDuration:error: 方法。比如采样率为32000,可以使用:

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

将帧长度设置为 256,因为 32,000 * 0.008 = 256。

但是请注意,setPreferredIOBufferDuration:error: 方法设置的是 preferred 号码,而不是 exact 号码。您可以向操作系统建议一个帧长度,但有时,由于硬件限制,您可能无法准确获得所需的帧长,而是接近它的值。