pcm: clarify and fix default sbits (msbits) value for all formats

As described in the kernel patch (link bellow), the significant (resolution)
bits should be related to the usable sample bits not the physical sample bits.

Link: https://lore.kernel.org/linux-sound/20240222173649.1447549-1-perex@perex.cz/
Link: https://github.com/larsimmisch/pyalsaaudio/pull/146
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2024-02-23 21:50:01 +01:00
parent 431f69a8c3
commit 13057b74c8
3 changed files with 31 additions and 4 deletions

View file

@ -215,7 +215,8 @@ range, thus you may get the significant bits for linear samples via
#snd_pcm_hw_params_get_sbits() function. The example: ICE1712
chips support 32-bit sample processing, but low byte is ignored (playback)
or zero (capture). The function snd_pcm_hw_params_get_sbits()
returns 24 in this case.
returns 24 in this case. The significant bits are related to the usable
sample bits (width) not the physical sample space.
\section alsa_transfers ALSA transfers
@ -3905,6 +3906,10 @@ int snd_pcm_hw_params_get_rate_numden(const snd_pcm_hw_params_t *params,
* \param params Configuration space
* \return signification bits in sample otherwise a negative error code if the info is not available
*
* Significant bits are related to usable sample bits (width) not the
* physical sample bits (width). For non-linear formats, this value may have
* a special meaning which may be defined in future.
*
* This function should only be called when the configuration space
* contains a single configuration. Call #snd_pcm_hw_params to choose
* a single configuration from the configuration space.

View file

@ -379,12 +379,28 @@ static int snd_pcm_hw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
return 0;
}
static inline int hw_params_call(snd_pcm_hw_t *pcm_hw, snd_pcm_hw_params_t *params)
#define hw_param_mask(params,var) \
&((params)->masks[(var) - SND_PCM_HW_PARAM_FIRST_MASK])
static int hw_params_call(snd_pcm_hw_t *pcm_hw, snd_pcm_hw_params_t *params)
{
int err;
/* check for new hw_params structure; it's available from 2.0.2 version of PCM API */
if (SNDRV_PROTOCOL_VERSION(2, 0, 2) <= pcm_hw->version)
return ioctl(pcm_hw->fd, SNDRV_PCM_IOCTL_HW_PARAMS, params);
return use_old_hw_params_ioctl(pcm_hw->fd, SND_PCM_IOCTL_HW_PARAMS_OLD, params);
err = ioctl(pcm_hw->fd, SNDRV_PCM_IOCTL_HW_PARAMS, params);
else
err = use_old_hw_params_ioctl(pcm_hw->fd, SND_PCM_IOCTL_HW_PARAMS_OLD, params);
if (err >= 0 && pcm_hw->version < SNDRV_PROTOCOL_VERSION(2, 0, 17) && params->msbits > 0) {
snd_mask_t *m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
if (snd_mask_single(m)) {
snd_pcm_format_t format = snd_mask_min(m);
int width = snd_pcm_format_width(format);
if (width > 0 && params->msbits > (unsigned int)width)
params->msbits = width;
}
}
return err;
}
static int snd_pcm_hw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)

View file

@ -2075,6 +2075,7 @@ int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t
{
unsigned int k;
snd_interval_t *i;
snd_mask_t *m;
unsigned int rstamps[RULES];
unsigned int vstamps[SND_PCM_HW_PARAM_LAST_INTERVAL + 1];
unsigned int stamp = 2;
@ -2159,6 +2160,11 @@ int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t
i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS);
if (snd_interval_single(i))
params->msbits = snd_interval_value(i);
m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
if (snd_mask_single(m)) {
snd_pcm_format_t format = snd_mask_min(m);
params->msbits = snd_pcm_format_width(format);
}
}
if (!params->rate_den) {