2

该主题已被多次讨论,并且我已在以前的应用程序中成功地使用了AKMIDICallbackInstrument旧的 a。AKAppleSequencer

我开始使用新的AKSequencer,这绝对是惊人的:优雅的界面,易于使用。但是,我一生无法弄清楚如何用它处理回调事件。我需要使用回调来触发基于音序器播放的 GUI 事件。

这是我的示例代码:

    private func setMetronome(bpm: BPM, beats:Int)
    {
        sequencer = AKSequencer(targetNode: metronomeSampler)
        sequencer.tempo = bpm
        sequencer.loopEnabled = false
        sequencer.length = Double(beats)

        metroCallback.callback = {status, noteNumber, velocity in
            if let midiStatus = AKMIDIStatus(byte: status), midiStatus.type != .noteOn { return }

            //Do callback stuff here
        }

        let metroCallbackTrack = sequencer.addTrack(for: metroCallback)

        for i in 0..<beats
        {
            if i == 0
            {
                sequencer.add(noteNumber: MIDINoteNumber(67), position: Double(i), duration: 1.0)
                metroCallbackTrack.add(noteNumber: MIDINoteNumber(67), position: Double(i), duration: 1.0)
            }
            else if (i % 4 == 0)
            {
                sequencer.add(noteNumber: MIDINoteNumber(67), position: Double(i), duration: 1.0)
                metroCallbackTrack.add(noteNumber: MIDINoteNumber(60), position: Double(i), duration: 1.0)
            }
            else
            {
                sequencer.add(noteNumber: MIDINoteNumber(60), position: Double(i), duration: 1.0)
                metroCallbackTrack.add(noteNumber: MIDINoteNumber(60), position: Double(i), duration: 1.0)
            }
            print("seq count:\(i)")
        }

        for track in sequencer.tracks
        {
            print("Adding track to mixer:\(track.length)")
            track >>> mixer
        }
    }

这段代码正确地创建了一系列节拍,它通过我的一切都在世界上进行n回放。AKSampler除了没有回调事件发生(使用打印语句确认)

思考过程

使用AKAppleSequencerAKMIDICallbackInstrument,您可以globalMIDIOutput使用AKAppleSequencer的 MIDI 输入来设置AKMIDICallBackInstrument

现在新的AKSequencerAKCallbackInstrument没有这些选项,新的也没有AKSequencerTrack(旧的AKAppleSequencer将使用AKMusicTrack可以设置 midi 输入/输出的对象)。在查看 new 的实现时AKSequencer,它是由AKNode对象驱动的,AKCallbackInstrument 一个AKNode对象,并且应该能够由具有正确 midi 数据的轨道驱动。

我将轨道添加到我的音序器,并从该轨道中添加必要的 midi 数据,这些数据完全复制了我想要回调的 midi 事件并执行我的 GUI 事件。但是,使用这种方法,它似乎不会调用回调。

有谁知道如何通过回调使用这些新组件?我真的不想回去,AKAppleSequencer除非显然没有办法用新的AKSequencer.

4

2 回答 2

8

AKCallbackInstrument使用新的AKSequencer,请尝试将您的回调仪器连接到您的输出,例如,

metroCallback >>> mixer

不明显,但对我有用。

编辑:包括新的最小工作AKSequencer版本AKCallbackInstrument

class SequencerWrapper {
    var seq: AKSequencer!
    var cbInst: AKCallbackInstrument!
    var mixer: AKMixer!

    init() {
        mixer = AKMixer()
        AudioKit.output = mixer
        seq = AKSequencer()
        cbInst = AKCallbackInstrument()

        // set up a track
        let track = seq.addTrack(for: cbInst)
        for i in 0 ..< 4 {
            track.add(noteNumber: 60, position: Double(i), duration: 0.5)
        }
        track.length = 4.0
        track.loopEnabled = true
        track >>> mixer  // must send track to mixer

        // set up the callback instrument
        cbInst.callback = { status, note, vel in
            guard let status = AKMIDIStatus(byte: status),
                let type = status.type,
                type == .noteOn else { return }
            print("note on: \(note)")
            // trigger sampler etc from here
        }
        cbInst >>> mixer // must send callbackInst to mixer
    }

    func play() {
        seq.playFromStart()
    }
}
于 2020-05-01T15:23:01.573 回答
3

感谢@c_booth 的工作示例!只是想为像我这样无法弄清楚上述示例为什么不起作用的傻瓜添加,您仍然需要调用 AudioKit.start()。

于 2020-05-22T15:15:14.927 回答