Re: Timing mechanism for MIDI ?
Re: Timing mechanism for MIDI ?
- Subject: Re: Timing mechanism for MIDI ?
- From: William Stewart <email@hidden>
- Date: Wed, 10 Dec 2008 17:38:45 -0800
Peter,
The timing granularity that you describe is fine, but only *because*
you are scheduling ahead... What CoreMIDI (and MusicSequence/Player)
do for you is use much finer timing models to ensure that the events
are delivered at the appropriate times. The original question had
mixed in the idea of *not* doing schedule ahead and using the NSTimers
- and this is going to be very jittery
Bill
On Dec 10, 2008, at 1:10 PM, Peter Johnson wrote:
Hi
Yes the thread relies on [NSThred sleepUntilDate] but that's not a
problem as NSThread is a wrapper around the POSIX pthreads
(sleepUntilDate is probably implemented with something like
pthreads_cond_wait) which is as low level as you can go in user-space.
In my sequencer, I do exactly what Brian describes. I have a window
of events which are queued ahead of where the actual transport play
head is, in my case it's an arbitrary 10 PPQN. I have only 2
threads, one for the timer and one for the sequencer. When playback
begins, I start both threads and take a starting time reference
using AudioGetCurrentHostTime(). The sequencer thread then sleeps on
a semaphore. When the timer thread ticks over, it signals (polls)
the sequencer thread. The sequencer thread then looks for events
between now + look_ahead and sends them to CoreMIDI with time stamps
into the future.
When the sequencer schedules a MIDI event for transmission it sets
the event's time to some future time. I use a functions like these
to convert between sequencer clocks (PPQN values incremented by the
timer thread) and nanoseconds for CoreMIDI, thus:
class Clock is in PPQN
const int32 Clock::PPQN = 480;
const int32 CLOCKS_PER_MINUTE = 60000;// 1 minute milliseconds
const uint64 CLOCK_DIVISOR = 1000000;// nanos to millis
int32 blah::clock_to_ms(const Clock& time)
{
return ((time - start_clock) * (CLOCKS_PER_MINUTE /
Clock::PPQN) / tempo);
}
void blah::send(MIDI_event e)
{
MIDITimeStamp nsec = static_cast<uint32>(clock_to_ms(e.time)) *
CLOCK_DIVISOR;
midi_tx(e.data, nsec);
}
void blah::midi_tx(you_data data, MIDITimeStamp nsec)
{
Byte midi[] = { (/* your data */ };
MIDIPacketList packetList;
MIDIPacket* packetPtr = MIDIPacketListInit(&packetList);
packetPtr = MIDIPacketListAdd(&packetList, sizeof packetList,
packetPtr, AudioConvertNanosToHostTime(nsec), 3, (const Byte*) &midi);
MIDIReceived(info.dest, &packetList);
}
_______________________________________________
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
_______________________________________________
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