使用AudioKit录音并播放音频时出现高频反馈的技术求助
问题根源
你的代码中,AudioKit的AudioEngine将处理后的音频(经PitchShifter)直接输出到扬声器,同时AVPlayer也在播放音频。麦克风会拾取扬声器发出的所有声音(包括AudioEngine输出的处理后音频和AVPlayer的播放音频),重新输入到AudioEngine中形成闭环反馈回路,最终放大产生高频噪音。而单独使用AVAudioRecorder时,仅录制麦克风输入,没有将处理后的音频输出到扬声器,因此不会触发反馈。
具体修复方案
1. 切断AudioEngine到扬声器的输出路由
你仅需要录制处理后的音频文件,无需实时播放处理结果,因此可以移除AudioEngine到硬件扬声器的输出连接:
init() { guard let input = engine.input else { return } pitchShiftEffect = PitchShifter(input) // 移除 engine.output = pitchShiftEffect 这一行 }
这样AudioEngine仅处理音频数据并通过tap写入文件,不会将处理后的声音输出到扬声器,从源头避免麦克风拾取反馈信号。
2. 优化音频会话配置,启用系统回声消除
调整音频会话参数,开启系统自带的回声消除和噪音抑制功能,进一步降低反馈风险:
private func handleAudioSessionCategory() { let session = AVAudioSession.sharedInstance() do { let options: AVAudioSession.CategoryOptions if UIDevice.primaryAudioDevice == .defaultSpeakers { options = [.defaultToSpeaker, .allowBluetooth, .enableSpokenAudio] try Settings.setSession(category: .playAndRecord, with: options) } else { options = [.enableSpokenAudio] try Settings.setSession(category: .playAndRecord, mode: .videoRecording, with: options) } try session.setCategory(.playAndRecord, mode: .videoRecording, options: options) try session.setActive(true) } catch { print("Audio session configuration failed: \(error.localizedDescription)") } }
注:enableSpokenAudio会启用系统的回声消除与噪音抑制,对降低播放-录制串扰有明显帮助。
3. 调整Tap安装时机与错误处理
当前代码在引擎启动后才安装tap,可能导致初始音频流异常。建议先安装tap再启动引擎,同时替换try!为try?避免崩溃:
func start(baseNote: Note) { handleAudioSessionCategory() pitchDetectionService.start { data in self.autoCorrectPitch(data, baseNote: baseNote) } // 先安装Tap再启动引擎 engine.input?.avAudioNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, time in try? self.unprocessedAudioFile?.write(from: buffer) } pitchShiftEffect.avAudioNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, time in try? self.processedAudioFile?.write(from: buffer) } try? engine.start() }
注:直接对pitchShiftEffect节点安装tap,替代原engine.output的tap,避免因移除engine.output导致tap失效。
4. 限制极端音高偏移参数
检查autoCorrectPitch逻辑,避免设置极端的pitchRatio值。过度极端的音高偏移会生成失真的高频信号,更容易触发反馈循环。确保变调范围控制在合理区间(比如±12半音内)。
5. 扬声器播放时的额外防护
如果必须在扬声器播放AVPlayer音频,可进一步降低AVPlayer音量(当前已设置为0.01,可尝试更低),或在扬声器模式下完全禁止AudioEngine的音频输出(仅录制原始输入)。
内容的提问来源于stack exchange,提问作者Sotiris Kaniras

