... in case you also do things, concurrent with the recording, that affect the
undo stack, either by pushing it (such as by changing the gain on one of the
playing tracks, or making a label) or by "Modifying state" without a new undo
item (such as when you change its size or mute or solo).
... The part that checks the previously unused statusFlags argument of
audacityAudioCallback can make zero-length labels. I did provoke this into
happening repeatably on macOS using a debug build, zero buffer length in device
preferences, and a busy CPU running other programs, within just two minutes of
recording.
But close zooming in on the label, and listening, revealed nothing obviously
wrong, no click in the playback. So I consider that a false positive.
But the part of the drop-out detection that would make nonzero length
labels, because the other AudioThread is lagging in its writes to disk --
this part remains. Yet I have not yet provoked this into happening.
1) When the program detects this, insert zeroes into the recording to keep the
other good parts synchronized.
2) When recording stops, a message box alerts the user, and a label track is
added showing the lost parts, labelled with consecutive numbers.
3) A menu item visible in alpha builds only is added to Tools, to simulate
recording errors at random times and test the reporting feature.
... in case you also do things, concurrent with the recording, that affect the
undo stack, either by pushing it (such as by changing the gain on one of the
playing tracks, or making a label) or by "Modifying state" without a new undo
item (such as when you change its size or mute or solo).
... This even makes it possible to remove the prohibition of undo and redo
during transport, not that we want to though. Playback and recording will
continue, using track objects that might not be in the current project.
- Dead code from experiments in SelectionBar removed.
- Many warnings about unused parameters fixed with WXUNUSED()
- Many warnings about signed / unsigned comparisons cleaned up.
- Several 'local variable declared but not used' warnings fixed.
... caused by remembering a NULL pointer to active project when starting a
stream.
Hard to reproduce, but reported by David Bailes. We suspect that both the
closing of another project window, and changes of focused application, are
necessary to reproduce the problem.
... Write only one variable in audacityAudioCallback, to be read (maybe in
another thread) by AudioIO::MidiTime().
The non-Alsa case behaves essentially as before: it wasn't broken, so it
isn't fixed, though it is rearranged.
... I am not sure that this will solve all problems of jittery play, but I do
think this will solve the problem of a rush of slightly late notes at start of
play.
... and hoping it is positively helpful for Linux.
In AudioIO::MidiTime(), compute one of the terms by different means.
Use PaStreamInfo::outputLatency.
Do not use the difference of PaStreamCallbackTimeInfo::outputBufferDacTime
and PaStreamCallbackTimeInfo::currentTime.
Which debugging shows is very nearly the same value for Windows and Mac.
But we suspect the PaStreamCallbackTimeInfo fields are not correctly reported
on Linux.
... At least it fixes the gross problem; but there seems to be a small
accumulation of error still each time around the loop, that I don't understand
yet.
... Used to be, it became true too soon when play started after time 0, so
AudioIO::IsStreamActive() might become false too soon -- except that now there
is always a portaudio stream when there is a midi stream, so that didn't happen.
Mistake was to add mT0 to MidiTime(), which already has mT0 for its origin.
This error would affect nothing if you just let play to the end without trying
a keystroke command. The error might have been enabling the wrong commands.
... 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.
Don't assume Pa_GetStreamTimePaStreamCallbackTimeInfo origin is time-of-day.
portaudio.h says you should not, and in fact it was not.
The report is that this gets us some play, but there are still freezes.
The problem was that Audacity did not refill its buffers until the note-off of the last note played. That was (in the James Bond case) 2.9s after the end of the loop. The fix was to not add note off events after mT1 and instead use gAllNotesOff.
This was caused by the indicator-passed-selection check being inside a loop over all wave tracks. If there are no wave tracks, then the check never happened. I added a duplicate version of the check if there are no wave tracks. This may not be the best solution, but it works for now.
I'm not entirely sure why the check is in the loop (or what's going on with the len and maxLen variables); as such, I just haven't touched that. Perhaps it would be safe to move the check always outside of the loop, but I'm not completely confident in that.