如何足够准确地同步两个音乐序列 (Audiokit.AKAppleSequencer)?

How to sync accurately enough two music sequences (Audiokit.AKAppleSequencer)?

我有 2 个音序器:

let sequencer1 = AKAppleSequencer(filename: "filename1")
let sequencer2 = AKAppleSequencer(filename: "filename2")

两者的 bpm 值相同。

sequencer1 开始播放一个 midi 曲目(只播放一次)时,我需要 sequencer2 在第一个音序器完成后开始播放。我怎样才能做到这一点? 请注意,sequencer2 已循环。

目前我有这种方法,但不够准确:

let callbackInstrument = AKMIDICallbackInstrument(midiInputName: "callbackInstrument", callback: nil)
let callbackTrack = sequencer1.newTrack()!
callbackTrack.setMIDIOutput(callbackInstrument.midiIn)

let beatsCount = sequencer1.length.beats

callbackTrack.add(noteNumber: MIDINoteNumber(beatsCount),
    velocity: 1,
    position: AKDuration(beats: beatsCount),
    duration: AKDuration(beats: 0.1))

callbackInstrument.callback = { status, _, _ in
    guard AKMIDIStatusType.from(byte: status) == .noteOn else { return }
    DispatchQueue.main.async { self.sequencer2.play() }//not accurate
}

let sampler = AKMIDISampler(midiOutputName: nil)
sequencer1.tracks[0].setMIDIOutput(sampler.midiIn)

感谢任何想法。

Apple 的 MusicSequenceAKAppleSequencer 的基础,它总是在启动后的前 100 毫秒左右出现时间错误。这是封闭源代码中的一个已知问题,永远不会修复。这里有两种可能的解决方法。

  1. 使用新的AKSequencer。它可能足以使这项工作准确(但不保证)。下面是使用 AKSequencerAKCallbackInstrument 的示例:

  2. 使用单个 AKAppleSequencer,但将 'sequencer2' 内容放在 'sequencer1' 内容之后。你不能自动循环它,但你可以从你的回调函数中重复 re-write 它(或者 pre-write 它 300 次或类似的东西)。根据我的经验,在播放时将 MIDI 写入 AKAppleSequencer 是没有问题的。示例应用程序 https://github.com/AudioKit/MIDIFileEditAndSync 包含时移 MIDI 音符数据的示例,可用于完成此操作。