... so that DeviceManager, DeviceToolbar, and PrefsDialog do not depend directly
on AudioIO.
But no function in the base class for starting streams, which would require
mention of Track types, which we want to avoid.
... New files, but (almost) empty; don't use the global variable gAudioIO,
but use one of two accessor function names (which are the same function for
now).
AudioIOBase will have fewer dependencies than AudioIO -- in particular, no
dependency on tracks.
It won't include StartStream. It will contain functions to query the
present state of streams, and device capabilities.
... except Audacity.h; and in no others.
Do so even if Experimental.h gets multiply included, as in both the .h and
.cpp files.
This makes it easier to do a text scan to be sure there are no unintended quiet
changes of meaning because of omission of Experimental.h when the flag is
an enabled one.
Also move inclusions of Experimental.h earlier.
Also don't require Experimental.h to be preceded by Audacity.h to define
EXPERIMENTAL_MIDI_OUT correctly.
The bug:
1. Set Audio host to WASAPI
2. choose recording and playback devices which have different default sample rates in shared mode.
3. Set overdub, and playthrough to off.
4. make a short recording.
5. playback. Fails with error dialog.
Cause of bug:
In AudioIO::GetBestRate, the last returned sample rate is cached. If the function is called again, with the same requested sample rate, then the cached value is returned. So in the above steps, when GetBestRate is called for playback, the sample rate of the recording device is returned.
Fix:
Include in the conditions for returning the cached rate that the values of playing and capturing as the same as in the previous call.
Flipped some conditions and used if else-if to reduce the indentation in code.
This makes the code more readable. No change in functionality.
Also created UpdateTimePositions() and made some bool functions void.
new variable mMaxFramesOutput used to communicate positional change.
AudioIO.cpp has nearly 6000 lines and needs to be broken up into separate aspects.
The main point of the new split is to better separate the time critical callback code (that runs in the portaudio thread) from the code that interacts with the disk (that runs in the Audio Thread).
... from the Audio thread to the PortAudio thread; the old
ScrubQueue::Consumer() function keeps only a vestigial purpose to prevent the
scrub queue from blocking.
... so there is only one update per track of the atomics in RingBuffer in each
pass of the loop in FillBuffers, which will be needed to synchronize RingBuffer
and TimeQueue correctly.
... this may be more than the batch size used in ongoing playback.
It is expected that this larger batch size is used only once when priming
the queue before starting play. But then FillBuffers() may attempt to
refill up to the minimum in case demand is outpacing supply.
Thus the new number defines a "yellow zone" for the queue.
1. The rate actually used by the sound card now sets the stopping sample number.
2. The tolerance in the 'stop position' is additionally trimmed to 20 samples.
... Rather than the confusing old terminology of "warped" time, meaning the
real time after accounting for time track, though that persists mostly in the
names of variables now mostly used only within PlaybackSchedule.
"Track" time refers to a position in a wave track, as indexed by the time
ruler.
"Real" time is indexed by the other scale of numbers drawn in the time track,
which is drawn on the screen with nonuniform spacing (so "warped" in that
sense), but it corresponds to uniform actual time.