Last active
July 13, 2020 18:51
-
-
Save davidfloegel/056b870eb89416da267882172947af59 to your computer and use it in GitHub Desktop.
New Midi Player
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MidiPlayer.swift | |
// harmonic | |
// | |
// Created by David Floegel on 03/07/2020. | |
// | |
import Foundation | |
import AudioKit | |
@objc(MidiPlayer) | |
class MidiPlayer: NSObject { | |
var sequencer = AKSequencer() | |
var sampler = AKAppleSampler() | |
var noteNumbers: [NSNumber] = [] | |
override init() { | |
super.init() | |
self.setupSynth() | |
} | |
func setupSynth() { | |
try? sampler.loadSoundFont("UprightPiano", preset: 0, bank: 0) | |
sequencer = AKSequencer(targetNode: sampler) | |
let _ = sequencer.addTrack(for: sampler) | |
try? AudioKit.stop() | |
AudioKit.output = sampler | |
try? AudioKit.start() | |
} | |
@objc | |
func playNotation(_ bpm: NSNumber, midiNotes: [NSDictionary]) { | |
sequencer.tracks[0].clear() | |
for (i, note) in midiNotes.enumerated() { | |
sequencer.tracks[0].add( | |
noteNumber: UInt8(truncating: note["midiValue"] as! NSNumber), | |
velocity: 100, | |
position: Double(i), | |
duration: Double(truncating: note["duration"] as! NSNumber) / 1000 | |
) | |
noteNumbers.append(note["midiValue"] as! NSNumber) | |
} | |
// TODO for some reason this doesn't correspond to the total of note durations | |
// it's also very unclear whether this is milliseconds, or seconds, or whatever. | |
sequencer.length = 600 // sequencer.tracks[0].length | |
sequencer.tempo = Double(truncating: bpm) | |
sequencer.loopEnabled = false | |
sequencer.playFromStart() | |
} | |
@objc | |
func stopNotation() { | |
sequencer.tracks[0].stop() | |
sequencer.stop() | |
for (note) in self.noteNumbers { | |
try? self.sampler.stop(noteNumber: UInt8(truncating: note), channel: 0) | |
} | |
} | |
@objc | |
static func requiresMainQueueSetup() -> Bool { | |
return true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment