AVMIDIPlayer has this initializer:
initWithData:soundBankURL:error:
This is in addition to an initializer for reading from a standard MIDI file.
The data is NSData, which I assumed is in a standard MIDI file format. So, how to get that data? Well, the current way to create a MIDI sequence is the AudioToolbox MusicSequence. (AVAudioEngine even has a member of this type).
MusicSequence has this converter:
MusicSequenceFileCreateData (
MusicSequence inSequence,
MusicSequenceFileTypeID inFileType,
MusicSequenceFileFlags inFlags,
SInt16 inResolution,
CFDataRef *outData
);
So let's try that.
var status = OSStatus(noErr)
var data:Unmanaged<CFData>?
status = MusicSequenceFileCreateData (musicSequence,
MusicSequenceFileTypeID(kMusicSequenceFile_MIDIType),
MusicSequenceFileFlags(kMusicSequenceFileFlags_EraseFile),
480, &data)
var ns:NSData = data!.takeRetainedValue()
var error:NSError?
self.mp = AVMIDIPlayer(data: ns, soundBankURL: soundbank, error: &error)
(I've loaded the soundbank previously). Good news: That does play the MIDI data. Bad news: Upon reaching the end of the sequence, it crashes.
queue = 'CallbackQueue', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
Two guesses. There is a bug in the platform code, or (more likely) my code.
tl;dr Am I getting the data incorrectly?
I received the Tumbleweed badge for this!
Anyway, the problem is the AVMIDIPlayer's play function. If you give it a nil completion handler, it is happy and it won't crash. If you do give it a completion handler, then blammo - crash. I've tried both a closure and a garden variety function for the completion handler.
var completion:AVMIDIPlayerCompletionHandler = {
println("done")
}
tl;dr
Do this:
midiPlayer.play(nil)
and not this:
midiPlayer.play(completion)