Jerzy,
    I want to encourage you to develop a simple MIDI/Audio 
synchronization program to serve as a reference. I've been meaning to 
add this to either PortAudio or PortMIDI, but obviously it hasn't happened.
    I think the problem is much simpler than you might think. Rather 
than dealing with ticks, it should be much easier to deal with 
double-precision floats in units of seconds. I understand your point 
about alignment between 44100hz and 480hz clocks, but in practice, you 
should avoid assuming a sample rate or a tick rate or a tempo, and it's 
easier to convert everything to seconds. The small (sub-millisecond) 
rounding error from ticks to seconds is comparable to the rounding that 
took place when the midi file was created and is dominated by other 
errors that come from audio latency, midi latency, synthesis latency, 
operating system latency, etc. I think you'll be able to get 
synchronization on the order of a millisecond or a few, but not much 
less, and if you achieve synchronization to a couple milliseconds, you 
won't hear the error except in contrived examples.
    Assuming you can go with timing based on seconds, you should open a 
PortMIDI output stream with a function pointer to your own time 
reference. This is a function that PortMidi can call(back) to get the 
current time in ms. This function should query PortAudio for the audio 
stream time. With this in place, if you want a MIDI message to go out at 
a time corresponding to an audio stream time of 1.137 seconds, you just 
give the message a timestamp of 1137 and let PortMIDI handle the 
synchronization from there. In at least some systems, these timestamps 
will be passed all the way through to the device driver so you should be 
getting the best MIDI timing your system is capable of. The higher-level 
software, e.g. the midi sequence player, shouldn't have to know about or 
do anything special to get synchronization.
    I've glossed over a few details. There will undoubtedly be time 
offsets between audio file time and PortAudio stream time and other 
offsets you'll have to compensate for. Also, PortMIDI will have to be 
opened with a latency > 0, and this latency will be added to the 
timestamp. The original idea here was that if audio was running with a 
10ms latency, then you could set PortMIDI latency to 10ms. Then, if you 
compute audio samples and a midi message at the same time, they will be 
output at the same time. There's also the issue that latency between the 
audio device driver that loads samples into the DAC and the analog 
output from the DAC (if you're converting to analog) can be rather large 
due to buffers, oversampling, and filters in the DAC. I don't think 
PortAudio can really estimate when a sample will become audio, so you 
might need a "fudge factor" that can be tuned to each machine's devices 
and hardware.

-Roger

_______________________________________________
media_api mailing list
media_api@create.ucsb.edu
http://lists.create.ucsb.edu/mailman/listinfo/media_api

Reply via email to