[alsa-devel] S16_LE + softvol = bad
Hello developers,
some cards (most notably, Intel HD audio) have the PCM control as softvol, and default to S16_LE as a format for dmix. Since softvol is configured to attenuate signal, and not many people set this control to 100% (especially those who have no other volume controls), this effectively leaves less than 16 bits per sample.
The card can surely produce sound of better quality in most cases, if one changes defaults.pcm.dmix.format in ~/.asoundrc. However, one should now search a lot of forums in order to know about this setting. Not everyone does this, and not everyone is even able to diagnose the "noisy sound in Linux" problem properly as "too few bits per sample in the default configuration". A much better situation would be if ALSA defaulted to good quality (i.e.: S24_LE or S32_LE on all cards that require softvol and support this sample format). Could you please change the files in /usr/share/alsa/cards accordingly?
Alexander E. Patrakov wrote:
some cards (most notably, Intel HD audio) have the PCM control as softvol, and default to S16_LE as a format for dmix.
HDA-Intel.conf doesn't set a sample format, and when none is set, dmix tries S32 before S16. You get S16 only if the device doesn't support S32.
Regards, Clemens
At Thu, 17 Jan 2008 15:00:47 +0100, Clemens Ladisch wrote:
Alexander E. Patrakov wrote:
some cards (most notably, Intel HD audio) have the PCM control as softvol, and default to S16_LE as a format for dmix.
HDA-Intel.conf doesn't set a sample format, and when none is set, dmix tries S32 before S16. You get S16 only if the device doesn't support S32.
The plugin code is written partly in such a way, but the other parts do require the format given explicitly. So, it doesn't work as is. Fixing this wouldn't be hard, I guess, though.
Takashi
At Thu, 17 Jan 2008 15:11:18 +0100, I wrote:
At Thu, 17 Jan 2008 15:00:47 +0100, Clemens Ladisch wrote:
Alexander E. Patrakov wrote:
some cards (most notably, Intel HD audio) have the PCM control as softvol, and default to S16_LE as a format for dmix.
HDA-Intel.conf doesn't set a sample format, and when none is set, dmix tries S32 before S16. You get S16 only if the device doesn't support S32.
The plugin code is written partly in such a way, but the other parts do require the format given explicitly. So, it doesn't work as is. Fixing this wouldn't be hard, I guess, though.
... and the below is the fix. Give it a try.
Takashi
diff -r f20b309ff22a src/conf/alsa.conf --- a/src/conf/alsa.conf Tue Jan 15 14:29:34 2008 +0100 +++ b/src/conf/alsa.conf Thu Jan 17 15:18:53 2008 +0100 @@ -68,7 +68,7 @@ defaults.pcm.ipc_perm 0660 defaults.pcm.ipc_perm 0660 defaults.pcm.dmix.max_periods 0 defaults.pcm.dmix.rate 48000 -defaults.pcm.dmix.format S16_LE +defaults.pcm.dmix.format "unchanged" defaults.pcm.dmix.card defaults.pcm.card defaults.pcm.dmix.device defaults.pcm.device defaults.pcm.dsnoop.card defaults.pcm.card diff -r f20b309ff22a src/pcm/pcm_direct.c --- a/src/pcm/pcm_direct.c Tue Jan 15 14:29:34 2008 +0100 +++ b/src/pcm/pcm_direct.c Thu Jan 17 15:18:53 2008 +0100 @@ -874,7 +874,11 @@ int snd_pcm_direct_initialize_slave(snd_ return ret; } } - ret = snd_pcm_hw_params_set_format(spcm, hw_params, params->format); + if (params->format == SND_PCM_FORMAT_UNKNOWN) + ret = -EINVAL; + else + ret = snd_pcm_hw_params_set_format(spcm, hw_params, + params->format); if (ret < 0) { static const snd_pcm_format_t dmix_formats[] = { SND_PCM_FORMAT_S32, diff -r f20b309ff22a src/pcm/pcm_dmix.c --- a/src/pcm/pcm_dmix.c Tue Jan 15 14:29:34 2008 +0100 +++ b/src/pcm/pcm_dmix.c Thu Jan 17 15:18:53 2008 +0100 @@ -1267,7 +1267,7 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, params.periods = 3;
err = snd_pcm_slave_conf(root, dopen.slave, &sconf, 8, - SND_PCM_HW_PARAM_FORMAT, 0, ¶ms.format, + SND_PCM_HW_PARAM_FORMAT, SCONF_UNCHANGED, ¶ms.format, SND_PCM_HW_PARAM_RATE, 0, ¶ms.rate, SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels, SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time, @@ -1282,8 +1282,10 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, if (psize == -1 && params.period_time == -1) params.period_time = 125000; /* 0.125 seconds */
- /* sorry, limited features */ - if (! (dmix_supported_format & (1ULL << params.format))) { + if (params.format == -2) + params.format = SND_PCM_FORMAT_UNKNOWN; + else if (!(dmix_supported_format & (1ULL << params.format))) { + /* sorry, limited features */ SNDERR("Unsupported format"); snd_config_delete(sconf); return -EINVAL;
2008/1/17, Takashi Iwai tiwai@suse.de:
... and the below is the fix. Give it a try.
Tested with no explicit defaults.pcm.dmix.format, with explicit S16_LE, and with explicit S32_LE, all with Intel HD audio and the PC speaker (total 6 cases, including one meaningless). In all cases, the code was able to choose the correct format for talking with hardware (i.e., the worst of (a) explicitly specified, if any, and (b) the best hardware-supported one). Thanks for a quick fix!
Takashi
diff -r f20b309ff22a src/conf/alsa.conf --- a/src/conf/alsa.conf Tue Jan 15 14:29:34 2008 +0100 +++ b/src/conf/alsa.conf Thu Jan 17 15:18:53 2008 +0100 @@ -68,7 +68,7 @@ defaults.pcm.ipc_perm 0660 defaults.pcm.ipc_perm 0660 defaults.pcm.dmix.max_periods 0 defaults.pcm.dmix.rate 48000 -defaults.pcm.dmix.format S16_LE +defaults.pcm.dmix.format "unchanged" defaults.pcm.dmix.card defaults.pcm.card defaults.pcm.dmix.device defaults.pcm.device defaults.pcm.dsnoop.card defaults.pcm.card diff -r f20b309ff22a src/pcm/pcm_direct.c --- a/src/pcm/pcm_direct.c Tue Jan 15 14:29:34 2008 +0100 +++ b/src/pcm/pcm_direct.c Thu Jan 17 15:18:53 2008 +0100 @@ -874,7 +874,11 @@ int snd_pcm_direct_initialize_slave(snd_ return ret; } }
ret = snd_pcm_hw_params_set_format(spcm, hw_params, params->format);
if (params->format == SND_PCM_FORMAT_UNKNOWN)
ret = -EINVAL;
else
ret = snd_pcm_hw_params_set_format(spcm, hw_params,
params->format); if (ret < 0) { static const snd_pcm_format_t dmix_formats[] = { SND_PCM_FORMAT_S32,
diff -r f20b309ff22a src/pcm/pcm_dmix.c --- a/src/pcm/pcm_dmix.c Tue Jan 15 14:29:34 2008 +0100 +++ b/src/pcm/pcm_dmix.c Thu Jan 17 15:18:53 2008 +0100 @@ -1267,7 +1267,7 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, params.periods = 3;
err = snd_pcm_slave_conf(root, dopen.slave, &sconf, 8,
SND_PCM_HW_PARAM_FORMAT, 0, ¶ms.format,
SND_PCM_HW_PARAM_FORMAT, SCONF_UNCHANGED, ¶ms.format, SND_PCM_HW_PARAM_RATE, 0, ¶ms.rate, SND_PCM_HW_PARAM_CHANNELS, 0, ¶ms.channels, SND_PCM_HW_PARAM_PERIOD_TIME, 0, ¶ms.period_time,
@@ -1282,8 +1282,10 @@ int _snd_pcm_dmix_open(snd_pcm_t **pcmp, if (psize == -1 && params.period_time == -1) params.period_time = 125000; /* 0.125 seconds */
/* sorry, limited features */
if (! (dmix_supported_format & (1ULL << params.format))) {
if (params.format == -2)
params.format = SND_PCM_FORMAT_UNKNOWN;
else if (!(dmix_supported_format & (1ULL << params.format))) {
/* sorry, limited features */ SNDERR("Unsupported format"); snd_config_delete(sconf); return -EINVAL;
At Thu, 17 Jan 2008 20:01:09 +0500, Alexander E. Patrakov wrote:
2008/1/17, Takashi Iwai tiwai@suse.de:
... and the below is the fix. Give it a try.
Tested with no explicit defaults.pcm.dmix.format, with explicit S16_LE, and with explicit S32_LE, all with Intel HD audio and the PC speaker (total 6 cases, including one meaningless). In all cases, the code was able to choose the correct format for talking with hardware (i.e., the worst of (a) explicitly specified, if any, and (b) the best hardware-supported one). Thanks for a quick fix!
Thanks for checking. I applied it to HG tree now.
This might break something on some drivers due to the format changes (requiring larger buffers) although I don't think it won't be much. Let's see. For such devices, we can add S16 in the card config.
Takashi
Takashi Iwai wrote:
At Thu, 17 Jan 2008 20:01:09 +0500, Alexander E. Patrakov wrote:
2008/1/17, Takashi Iwai tiwai@suse.de:
... and the below is the fix. Give it a try.
Tested with no explicit defaults.pcm.dmix.format, with explicit S16_LE, and with explicit S32_LE, all with Intel HD audio and the PC speaker (total 6 cases, including one meaningless). In all cases, the code was able to choose the correct format for talking with hardware (i.e., the worst of (a) explicitly specified, if any, and (b) the best hardware-supported one). Thanks for a quick fix!
Thanks for checking. I applied it to HG tree now.
Could you please apply the same tweak (use the best available sample format unless overridden) to dsnoop, too?
At Wed, 23 Jan 2008 16:21:46 +0500, Alexander E. Patrakov wrote:
Takashi Iwai wrote:
At Thu, 17 Jan 2008 20:01:09 +0500, Alexander E. Patrakov wrote:
2008/1/17, Takashi Iwai tiwai@suse.de:
... and the below is the fix. Give it a try.
Tested with no explicit defaults.pcm.dmix.format, with explicit S16_LE, and with explicit S32_LE, all with Intel HD audio and the PC speaker (total 6 cases, including one meaningless). In all cases, the code was able to choose the correct format for talking with hardware (i.e., the worst of (a) explicitly specified, if any, and (b) the best hardware-supported one). Thanks for a quick fix!
Thanks for checking. I applied it to HG tree now.
Could you please apply the same tweak (use the best available sample format unless overridden) to dsnoop, too?
Done.
Takashi
participants (3)
-
Alexander E. Patrakov
-
Clemens Ladisch
-
Takashi Iwai