AudioQueue播放PCM与192kHz/24bit音频混音时出现0.5秒静音问题
使用AudioQueue播放24kHz 16bit格式的PCM文件,同时与192kHz 24bit的sound2音频混音。AVAudioSession配置如下:
- Category:
AVAudioSessionCategoryPlayback - Options:
AVAudioSessionCategoryOptionMixWithOthers|AVAudioSessionCategoryOptionDuckOthers
按预期,播放PCM时sound2应自动降低音量,但实际情况是sound2在降音量前会出现0.5秒的完全静音,之后才输出降音量后的声音。该问题仅在sound2为192kHz 24bit音质时出现,降低其音质则一切正常,最终sound2确实会按设置降低音量。
这一问题的核心是高采样率音频的实时重采样延迟:当系统触发DuckOthers逻辑时,需要将192kHz 24bit的sound2实时转换为与AudioQueue播放的PCM一致的采样率(24kHz),这个格式转换的初始化过程需要额外时间,导致短暂静音后才完成降音处理。低采样率音频的转换开销极低,因此不会出现明显延迟。
1. 预转换sound2采样率
将192kHz 24bit的sound2预先转换为与AudioQueue播放的PCM相同的采样率(24kHz),或系统通用的采样率(如44.1kHz/48kHz),避免系统实时重采样的等待。可以通过AudioConverterRef(AudioToolbox框架)或AVAssetReader/AVAssetWriter完成离线转换。
2. 手动实现Duck逻辑
取消AVAudioSessionCategoryOptionDuckOthers选项,改为手动控制sound2的音量变化:
- 确保sound2的播放器(如AVPlayer)保留音量控制权限
- 在AudioQueue开始播放PCM的回调中,通过线性渐变的方式降低sound2的音量(比如0.1秒内从原音量降到目标降音量)
- PCM播放结束后,再线性恢复sound2的原音量
3. 提前激活AudioSession
在启动AudioQueue播放前,提前激活AVAudioSession,给系统足够时间完成音频格式适配:
AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *error; [session setCategory:AVAudioSessionCategoryPlayback options:AVAudioSessionCategoryOptionMixWithOthers|AVAudioSessionCategoryOptionDuckOthers error:&error]; [session activateWithOptions:AVAudioSessionActivateOptionNotifyOthersOnDeactivation error:&error]; // 提前100ms启动AudioQueue,给系统预留适配时间 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 启动AudioQueue播放PCM的代码 });
4. 优化sound2播放器配置
如果sound2使用AVPlayer,关闭自动等待最小化卡顿的选项,强制播放器提前加载音频数据:
AVPlayer *sound2Player = [[AVPlayer alloc] initWithURL:sound2URL]; sound2Player.automaticallyWaitsToMinimizeStalling = NO;
内容的提问来源于stack exchange,提问作者yuanjilee

