Hi, A few things come to my mind, not sure if it's related or not to your problems:
A MIDI packet can have multiple MIDI events. This often happens if the source plays two notes exactly at the same time, etc. The packet timestamp can be 0 in some cases, depending on the source, meaning "play this packet as soon as possible". In the stackoverflow question, you produce the actual samples on the MIDI thread. I think it's better to put the events on a thread-safe queue and process them on the audio thread. /Jonatan > Date: Tue, 17 May 2016 01:48:06 -0700 (PDT) > From: "Patrick J. Collins" <[email protected]> > To: [email protected] > Subject: more midi woes... > Message-ID: <[email protected]> > Content-Type: TEXT/PLAIN; charset=US-ASCII > > Hi everyone, > > So I have spent a good 4 painful days trying to get midi playback to > work, and I am about ready to give up. It's so depressing, what should > be so easy has proven to be so incredibly difficult and frustrating. > The worst part is, I can't even figure out what is happening. I've > tried rewriting my code in a billion different ways, and every time it > results in something "wrong", just in a different way. > > I guess the first question to ask here is: > > Do we really, really, really know that the MidiReadProc is reliable and > actually works? > > I am doing what seems like the simplest of simple: Send midi events to > an instrument if they are for a particular channel. > > static void midiReadProc(const MIDIPacketList *pktlist, > void *refCon, > void *connRefCon) { > > struct MidiData *midiData = (struct MidiData *)refCon; > > MIDIPacket *packet = (MIDIPacket *)pktlist->packet; > for (int i = 0; i < pktlist->numPackets; i++) { > NSUInteger channel = packet->data[0] & 0xf; > FMInstrument *fmInstrument = midiData->fmInstruments[channel]; > if (fmInstrument && channel == 6) [fmInstrument > writePacketWithObservedTimestamps:*packet]; > packet = MIDIPacketNext(packet); > } > } > > ... > > Then in my FMInstrument class, I am just doing: > > -(void)writePacketWithObservedTimestamps:(MIDIPacket)packet { > _ringBuffer->Write(packet.data, packet.length); > > MIDITimeStamp now = packet.timeStamp; > if (self.lastReadAt) { > NSNumber *delta = [NSNumber numberWithDouble:convertToSeconds(now) > - convertToSeconds(self.lastReadAt)]; > [self.deltas insertObject:delta atIndex:0]; > } > self.lastReadAt = now; > } > > And i've dispatched a thread to do: > > -(void)startPolling { > while (_shouldPoll) { > @autoreleasepool { > if (![self.deltas count]) continue; > > NSUInteger numberOfSamplesToGenerate = ceil([self sampleRate] * > [[self.deltas lastObject] doubleValue]); > [self.deltas removeLastObject]; > short *tempBuffer = (short *)malloc(sizeof(short) * > numberOfSamplesToGenerate); > _synthUnit->GetSamples(numberOfSamplesToGenerate, tempBuffer); > > for (int i = 0; i < numberOfSamplesToGenerate; i++) { > _generatedSamples[_bufferWriteIndex] = tempBuffer[i]; > _bufferWriteIndex += 1; > if (_bufferWriteIndex > _maxBufferIndex) _bufferWriteIndex > = 0; // _maxBufferIndex is samplerate * duration of sequence > } > free(tempBuffer); > } > } > } > > Just as a test, I am letting the MidiReadProc process the entire midi file, > after its done, then I let OpenAL stream the buffer, and the timing of all the > midi events is just, pure insanity. All over the place.. Total nonsense.. > notes that should not sound until way later happen immediately. It's as if > MidiReadProc is giving me totally incorrect timestamps, and delivering the > events in the wrong order... But that's not possible right? > > The only thing left for me to try is to not use the MidiReadProc, but rather > iterator through all the midi events in all the tracks.. I was trying to > avoid > having to do that because it's no fun, and I thought Midi was a solved problem > and that certainly it would be trivial to have midi playback with fm > synthesis... > > I'm depressed. > > Patrick J. Collins > http://collinatorstudios.com -- /Jonatan http://kymatica.com _______________________________________________ Do not post admin requests to the list. They will be ignored. Coreaudio-api mailing list ([email protected]) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/coreaudio-api/archive%40mail-archive.com This email sent to [email protected]
