alsa-lib
alsa-lib copied to clipboard
What is the semantics of snd_pcm_hw_params_any?
It is not really a bug report but rather a request for clarification in attempt to figure out who is to blame for incorrect pulseaudio behavior.
I've got two different cards -- one internal and one USB -- which behave quite differently for this simple high level code:
snd_pcm_open()
snd_pcm_hw_params_any()
iterate snd_pcm_hw_params_test_rate() to check for supported rates
snd_pcm_hw_params_set_rate_near(44100)
snd_pcm_hw_params()
snd_pcm_hw_params_any()
iterate snd_pcm_hw_params_test_rate() to check for supported rates
In essence supported sample rates are queried twice, always with snd_pcm_hw_params_any() before them, but separated by snd_pcm_hw_params_set_rate_near().
Now with internal card both iterations report 7 supported rates while for USB first iteration reports 4 rates and second only one (44100). Is that expected or is snd_pcm_hw_params_any() supposed to provide configuration which would result in all rates reported again?
If you set the params - snd_pcm_hw_params(), the driver may restrict the future configuration space depending on this settings (for example to lock the playback and capture rates to identical value). Do you see this behaviour without snd_pcm_hw_params() in the chain?
Without snd_pcm_hw_params() both calls report all supported rates.
High level code in first comment is what pulseaudio basically does. Card initialization ends with snd_pcm_hw_params() while supported rates are queried later on. For some cards all rates are returned while for USB audio only one rate is returned. But as I understand that's something to be expected.
Yes, the configuration space is dynamic and it may change when the hw params are set.
Is there a way to leave this state and go back to unrestricted configuration?
Yes, snd_pcm_hw_free() call after snd_pcm_hw_params(). The PCM stream should be put back to the "open" state.
I don't follow the "set params" -> "query params" operation in PA. The query should be first...
I can't really tell why pulseaudio is doing things like this, but it seems to be in current shape for years. For some reason "set params" is part of initialization and capabilities query is done only once initialization is successful. I'm in the process of creating workaround but I'm still not sure about guarantees that alsa provides. I'd like to do something like:
snd_pcm_hw_params_alloca(&orig_hwparams); snd_pcm_hw_params_current(pcm, orig_hwparams); snd_pcm_hw_free(pcm); <query rates> snd_pcm_hw_params(pcm, orig_hwparams);
but not sure if orig_hwparams is still valid after snd_pcm_hw_free()? Or should I snd_pcm_hw_params_copy() it first?
Just in case it's about issue: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1145
and initialization process I mentioned is here: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/blob/v14.2/src/modules/alsa/alsa-util.c#L675
Seems that no matter what I do params retrieved with snd_pcm_hw_params_current() never succeed if passed to snd_pcm_hw_params().
You may use snd_pcm_dump() to check the set / current params.
Another pulseaudio issue with seemingly same outcome https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/1414
With my C-Media Unitek Y-247A I do not see this issue, all supported rates are detected by pulseaudio. Guess this still could be kernel driver change causing different behavior for devices with programmable clock source stuff.
I'm trying to fetch one of the modern dongles to confirm findings here regarding pulseaudio rate probing procedure.
Yes, snd_pcm_hw_free() call after snd_pcm_hw_params(). The PCM stream should be put back to the "open" state.
I don't follow the "set params" -> "query params" operation in PA. The query should be first...
Hi @perexg here is the pulseaudio sample rate probe routine since year 2011 https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/blob/master/src/modules/alsa/alsa-util.c#L1440-1452 Note this currently runs after snd_pcm_hw_param()
is already called with default sample rate.
I can reproduce this issue now with UAC2 hardware. Looks like this always worked before (and now with e.g. UAC1 or HDMI hardware that I have) because nothing was restricting sample rates.
I'll try to experiment with calling snd_pcm_hw_free
before starting probe or moving probe routine to happen before snd_pcm_hw_param()
is called for the first time.
Hi @jpalus could you please test pulseaudio with this change https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/782 ? I moved rate detection code to be just after snd_pcm_open()
which seems to fix the issue with UAC2 device that I have.