iOS VoIP应用中接近传感器触发导致Audio Unit回调inNumberFrames异常求助
解决Linphone SDK iOS应用中接近传感器导致Audio Unit帧大小变化的问题
我之前也碰到过类似的Audio Unit和接近传感器交互的坑,结合你描述的情况,给你几个具体的排查和解决方向:
1. 监听路由变化,重新锁定帧大小参数
接近传感器触发时,系统会自动切换音频路由(扬声器→听筒),哪怕你没手动切换设备,系统也可能隐性重置Audio Unit的参数。你可以在路由变化时重新强制设置帧相关属性:
首先注册路由变化通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAudioRouteChange:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];
然后在回调里重新设置参数:
- (void)handleAudioRouteChange:(NSNotification *)notification { AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *error; // 重新设置偏好的buffer时长(对应256帧,按44.1kHz采样率计算) NSTimeInterval targetDuration = 256.0 / 44100.0; [session setPreferredIOBufferDuration:targetDuration error:&error]; // 重新设置Audio Unit的最大帧切片和固定帧切片 UInt32 framesPerSlice = 256; AudioUnitSetProperty(card->io_unit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &framesPerSlice, sizeof(framesPerSlice)); // 尝试设置固定帧切片(部分Audio Unit支持) AudioUnitSetProperty(card->io_unit, kAudioUnitProperty_FramesPerSlice, kAudioUnitScope_Global, 0, &framesPerSlice, sizeof(framesPerSlice)); }
2. 在渲染回调内部适配帧大小变化
如果系统还是强制改变inNumberFrames,可以在回调里把大帧拆分成Linphone需要的256帧块处理,避免破坏缓冲策略:
static OSStatus au_write_cb ( void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData ) { LinphoneAudioCard *card = (LinphoneAudioCard *)inRefCon; const UInt32 targetFrames = 256; UInt32 remainingFrames = inNumberFrames; int16_t *sourceBuffer = (int16_t *)ioData->mBuffers[0].mData; while (remainingFrames > 0) { UInt32 processFrames = MIN(remainingFrames, targetFrames); // 截取对应帧的数据,喂给Linphone的音频输入逻辑 linphone_audio_card_write(card, sourceBuffer, processFrames); sourceBuffer += processFrames; remainingFrames -= processFrames; } return noErr; }
3. 检查Linphone SDK的音频配置
Linphone本身有自己的音频缓冲管理,你可以尝试强制设置SDK的音频缓冲大小:
// 设置Linphone的音频缓冲大小(单位毫秒,对应256帧≈5.8ms) linphone_core_set_audio_buffer_size(lc, 6);
另外可以查看Linphone的LinphoneAudioConfiguration相关API,有没有强制固定输入帧大小的选项。
4. 对比Speakerbox的细节差异
苹果Speakerbox Demo能保持帧大小稳定,大概率是它在路由变化时做了参数重置,或者Audio Session的配置更严谨:
- 确认你的Audio Session Category设置正确:VoIP应用必须用
AVAudioSessionCategoryPlayAndRecord,并且要添加AVAudioSessionCategoryOptionAllowBluetooth和AVAudioSessionCategoryOptionDefaultToSpeaker选项; - 检查Speakerbox的
setupAudioSession方法,它是否在初始化时就严格锁定了buffer时长,并且在路由变化时重新确认参数; - 注意Speakerbox是否禁用了音频会话的自动配置,比如没有设置
AVAudioSessionCategoryOptionMixWithOthers这类可能导致参数波动的选项。
内容的提问来源于stack exchange,提问作者steven
相关产品推荐
相关产品推荐

