more midi woes...
more midi woes...
- Subject: more midi woes...
- From: "Patrick J. Collins" <email@hidden>
- Date: Tue, 17 May 2016 01:48:06 -0700 (PDT)
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
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden