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
[email protected]
http://lists.create.ucsb.edu/mailman/listinfo/media_api