1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-05 06:39:26 +02:00

Bug1714, more: better calculation of MidiTime...

... after I reflected more on the explanation of it in the long comment at top.

Brings back the use of PaUtil_GetTime() but now calls it also in the audio IO
callback, so we can correct the unspecified origin of times supplied to the
audio IO callback to agree with the PaUtilGetTime() clock.

Thus the Midi time calculation is again based on the clock time of the other
thread that calls MidiTime, making it a few milliseconds more accurate, while
avoiding subtraction of two times based on widely different origins, which
made the big numbers that overlowed and caused Bug1714 to happen.
This commit is contained in:
Paul Licameli 2017-08-14 01:20:37 -04:00
parent 76a9962a5e
commit 47eaf526a6
2 changed files with 21 additions and 4 deletions

View File

@ -4022,10 +4022,23 @@ PmTimestamp AudioIO::MidiTime()
// PaUtil_GetTime(), mAudioCallbackOutputDacTime, PaUtil_GetTime() - mAudioCallbackOutputDacTime);
// note: the extra 0.0005 is for rounding. Round down by casting to
// unsigned long, then convert to PmTimeStamp (currently signed)
// PRL: Bug1714 happened because PaUtil_GetTime() and
// mAudioCallbackOutputDacTime could be very widely different, causing
// integer overlows.
// Portaudio documentation says the origin for
// the times passed to audacityAudioCallback is unspecified.
// See long comments at the top of the file for the explanation of this
// calculation; we must use PaUtil_GetTime() here and also in the audio
// callback, to change the origin of times from portaudio, so the diffence of
// now and then is small, as the long comment assumes.
auto clockChange = PaUtil_GetTime() - mAudioCallbackClockTime;
auto offset = mAudioCallbackOutputDacTime - mAudioCallbackOutputCurrentTime;
return (PmTimestamp) ((unsigned long) (1000 * (AudioTime() + 1.0005 -
mAudioFramesPerBuffer / mRate +
-offset)));
return (PmTimestamp) ((unsigned long) (1000 * (
AudioTime() + 1.0005 -
mAudioFramesPerBuffer / mRate +
clockChange - offset
)));
}
void AudioIO::AllNotesOff()
@ -4258,6 +4271,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
#ifdef EXPERIMENTAL_MIDI_OUT
/* GSW: Save timeInfo in case MidiPlayback needs it */
gAudioIO->mAudioCallbackClockTime = PaUtil_GetTime();
gAudioIO->mAudioCallbackOutputDacTime = timeInfo->outputBufferDacTime;
gAudioIO->mAudioCallbackOutputCurrentTime = timeInfo->currentTime;
// printf("in callback, mAudioCallbackOutputDacTime %g\n", gAudioIO->mAudioCallbackOutputDacTime); //DBG

View File

@ -530,7 +530,10 @@ private:
// These fields are used to synchronize MIDI with audio:
/// PortAudio's currentTime
/// PortAudio's clock time
volatile double mAudioCallbackClockTime;
/// PortAudio's currentTime -- its origin is unspecified! So that's why
/// we also record the above
volatile double mAudioCallbackOutputCurrentTime;
/// PortAudio's outTime
volatile double mAudioCallbackOutputDacTime;