AudioKit单轮MIDI播放时分离录制多轨乐器音频的问题
问题解决:AudioKit多MIDISampler分离录制单轨音频
问题根源分析
你遇到的文件数量不足、音频混乱问题,核心原因有两点:
- 文件命名冲突:所有
NodeRecorder使用同一目录但未指定唯一文件名,默认生成的文件名重复导致文件被覆盖,最终只保留部分文件。 - 录制源路由不稳定:直接录制
MIDISampler节点可能存在音频路由同步问题,导致不同轨道的音频串扰。
可行解决方案
核心思路
- 为每个录制轨道分配唯一的输出文件URL,避免文件覆盖。
- 为每个
MIDISampler单独创建AKMixer节点,将Sampler输出接入专属Mixer后再录制,提升音频捕获的稳定性。 - 替换强制
try!为do-catch错误处理,避免潜在崩溃。
修正代码示例
var drumKitSampler: MIDISampler! var bassSampler: MIDISampler! var pianoChordsSampler: MIDISampler! // 加载音色(此处省略你的加载逻辑) // 1. 配置音频路由:为每个Sampler创建专属Mixer let drumMixer = AKMixer(drumKitSampler) let bassMixer = AKMixer(bassSampler) let pianoMixer = AKMixer(pianoChordsSampler) let mainMixer = AKMixer(drumMixer, bassMixer, pianoMixer) AudioKit.output = mainMixer // 启动音频引擎 do { try AudioKit.start() } catch { SLOG("AudioKit启动失败: \(error.localizedDescription)") } // 2. 为每个轨道生成唯一文件URL guard let outputDirURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { SLOG("无法获取输出目录") return } let drumFileURL = outputDirURL.appendingPathComponent("drum_track.caf") let bassFileURL = outputDirURL.appendingPathComponent("bass_track.caf") let pianoFileURL = outputDirURL.appendingPathComponent("piano_track.caf") // 3. 初始化各轨道Recorder,指定专属文件URL var drumRecorder: NodeRecorder? var bassRecorder: NodeRecorder? var pianoRecorder: NodeRecorder? do { drumRecorder = try NodeRecorder(node: drumMixer, fileURL: drumFileURL, shouldCleanupRecordings: false) bassRecorder = try NodeRecorder(node: bassMixer, fileURL: bassFileURL, shouldCleanupRecordings: false) pianoRecorder = try NodeRecorder(node: pianoMixer, fileURL: pianoFileURL, shouldCleanupRecordings: false) } catch { SLOG("Recorder初始化失败: \(error.localizedDescription)") return } // 4. 开始录制并启动MIDI播放 do { try drumRecorder?.record() try bassRecorder?.record() try pianoRecorder?.record() // 此处启动你的MIDI序列播放逻辑 } catch { SLOG("录制启动失败: \(error.localizedDescription)") } // 5. 定时停止录制 DispatchQueue.main.asyncAfter(deadline: .now() + 20) { do { try drumRecorder?.stop() try bassRecorder?.stop() try pianoRecorder?.stop() SLOG("所有轨道录制完成") } catch { SLOG("录制停止失败: \(error.localizedDescription)") } }
关键说明
- 使用专属
AKMixer:每个Sampler的输出先进入独立Mixer,再汇总到主Mixer,既不影响正常播放,又能确保Recorder精准捕获单轨音频,避免串扰。 - 唯一文件URL:通过
appendingPathComponent为每个轨道生成不同的文件名,彻底解决文件覆盖问题。 - 错误处理:所有可能抛出异常的操作都用
do-catch包裹,便于排查问题,避免程序崩溃。
内容的提问来源于stack exchange,提问作者David Songistic
相关产品推荐
相关产品推荐

