An easy to use CoreMIDI and AudioSampler library.


Create a MIDIController which handles MIDI devices and receives MIDI messages.

// Create the MIDISession.
let controller = MIDIController()

// Retreive the devices connected to the system.
let devices = controller.inputDevices

// Set a selected device for the controller as input.
controller.set(device: selectedDevice)

Create an AudioSampler which receives the MIDI messages and synthetizes them.

// soundbankURL can be a URL to an sf2 soundbank file. 
let sampler = try AudioSampler(soundbank: soundbankURL)

// Attach a MIDIService to the sampler.

// Connect the sampler.node to an AVAudioEngine.
audioEngine.connect(sampler.node, to: audioEngine.mainMixerNode, format: nil)
try engine.start()


Decoding MIDIEvent

The AudioSampler handles noteOn noteOff and sustain pedal messages.

enum MIDIEvent {
    case noteOn(note: Note, velocity: Velocity)
    case noteOff(note: Note)
    case sustain(Bool)

The conversion from CoreMIDI.MIDIEventPacket to MIDIEvent happanes in a MIDICodingStrategy implementation.

protocol MIDICodingStrategy {
    var verion: MIDIProtocolID { get }
    func decode(event: MIDIEventPacket) -> MIDIEvent?

Confirming to this protocol you can create your own custom MIDIEvent conversion for your own MIDI controller.

let controller = MIDIController(decoder: CustomAKAICoder())

Or you can use the default MIDI 1.0 coder and add a fallback operator for unhandled MIDI events.

let controller = MIDIController(decoder: .default_v1.fallback(PadsDecoder()))


View Github