I'm wondering what the best way is to have a AKSequencer (actually an AKMusicTrack) output it's MIDI to an external device.
I have gotten it to work, but I feel like there is probably a more efficient way.
The way I've done it:
I've made subclass of AKPolyphonicNode ("MyPolyphonicNode")
I've used this to init a subclass of AKMIDINode ("MyMIDINode"),
class MyMIDINode:AKMIDINODE {
init(...) {
...
let myPolyphonicNode = MyPolyphonicNode()
super.init(node: myPolyphonicNode, midiOutputName: "myMIDIOutput")
...
}
//etc
}
and setMIDIoutput of the output of the AKMusicTrack to the midiIn of the AKMIDINode subclass:
track.setMIDIOutput(myMIDINode.midiIn)
Then in the MyPolyphonicNode subclass, I've overriden:
override func play(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, frequency: Double) {
myDelegate.myDelegateFunction(noteNumber:MIDINoteNumber, velocity:MIDIVelocity, channel:myChannel)
}
And in its delegate:
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))
}
This works, but I am thinking there is probably a way of telling the AKMusicTracks directly to output externally without doing all this?
A simpler solution is to use AKMIDICallbackInstrument
, although it is the same basic idea. It is easy to set up:
callbackInst = AKMIDICallbackInstrument()
track.setMIDIOutput(callbackInst.midiIn)
You need to provide a callback function which will trigger external 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.
}
This function will be called whenever events on the AKMusicTrack
are played