The caller's requested latency in frames is based on the stream's
requested rate in `stream_params`. In the default case (when not
overriding latency for BT headsets), use this rate when converting
frames to hns.
Microsoft wave audio docs say "samples are the preferred time format in which
to represent the current position", but relying on this causes problems on
Windows XP, the only OS cubeb_winmm is used on.
While the wdmaud.sys driver internally tracks a 64-bit position and ensures no
backward movement, the WinMM API limits the position returned from
waveOutGetPosition() to a 32-bit DWORD (this applies equally to XP x64). The
higher 32 bits are chopped off, and to an API consumer the position can appear
to move backward.
In theory, even a 32-bit TIME_SAMPLES position should provide plenty of
playback time for typical use cases before this pseudo wrap-around, e.g:
(2^32 - 1)/48000 = ~24:51:18 for 48.0 kHz stereo;
(2^32 - 1)/44100 = ~27:03:12 for 44.1 kHz stereo.
In reality, wdmaud.sys doesn't provide a TIME_SAMPLES position at all, only a
32-bit TIME_BYTES position, from which wdmaud.drv derives TIME_SAMPLES:
SamplePos = (BytePos * 8) / BitsPerFrame,
where BitsPerFrame = Channels * BitsPerSample,
Per dom\media\AudioSampleFormat.h, desktop builds always use 32-bit FLOAT32
samples, so the maximum for TIME_SAMPLES should be:
(2^29 - 1)/48000 = ~03:06:25;
(2^29 - 1)/44100 = ~03:22:54.
This might still be OK for typical browser usage, but there's also a bug in the
formula above: BytePos * 8 (BytePos << 3) is done on a 32-bit BytePos, without
first casting it to 64 bits, so the highest 3 bits, if set, would get shifted
out, and the maximum possible TIME_SAMPLES drops unacceptably low:
(2^26 - 1)/48000 = ~00:23:18;
(2^26 - 1)/44100 = ~00:25:22.
To work around these limitations, we just get the position in TIME_BYTES,
recover the 64-bit value, and do our own conversion to samples.
Format all the code under `include` and `src` except those files under
`src/speex` with style setting in `.clang-format` file by the following
script:
```sh
FILE_LIST="$(find "include" "src" -not -path "src/speex/*" | grep -E ".*(\.cpp|\.c|\.h|\.hpp|\.hh)$")"
echo "Files found to format:\n---\n$FILE_LIST\n---"
clang-format --verbose -i $FILE_LIST
```
There is a bug in the OSS cubeb code which use the previous number of
frames as input for the next data-exchange, when full-duplex is
activated. This causes noticable jitter, because the wrong number of
audio frames is exchanged.
The solution is to check both input and output audio DSP buffers and
select the minimum number of audio frames which can be transferred when
full duplex is activated.
On some device (namely, a Samsung Galaxy A30 running Android 10, see
https://bugzilla.mozilla.org/show_bug.cgi?id=1679932), the state is
"STARTED" for quite some time, so we don't go into the `if` statement.
It's best to fallback.
We then need to ensure the monotonicity of this clock (since now we use
two distinct ways of reporting the time, it can end up being
non-monotonic for some calls), using the same technique we use on other
backends.
Reduce the code complexity of non-blocking IO all together. Besides, we
should let recording direction driving the playback direction if we are
working with duplex stream.
- Fix misuse of SNDCTL_DSP_GETOSPACE ioctl on record.fd as well
- Add more comments regarding buffer initialization
- Address comments about which direction driving another direction