我们有一个通信应用程序,已经超过8年了,现在在IOS平台上,最近我们遇到了一个问题,在新的iPhone 14。
我们将音频会话类别AVAudioSessionCategoryPlayAndRecord与AVAudioSessionMode语音聊天配合使用。我们还将使用kAudioUnitSubType_VoiceProcessingIO组件。
CoreAudio设置的一部分将回调大小设置如下:
NSTimeInterval desiredBufferDuration = .02;
BOOL prefResult = [session setPreferredIOBufferDuration:desiredBufferDuration error:&nsError];
然后,当使用返回请求缓冲持续时间时
NSTimeInterval actualBufferDuration = [session IOBufferDuration];
型
我们得到预期的.0213333,即48 kHz时的1024个样本。
在音频回调中,我们总是收到1024个样本。在回调中,我们只记录提供的样本数,如下所示:
static OSStatus inputAudioCallback (void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
NSLog (@"A %d", inNumberFrames);
}
代码被简化了,但是你明白了。
在iPhone 14以外的任何硬件设备上,我们每次从这个日志语句中得到1024。
在iPhone14上,我们得到如下序列:
A 960(6次)
阿1440
A 960(7次)
阿1440
它会重复。这本身并不会引起任何问题,但是我们也会在回调过程中拉入麦克风。下面是音频回调中的简化代码:
renderErr = AudioUnitRender(ioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, myIOData);
简单调用,但通常在960/1440转换时,AudioUnitRender会为最后一个960和1440回调返回kAudioUnitErr_CannotDoInCurrentContext。
这会导致麦克风数据丢失,从而导致音频中出现爆音/毛刺。
如果我们切换到使用kAudioUnitSubType_RemoteIO子类型,我们每次回调都能可靠地获得1024个样本,并且AudioUnitRender函数每次都能正确工作。问题是我们无法消除回声,因此在此模式下使用手持设备毫无价值。
因此,问题是,iPhone 14是否发生了严重变化,在使用kAudioUnitySubType_VoiceProcessingIO时,在音频回调期间调用AudioUnitRender?这绝对不是IOS 16错误,因为iPhone 13或支持IOS 16的早期型号没有任何问题。
事实上,我们没有得到1024个样本在一个时间种告诉我们的东西是真的错了,但这段代码已经正确地工作了多年,现在是真正的行为在iPhone 14上时髦。
1条答案
按热度按时间ovfsdjhp1#
我们这边也遇到了同样的问题。我们认为这是Apple的问题,因为正如您所说,据我们所知,此API没有任何变化。它应该是与kAudioUnitSubType_VoiceProcessingIO音频单元交互的有效方式。
作为一种解决方案,我们决定尝试使用kAudioOutputUnitProperty_SetInputCallback属性注册另一个回调以进行捕捉,该属性与我们使用kAudioUnitProperty_SetRenderCallback设置的属性(之前将同时处理渲染和捕捉)放在一起。
然后,
captureCallback
调用AudioUnitRender并将数据复制到缓冲区中:下面是我们如何在IosAudioUnit构造函数中设置bufferList:
渲染回调和新的捕捉回调在iPhone 14上仍然是以960和1440的样本大小调用的,但AudioUnit似乎处理得更好,音频中不再有爆裂/小故障!
希望这有帮助!