I am having endless issues with MusicTrack. I am trying to create a drum machine.
1) Looping (MusicTrackLoopInfo): is broken as far as I can tell, if you wish to try and change notes on the fly whilst looping (unless someone can tell me different or has a workaround?).
2) With the code below I use MusicTrackNewMIDINoteEvent to insert notes at regular interval (0.25, 0.5 etc). But due to the above, this is useless. So instead I tried using MusicTrackNewUserEvent to try and trigger note events from that.
The plan was to pass a timestamp, and fire UserEvent's on every 16th note, and check with an Array if to play a drum sound or not.
However, when played, it is totally out of time and absolutely unusable for triggering drum noises.
Am I right in saying user UserEvent's are not as accurate timing wise as NoteEvent's?
The whole method (midiTest) is called on a separate thread with...
[NSThread detachNewThreadSelector:@selector(midiTest) toTarget:audioEngine withObject:nil];
I am exasperated by it all! Any ideas?
-(void) midiTest {
OSStatus result = noErr;
[self createAUGraph];
[self configureAndStartAudioProcessingGraph: self.processingGraph];
// Create a client
MIDIClientRef virtualMidi;
result = MIDIClientCreate(CFSTR("Virtual Client"),
MyMIDINotifyProc,
NULL,
&virtualMidi);
// Create an endpoint
MIDIEndpointRef virtualEndpoint;
result = MIDIDestinationCreate(virtualMidi, (CFStringRef)@"Virtual Destination", MyMIDIReadProc, (__bridge void *)(self), &virtualEndpoint);
MusicSequence s;
NewMusicSequence(&s);
MusicTrack sequenceTrack;
MusicSequenceNewTrack(s, &sequenceTrack);
NSValue * sequenceStruct = [NSValue value:&s withObjCType:@encode(MusicSequence)];
[self.musicSequenceArray addObject: sequenceStruct];
MusicSequenceSetUserCallback(s, UserCallback, NULL);
MusicPlayer p;
NewMusicPlayer(&p);
MusicSequenceSetMIDIEndpoint(s, virtualEndpoint);
[self loadPreset];
MusicPlayerSetSequence(p, s);
result = MusicSequenceGetIndTrack(s, 0, &sequenceTrack);
MIDINoteMessage noteMessage;
noteMessage.channel = 0;
noteMessage.note = 60;
noteMessage.velocity = 100;
noteMessage.releaseVelocity = 0;
noteMessage.duration = 0.0;
int ticksPerBar = 4;
for (int i = 0; i<(8 *ticksPerBar); i++) {
UserEvent event;
event.length = 0;
event.length = sizeof(UserEvent);
event.playedNote = noteMessage.note;
event.tStamp = (float)i/ticksPerBar;
event.message = noteMessage;
event.player = _samplerUnit;
event.midiStatus = 144;
result = MusicTrackNewMIDINoteEvent(sequenceTrack, (float)i/ticksPerBar, ¬eMessage);
//MusicTrackNewUserEvent( sequenceTrack, (float)i/ticksPerBar, (MusicEventUserData *)&event);
}
MusicTrackLoopInfo loopInfo = { 8.0f, 0 };
result = MusicTrackSetProperty(sequenceTrack, kSequenceTrackProperty_LoopInfo, &loopInfo, sizeof(MusicTrackLoopInfo));
MusicPlayerPreroll(p);
MusicPlayerStart(p);
}