Parse the audio.position spec completely so that we have the right
number of channels but only store the first max_position channels.
Also rename some field to make it clear that this is about the max
number of channel positions.
Add a function that accepts the size of the position array when reading
the audio positions. This makes it possible to decouple the position
array size from SPA_AUDIO_MAX_CHANNELS.
Also use SPA_N_ELEMENTS to pass the number of array elements to
functions instead of a fixed constant. This makes it easier to change
the array size later to a different constant without having to patch up
all the places where the size is used.
Disabling dB volumes for max_dB < 0 was added in Pulseaudio in 2021,
based on a device which had -128..-127.07 range. However, negative
max_dB is valid value for USB devices, and there are devices that have
it.
Eg. Microsoft LifeChat LX-3000 has
numid=6,iface=MIXER,name='Speaker Playback Volume'
; type=INTEGER,access=rw---R--,values=2,min=0,max=151,step=0
: values=150,150
| dBminmax-min=-28.37dB,max=-0.06dB
and the dB range seems to be OK. Web search for "The decibel volume
range for element" also gives other hits with seemingly OK looking
ranges.
Don't disable dB volume unless both the max is negative and the range is
suspiciously small. This should still disable it for the device this
check was originally added for.
Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/447
Link: 10ac01a206
Some ALSA devices have minimum HW volume value that is muted. ALSA
indicates it with SND_CTL_TLV_DB_GAIN_MUTE = -9999999 dB/100 volume dB.
When rounding down to HW volume, we may get this muted value.
When determining splitting of volumes to mixers and soft volume, we
don't want HW mixers to set volume to muted, unless the target volume is
actually muted.
Fix by adding element_ask_unmuted_dB_vol() that rounds up if the asked
rounding mode resulted to mute.
This fixes mic getting muted at low volume despite ALSA reporting the dB
values correctly.
Fixes#4890
Move accounting for pending ISO packet to the reference time. Make sure
rate matching is reset on start, and reset matching on resync properly.
Allow resync on first cycle, ok since iso_io->now is valid immediately.
Silence padding larger than ISO packet may be needed for resync when
quantum is large. We can't insert silence by adding data to encoding
buffer, as the encoding buffer may be then too small and it may also be
partially filled.
Fix by inserting silence from flush_data() just before buffers would be
consumed.
Fixes ISO stream alignment at playback start.
If BlueZ doesn't reply, it may consider the operation still active.
Try to Release the transport to get to a known state.
This can happen if device doesn't respond to operations in reasonable
time and BlueZ doesn't have its own timeout which is the case for BAP
currently (which is a bug there).
The interface of string typed controls has recently been changed in
libcamera[0], which affects `properties::Model`, so adapt to that change
in such a way that is compatible with both the new and old versions.
[0]: f84522d7cd
Log something less confusing when connection to remote device drops
unexpectedly.
Silence logging transport Release() error in cases where the transport
was simultaneously deleted.
We don't want to override the converter flags with the follower flags,
just enhance them with specific follower flags. Otherwise we lose the
DYNAMIC_DATA and other port flags from the converter.
See #4918
When using LC3-24kHz, remote device drops connection after a few seconds
if there is no sink playback. Avoid this by sending silence, one TX
packet for each RX packet, if sink hasn't been feeding data within a
timeout.
Configure the headroom to be equal of the minimum allowed period size for
the configuration.
This is desirable when the ALSA driver's hw_ptr is 'jumpy' due to
underplaying hardware architecture, like SOF.
In case of SOF the DSP firmware will burst read at stream start to fill
it's host facing buffer and later settles to a constant pace. The minimal
period size is constrained by the driver to cover the initial burst and
settling time of the hw_ptr.
Guard this mode of working with a new boolean flag, which is only enabled
for SOF cards, kept it disabled for other cards to avoid any unforeseen
side effects.
Even if the use-period-size-min-as-headroom is set to true, the manual
headroom configuration will take precedence to allow experimentation.
Link: https://github.com/thesofproject/linux/issues/5284
Link: https://github.com/thesofproject/sof/issues/9695#issuecomment-2569033847
Link: https://github.com/thesofproject/sof/issues/10172
Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4489
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Replace force_rate with force_quantum. We use force_rate when we need
to play an IEC958 or a DSD format but it does not make sense to just
force the rate without also forcing the duration.
This is also what happens when doing IRQ based scheduling, we then force
both the duration and rate of the graph so we can reuse this logic.
Also when forcing a quantum, take into account the suggested duration
and rate of the graph and scale that with the currently configured rate
for the period size. This gives a quantum that will match the requested
rate better. This is important for the DSD, where rate are very high and
we want the period size to be something reasonable relative to the
selected graph rate.
For batch devices (and when using a timer) we also configure a period
size that is half the duration of the quantum, to make sure we get some
headroom. We however need to force the full duration as the quantum, so
keep track of this scaling and apply when calculating the duration.
Commit cbbf37c3b8 changed the logic of the
Start command. Before this commit, when there was no converter, the
follower would always get the Start command. After the commit, the
follower would only get Start when previously Paused.
This however breaks when we set a format or buffers on the follower
without a converter because those actions might change the state of the
follower to Paused implicitly.
We should simply remove the started check here and always call Start on
the converter and follower, the implementations themselves will keep track
if anything needs to be done.
Fixes#4911
Some drivers (emu10k1) appear to not necessarily support more than 2
periods.
Don't fail start if snd_pcm_hw_params_set_periods_min() fails, then we
just set nearest possible periods and buffer sizes.
Align RX of streams in same ISO group:
- Ensure all streams in ISO group have same target latency also for BAP
Client
- Determine rate matching to ISO group clock from RX times of all
streams in the group
- Based on this, compute nominal packet RX times, and feed them to
decode-buffer instead of the real RX time. This is enough for
sub-sample level sync.
- Customise buffer overrun handling for ISO so that it drops data to
arrive exactly at the target, for faster convergence at RX start
The ISO clock matching is done based on kernel-provided packet RX times,
so it has unknown offset from the actual ISO clock, probably a few ms.
Current kernels (6.17) do not provide anything better to use for the
clock matching, and doing it properly appears to be controller
vendor-defined (if possible at all).
Take resampler delay into account when computing the buffer fill level,
including the fractional part.
If decode-buffer is now fed nominal packet reference times in
write_packet(), it converges the total buffer + resampler latency to the
target at sub-sample accuracy.
This is needed for aligning RX of ISO streams in the same group, so that
e.g. stereo pair alignment is achieved even though the streams have
separate resamplers. Resampler phases get aligned via independent rate
matching.
The rate matching calculations are done in the system clock domain. If
the driver ticks at a different rate, the correction factor needs to be
adjusted by the rate_diff.
setup_matching() also needs to be before spa_bt_decode_buffer_process():
as follower we should use rate matching value calculated on the
*previous* cycle, because this is what driver is doing when it adjusts
it tick rate.