Swift - AudioKit AKMidi to AKSequencer

Viewed 531

I currently have an application which uses an AKKeyboard to create sounds using an Oscillator. Whenever the keyboard is played I get the MIDI data also. What I would like to do is create an AKSequence from the MIDI data I receive.

Any advice or pointers will be greatly appreciated, thank you.

Here is a partial amount of my code:

var bank = AKOscillatorBank()
var midi: AKMIDI!
let sequencer = AKSequencer()
let sequenceLength = AKDuration(beats: 8.0)

func configureBank() {
    AudioKit.output = bank

    do {
        try AudioKit.start()
    } catch {
        AKLog("AudioKit couldn't be started")
    }

    midi = AudioKit.midi
    midi.addListener(self)
    midi.openInput()
}

// AKKeyboard Protocol methods
func noteOn(note: MIDINoteNumber) {
    let event = AKMIDIEvent(noteOn: note, velocity: 80, channel: 5)
    midi.sendEvent(event)
    bank.play(noteNumber: note, velocity: 100)
}

func noteOff(note: MIDINoteNumber) {
    let event = AKMIDIEvent(noteOff: note, velocity: 0, channel: 5)
    midi.sendEvent(event)
    bank.stop(noteNumber: note)
}

// AKMIDIListener Protocol methods..
func receivedMIDINoteOff(noteNumber: MIDINoteNumber, velocity: MIDIVelocity, channel: MIDIChannel) {
    print("ReceivedMIDINoteOff: \(noteNumber), velocity: \(velocity), channel: \(channel)")
}
1 Answers

You don't actually need to build the sequence directly from the AKMIDIEvents. Just query the sequence's currentPosition when you call AKKeyboardView's noteOn and noteOff methods and programmatically add events to a sequencer track based on this.

The process is basically identical to this (minus the final step, of course): https://stackoverflow.com/a/50071028/2717159

Edit - To get the noteOn and noteOff times, and duration:

// store notes and times in a dictionary:
var noteDict = [MIDINoteNumber: MIDITimeStamp]()

// when you get a noteOn, note the time
noteDict[currentMIDINote] = seq.currentPosition.beats

// when you get a noteOff
let endTime = seq.currentPosition.beats
if let startTime = noteDict[currentMIDINote] {
    let durationInBeats = endTime - startTime
    // use the startTime, duration and currentMIDINote to add event to track
    noteDict[currentMIDINote] = nil
}
Related