We're missing the delay in samples plus all of the extra samples of
silence we use to restart the device. This is in the samplerate of
the device.
Convert this to the time domain of the graph before adding it to xrun.
The default period is based on the default rate and might be too small
when using high samplerates. Scale the rate with the samplerate and make
sure it's a power of 2 to avoid trouble.
Fixes#3444
Add an xrun counter in the clock that accumulated the duration of
xruns. Fill this in in alsa-pcm.
A client could use this to dectect xruns (when it changes) and to align
the position and nsec after an xrun.
Only update the avail when we did a snd_pcm_forward(). Otherwise
we might think there is more available than there really is and we
might get xrun.
See #3395
It seems there are drivers that don't return a good values and we end up
with a lot of delay or automatic disable of htimestamp when the values
look too off.
Always use get_avail() and then only fetch the hires timestamp when
enabled to enhance the delay reporting. This way we also recover from
errors from snd_pcm_avail() instead of ignoring them.
This should make the recover after mmap_begin obsolete but we'll leave
that just to be safe.
There are currently several issues when multiple alsa devices are
involved.
For alsa devices that are followers, all data is written via
impl_node_process(). Currently spa_alsa_write() is only called if a new
buffer was queued.
It can happen that all buffers are in the ready list (queued by previous
calls but not yet written because there was no free space in the kernel
ring buffer). In this case writing stalls indefinitely.
To fix this, also call spa_alsa_write() if no new buffer is queued but
there are still buffers in the ready list.
If the ready list of the primary device is not empty then only this
device is handled because spa_alsa_write() is called directly. The other
devices make no progress during this interval.
The clock drift calculation works by comparing the alsa delay with the
expected delay since the last wakeup. This only work if the alsa
ringbuffer was filled completly. If the ready list contains a partial
buffer then the ringbuffer is not filled and the timing calculation
during the next wakeup is incorrect.
To fix all this, remove the special case for the non-empty ready list
and just call spa_node_call_ready() every time.
If we detect Playback/Capture Pitch 1000000, we can adjust those values
to update the feedback endpoint for the host. On the capture side, this
will instruct the host to adjust the rate at which data is being sent.
On the playback side, this will adjust the amount of data the USB gadget
driver sends out in each USB tick.
Use snd_pcm_htimestamp to get both the available space and the timestamp
when this was calculated. We can then use this to get a better estimate
of the delay in the device against the graph start and get a more
reliable delay between capture and playback.
Use separate values for the number of available samples in the
ringbuffer and the delay in the device.
When using htimestamp we can use the tstamp to get a more accurate delay
value against the graph start time.
Use a separate variable to hold the maximum amount of drift we allow
between driver and follower. Ensure this value is smaller than the max_error
and period size so that we have at most 1 period of drift.
Don't reschedule a timeout when we have less samples available than the
target but only reschedule when we have less that the required amount we
need to read. This ensures that we hover around the target level and the
timeouts/rate matching adapts correctly. Previously we would only rate
match if the have at least the target amount of samples, which would
then always result in a possitive rate adjustment and cause drift.
For capture, make sure that there is at least 32 samples of headroom
when we are not using IRQ mode to handle jitter in the timer wakeup.
For capture of batch devices this results in (for a 1024 quantum) a
target buffer fill level of 1024 + 512, and we will read if there are at
least 1024 samples available.
For non-batch devices we aim for a target buffer fill level of 1024 + 32
and read if there are at least 1024 samples available.
For IRQ based scheduling we might otherwise be woken up after we only
added one of the fds to the poll loop and then we get an error when we
try to update it afterwards. Instead, add the fds from the data thread
to get things nicely in sync.
In IRQ mode, disable the ALSA fds while we wait for the graph to produce
data. Otherwise we will wake up very quickly over and over.
When we get more data, we activate the sources again to start the next
cycle.
Provides configuration to disable timer-based scheduling. This can be
useful at low latencies, for example, where period-based interrupts
might be more reliable than timers.
Drivers should only read the target_ values in the timeout, update the
timeout with the new duration and then update the position.
For the position we simply need to add the previous duration to the
position and then set the new duration + rate.
Otherwise, everything else should read the duration/rate and not use
the target_ values.
Place the target rate and duration in the io clock area.
The driver is meant to read these new values at the start of the cycle
and update the position rate and duration.
This used to be done by the pipewire server when it received the ready
callback from the driver but this is in fact too late. Most driver would
start processing and set the next timeout based on the old rate/duration
instead of the new pending ones.
There is still a fallback for the old behaviour (with a warning) when
the driver doesn't yet update the position.
Don't just limit the max delay of samples we keep in the ALSA ringbuffer
to the buffer_size but to half of it. Make this into a max_delay
variable.
If we have a buffer size of 8192 samples and a headroom of 8192 samples,
when capturing, we would wait for the ringbuffer to contain at least
8192 samples, which would always xrun. When we limit the size to
half, we can still read the data without xruns.
Fixes#2972
When we are rate matching, keep some more headroom to make sure we
have enough data for the adaptive resampler.
Fixes crackling when following the dummy node and probably also when
following another capture device.
Add SPA_SCALE32_UP that scales a uint32 without overflow.
Use this for scaling the threshold in ALSA.
Fix the scaling in audioconvert of the buffer size, the scaling was
wrong and it was also causing an overflow resulting in choppy sound in
some cases.
See #2680