narco
narco

Reputation: 840

How to output external MIDI from an AKMusicTrack in AudioKit

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?

Upvotes: 3

Views: 196

Answers (1)

c_booth
c_booth

Reputation: 2225

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

Upvotes: 2

Related Questions