如何从 AudioKit 中的 AKMusicTrack 输出外部 MIDI
How to output external MIDI from an AKMusicTrack in AudioKit
我想知道让 AKSequencer(实际上是 AKMusicTrack)将其 MIDI 输出到外部设备的最佳方法是什么。
我已经让它工作了,但我觉得可能还有更有效的方法。
我的做法:
我创建了 AKPolyphonicNode 的子类 ("MyPolyphonicNode")
我用它来初始化 AKMIDINode 的子类 ("MyMIDINode"),
class MyMIDINode:AKMIDINODE {
init(...) {
...
let myPolyphonicNode = MyPolyphonicNode()
super.init(node: myPolyphonicNode, midiOutputName: "myMIDIOutput")
...
}
//etc
}
并将AKMusicTrack的输出setMIDIoutput设置为AKMIDINode子类的midiIn:
track.setMIDIOutput(myMIDINode.midiIn)
然后在 MyPolyphonicNode 子类中,我覆盖了:
override func play(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, frequency: Double) {
myDelegate.myDelegateFunction(noteNumber:MIDINoteNumber, velocity:MIDIVelocity, channel:myChannel)
}
并在其委托中:
let midi:AKMIDI //set in the init
enableMIDI(midi.client, name: "midiClient") //also in the init
func myDelegateFunction(noteNumber:MIDINoteNumber, velocity:MIDIVelocity, channel:MIDIChannelNumber) {
midi.sendEvent(AKMIDIEvent(noteOn: noteNumber, velocity: velocity, channel: channel))
}
这行得通,但我想可能有一种方法可以让 AKMusicTracks 直接向外部输出而无需执行所有这些操作?
一个更简单的解决方案是使用 AKMIDICallbackInstrument
,尽管它的基本思想相同。易于设置:
callbackInst = AKMIDICallbackInstrument()
track.setMIDIOutput(callbackInst.midiIn)
您需要提供一个触发外部 MIDI 的回调函数:
callbackInst.callback = { statusByte, note, velocity in
// NB: in the next AudioKit release, there will be an easier init for AKMIDIStatus:
// let status = AKMIDIStatus(statusByte: statusByte)
let status = AKMIDIStatus(rawValue: Int(statusByte >> 4))
switch status {
case .noteOn:
midi.sendNoteOnMessage(noteNumber: note, velocity: velocity)
case .noteOff:
midi.sendNoteOffMessage(noteNumber: note, velocity: velocity)
default:
// etc.
}
每当播放 AKMusicTrack
上的事件时都会调用此函数
我想知道让 AKSequencer(实际上是 AKMusicTrack)将其 MIDI 输出到外部设备的最佳方法是什么。
我已经让它工作了,但我觉得可能还有更有效的方法。
我的做法:
我创建了 AKPolyphonicNode 的子类 ("MyPolyphonicNode")
我用它来初始化 AKMIDINode 的子类 ("MyMIDINode"),
class MyMIDINode:AKMIDINODE {
init(...) {
...
let myPolyphonicNode = MyPolyphonicNode()
super.init(node: myPolyphonicNode, midiOutputName: "myMIDIOutput")
...
}
//etc
}
并将AKMusicTrack的输出setMIDIoutput设置为AKMIDINode子类的midiIn:
track.setMIDIOutput(myMIDINode.midiIn)
然后在 MyPolyphonicNode 子类中,我覆盖了:
override func play(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, frequency: Double) {
myDelegate.myDelegateFunction(noteNumber:MIDINoteNumber, velocity:MIDIVelocity, channel:myChannel)
}
并在其委托中:
let midi:AKMIDI //set in the init
enableMIDI(midi.client, name: "midiClient") //also in the init
func myDelegateFunction(noteNumber:MIDINoteNumber, velocity:MIDIVelocity, channel:MIDIChannelNumber) {
midi.sendEvent(AKMIDIEvent(noteOn: noteNumber, velocity: velocity, channel: channel))
}
这行得通,但我想可能有一种方法可以让 AKMusicTracks 直接向外部输出而无需执行所有这些操作?
一个更简单的解决方案是使用 AKMIDICallbackInstrument
,尽管它的基本思想相同。易于设置:
callbackInst = AKMIDICallbackInstrument()
track.setMIDIOutput(callbackInst.midiIn)
您需要提供一个触发外部 MIDI 的回调函数:
callbackInst.callback = { statusByte, note, velocity in
// NB: in the next AudioKit release, there will be an easier init for AKMIDIStatus:
// let status = AKMIDIStatus(statusByte: statusByte)
let status = AKMIDIStatus(rawValue: Int(statusByte >> 4))
switch status {
case .noteOn:
midi.sendNoteOnMessage(noteNumber: note, velocity: velocity)
case .noteOff:
midi.sendNoteOffMessage(noteNumber: note, velocity: velocity)
default:
// etc.
}
每当播放 AKMusicTrack
上的事件时都会调用此函数