Set max volume as default for softvol

Set max volume as default for softvol.
This commit is contained in:
Takashi Iwai 2005-01-03 17:12:51 +00:00
parent cb6bb19b4d
commit 82e408d08b

View file

@ -91,6 +91,28 @@ static unsigned short preset_dB_value[PRESET_RESOLUTION] = {
#endif /* DOC_HIDDEN */ #endif /* DOC_HIDDEN */
/* (32bit x 16bit) >> 16 */
typedef union {
int i;
short s[2];
} val_t;
static inline int MULTI_DIV(int a, unsigned short b)
{
val_t v, x, y;
v.i = a;
y.i = 0;
#if __BYTE_ORDER == __LITTLE_ENDIAN
x.i = (unsigned int)v.s[0] * b;
y.s[0] = x.s[1];
y.i += (int)v.s[1] * b;
#else
x.i = (unsigned int)v.s[1] * b;
y.s[1] = x.s[0];
y.i += (int)v.s[0] * b;
#endif
return y.i;
}
/* /*
* apply volumue attenuation * apply volumue attenuation
* *
@ -106,7 +128,6 @@ static void snd_pcm_softvol_convert(snd_pcm_softvol_t *svol,
unsigned int cur_vol) unsigned int cur_vol)
{ {
const snd_pcm_channel_area_t *dst_area, *src_area; const snd_pcm_channel_area_t *dst_area, *src_area;
short *src, *dst;
unsigned int src_step, dst_step; unsigned int src_step, dst_step;
unsigned int ch; unsigned int ch;
unsigned int fr; unsigned int fr;
@ -123,18 +144,39 @@ static void snd_pcm_softvol_convert(snd_pcm_softvol_t *svol,
} }
vol_scale = svol->dB_value[cur_vol]; vol_scale = svol->dB_value[cur_vol];
for (ch = 0; ch < channels; ch++) { if (svol->sformat == SND_PCM_FORMAT_S16) {
src_area = &src_areas[ch]; /* 16bit samples */
dst_area = &dst_areas[ch]; short *src, *dst;
src = snd_pcm_channel_area_addr(src_area, src_offset); for (ch = 0; ch < channels; ch++) {
dst = snd_pcm_channel_area_addr(dst_area, dst_offset); src_area = &src_areas[ch];
src_step = snd_pcm_channel_area_step(src_area) / sizeof(short); dst_area = &dst_areas[ch];
dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(short); src = snd_pcm_channel_area_addr(src_area, src_offset);
fr = frames; dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
while (fr--) { src_step = snd_pcm_channel_area_step(src_area) / sizeof(short);
*dst = ((int)*src * vol_scale) >> VOL_SCALE_SHIFT; dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(short);
src += src_step; fr = frames;
dst += dst_step; while (fr--) {
*dst = ((int)*src * vol_scale) >> VOL_SCALE_SHIFT;
src += src_step;
dst += dst_step;
}
}
} else {
/* 32bit samples */
int *src, *dst;
for (ch = 0; ch < channels; ch++) {
src_area = &src_areas[ch];
dst_area = &dst_areas[ch];
src = snd_pcm_channel_area_addr(src_area, src_offset);
dst = snd_pcm_channel_area_addr(dst_area, dst_offset);
src_step = snd_pcm_channel_area_step(src_area) / sizeof(int);
dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(int);
fr = frames;
while (fr--) {
*dst = MULTI_DIV(*src, vol_scale);
src += src_step;
dst += dst_step;
}
} }
} }
} }
@ -149,6 +191,7 @@ static unsigned int get_current_volume(snd_pcm_softvol_t *svol)
unsigned int val; unsigned int val;
if (snd_ctl_elem_read(svol->ctl, &svol->elem) < 0) if (snd_ctl_elem_read(svol->ctl, &svol->elem) < 0)
return 0; return 0;
/* set max vol as default */
val = svol->elem.value.integer.value[0]; val = svol->elem.value.integer.value[0];
if (val > svol->max_val) if (val > svol->max_val)
val = svol->max_val; val = svol->max_val;
@ -281,8 +324,9 @@ static int snd_pcm_softvol_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * param
snd_pcm_plugin_hw_params_slave); snd_pcm_plugin_hw_params_slave);
if (err < 0) if (err < 0)
return err; return err;
if (slave->format != SND_PCM_FORMAT_S16) { if (slave->format != SND_PCM_FORMAT_S16 &&
SNDERR("softvol supports only S16"); slave->format != SND_PCM_FORMAT_S32) {
SNDERR("softvol supports only S16 or S32");
return -EINVAL; return -EINVAL;
} }
svol->sformat = slave->format; svol->sformat = slave->format;
@ -346,7 +390,13 @@ static void snd_pcm_softvol_dump(snd_pcm_t *pcm, snd_output_t *out)
static int add_user_ctl(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo) static int add_user_ctl(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo)
{ {
return snd_ctl_elem_add_integer(svol->ctl, &cinfo->id, 1, 0, svol->max_val, 0); int err;
err = snd_ctl_elem_add_integer(svol->ctl, &cinfo->id, 1, 0, svol->max_val, 0);
if (err < 0)
return err;
svol->elem.value.integer.value[0] = svol->max_val;
return snd_ctl_elem_write(svol->ctl, &svol->elem);
} }
/* /*
@ -482,7 +532,9 @@ int snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_softvol_t *svol; snd_pcm_softvol_t *svol;
int err; int err;
assert(pcmp && slave); assert(pcmp && slave);
if (sformat != SND_PCM_FORMAT_UNKNOWN && sformat != SND_PCM_FORMAT_S16_LE) if (sformat != SND_PCM_FORMAT_UNKNOWN &&
sformat != SND_PCM_FORMAT_S16 &&
sformat != SND_PCM_FORMAT_S32)
return -EINVAL; return -EINVAL;
svol = calloc(1, sizeof(*svol)); svol = calloc(1, sizeof(*svol));
if (! svol) if (! svol)
@ -749,8 +801,10 @@ int _snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
SND_PCM_HW_PARAM_FORMAT, 0, &sformat); SND_PCM_HW_PARAM_FORMAT, 0, &sformat);
if (err < 0) if (err < 0)
return err; return err;
if (sformat != SND_PCM_FORMAT_UNKNOWN && sformat != SND_PCM_FORMAT_S16) { if (sformat != SND_PCM_FORMAT_UNKNOWN &&
SNDERR("only S16 format is supported"); sformat != SND_PCM_FORMAT_S16 &&
sformat != SND_PCM_FORMAT_S32) {
SNDERR("only S16 or S32 format is supported");
snd_config_delete(sconf); snd_config_delete(sconf);
return -EINVAL; return -EINVAL;
} }