... Fixing many conditional operators with explicit construction of wxString
instead of simple string literals;
And fixing allocation of more strictly aligned structures on Mac, without need
for 10.14 as the minimum SDK, by means of some class-specific operators new
and delete.
.. Call the function SamplesToFloats instead, or in one place, where source
is also always float, just do memcpy.
Dithering never happened in these cases.
... The first is an example of a Setting with a computed default value.
Also making a new file to hold them, separate from the GUI that changes them
in QualityPrefs; fewer things depend on QualityPrefs
... Giving many examples of use of Settings objects. Many other rewrites like
this should be made to eliminate as many direct uses of gPrefs as we can.
Don't rely on long distance coincidences of literals for paths or defaults.
For each of several paths like /AudioIO/Host, all uses of that path are replaced
with use of a global Settings object defined in one place, in AudioIOBase. The
object also gives the benefit of caching the last-read or written value.
Other users of those preferences must then include "AudioIOBase.h" to make the
dependency explicit at compile time.
It should be checked that no other mentions of those paths remain in the source,
and that there was no unintended change in default values.
This also inverts dependency of AudioIOBase on RecordingPrefs, which is GUI for
changing some of these settings.
... This makes it impossible to forget to include the EXPERIMENTAL definitions
(such as when cutting and pasting code) and so get unintended quiet changes of
behavior.
The EXPERIMENTAL flags are now specified instead in new file Experimental.cmake
... The break was caused by ffa67d2 which split the base class AudioIoCallback
out of AudioIO.
This change only demotes some member declarations from AudioIO into
AudioIoCallback, and changes the qualified names of function definitions.
So now you can eliminate #define MIDI_THREAD in AudioIO.h and rebuild.
... guarantee the gap between producer and consumer is more than one grain, so
that the consumed entry is not still being produced.
Fixes small errors in positioning of the green play head line.
... and probably less contention with the checkpoint thread during recording,
and probably less total drop-out time when stress-testing recording with high
sample rates or slow external devices or both.
And another transaction scope for the post-processing of dropouts may reduce the
total time spent there.
... The post-processing of an excessive number of small, touching intervals
was one cause of apparent hangs when stopping recording to a slow external
device and using a high recording sample rate, in my own trials.
... when there really is at least one new sample block committed to the table,
which is typically only once in about every six seconds, with the default rate
and sample format.
Also renamed a callback function more aptly, since blocks are not files any
more.
!!! THERE WILL NO DOUBT BE BUGS !!!
This is a big one and there's still several things to
complete. Just want to get this in the wild to start
receiving feedback.
One big thing right now is that it will NOT load pre-aup3
files. An importer is on the way for that.
I got an error when compiling with wxWidgets 3.0.4, because wxPowerResource is undefined.
It seems to me that wxPowerResource has been introduced with wxWidgets 3.1.x branch:
51d715e46d (diff-93a9bace734a8065b203ebd2f670cbe8)
so, it would be worth to check if the feature is supported at compile time.
I don't know how this hasn't been seen before, but Cliff found that
opening Audacity via Commander One would, more often than not, cause
the pause button to enable when you started monitoring.
Seems it was picking up uninitialized memory values, but near as I can
tell, this has been this way for a very long time (like forever). So,
it's possible that I've not completely identified the culprit.
Even so, this should be initialized anyway and Cliff reports that it
does resolve the problem for him.
Currently AudioIoCallback::ScrubState::Get(), inserts a period of silence the first time it's called because at this time Scrubber::ContinueScrubbingPoll() has not been called, and so message.end has not been set to an appropriate value.
In the case of keyboard scrubbing and play-at-speed, the initial speed is already known, so message.end can be set to this value, removing the need for an initial silence.
The start of keyboard scrubbing and play-at-speed are now faster (the latter very much faster).
If one of the keyboard scrubbing keys is being held down, and the other keyboard scrubbing key is pressed:
1. With current behaviour, scrubbing in the other direction only starts when the original key is released - scrubbing stops and then starts in the other direction.
2. With the new behaviour, scrubbing immediately changes direction, and does not stop when the original key is released - scrubbing does not stop and then start again.
New behaviour:
If one of the keyboard scrubbing keys is being held down,
Problem:
On Windows, after 50ms, there is a short period of roughly zero introduced into the output. On Linux, there is also a spike which sounds like a crackle.
In AudioIO::FillBuffers(), Mixer::SetTimesAndSpeed() is called, which sets mT0 and mT1 to a small interval.
In Mixer::MixVariableRates(), all the samples in the interval are used, which means the Resample::Process() is called with last equal to true.
So when Mixer::MixVariableRates() is called again, the resampler is being reused after a call to Process() in which last is true.
It is not stated in the soxr documentation if the resampler will produce valid results in this case, and it's only the scrubbing code which does this.
I think this is the problem, and so the partial fix below avoids this happening.
Partial fix for play-at-speed and keyboard scrubbing:
For these, there is no need to reset the values of mT0 and mT1. (There is no need to allow for the sample position being used to potentially jump around.)
So for these cases, Mixer::SetSpeed() is called, rather than Mixer::SetTimesAndSpeed().
Instead of only when recording (it broke monitoring), now Audacity
will prevent the system from sleeping while any audio I/O is active.
This might be a little strong-handed though and maybe should be a
preference option.