You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AudioKit单轮MIDI播放时分离录制多轨乐器音频的问题

问题解决:AudioKit多MIDISampler分离录制单轨音频

问题根源分析

你遇到的文件数量不足、音频混乱问题,核心原因有两点:

  1. 文件命名冲突:所有NodeRecorder使用同一目录但未指定唯一文件名,默认生成的文件名重复导致文件被覆盖,最终只保留部分文件。
  2. 录制源路由不稳定:直接录制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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:57:25