From: Takashi Iwai <tiwai@suse.de>
To: batyi@mail.ru
Cc: alsa-devel@lists.sourceforge.net
Subject: Re: Notes on 1.0.8-rc1 (and post-rc1)
Date: Wed, 12 Jan 2005 11:35:33 +0100 [thread overview]
Message-ID: <s5h1xcrc4ui.wl@alsa2.suse.de> (raw)
In-Reply-To: <41E4BAD2.3080106@mail.ru>
[-- Attachment #1: Type: text/plain, Size: 1595 bytes --]
At Wed, 12 Jan 2005 11:51:14 +0600,
Petr Gladkikh wrote:
>
> 1. Volume pcm which have volume coefficient as a parameter.
> 2. Mixer hook which can push volume coefficient from specified mixer
> control element into given value (It does it in a way similar to
> watching control changes in alsamixer). This hook can be attached to
> volume pcm.
>
> Configuration example
>
> pcm.vol {
> type volume
> slave.pcm hw:0
> coeff 0.9
> hook {
> card default
> control Master
> index 0
> }
> }
>
> Explicitly specified coefficient and one provided by hook are
> multiplied before applying to samples. Input and output PCM formats
> must match (as for copy plugin).
>
> These things are usable alone. For example you can adjust amplitude of
> PCM or tell Master_volume_control of one card to affect output of
> another :) But to completely cheat applications all this lacks some
> emulated volume control like described in quoted post above.
>
> So I wonder if this code could be useful for alsa-lib? Perhaps it can
> supplement softvol code? I would like it to be reviewed by anyone
> who interested. (I'll send the path in few days.)
Of course, it's interesting.
I think, however, the faeatures above can be easily merged to softvol,
too. Only two changes would be needed in practice:
- When coeff != 1, update the dB table at initialization
- Accept hw volume control (maybe better to add a new option)
instead of always bypassing it
An example patch is below (untested as usual).
The coeff is in dB on my code.
Or, any other functions in your proposal?
Takashi
[-- Attachment #2: Type: text/plain, Size: 6327 bytes --]
Index: alsa-lib/src/pcm/pcm_softvol.c
===================================================================
RCS file: /suse/tiwai/cvs/alsa/alsa-lib/src/pcm/pcm_softvol.c,v
retrieving revision 1.10
diff -u -r1.10 pcm_softvol.c
--- alsa-lib/src/pcm/pcm_softvol.c 4 Jan 2005 11:33:27 -0000 1.10
+++ alsa-lib/src/pcm/pcm_softvol.c 12 Jan 2005 10:31:22 -0000
@@ -48,6 +48,7 @@
unsigned int cur_vol[2];
unsigned int max_val;
double min_dB;
+ double coeff_dB;
unsigned short *dB_value;
} snd_pcm_softvol_t;
@@ -453,6 +454,7 @@
snd_output_printf(out, "Soft volume PCM\n");
snd_output_printf(out, "Control: %s\n", svol->elem.id.name);
snd_output_printf(out, "min_dB: %g\n", svol->min_dB);
+ snd_output_printf(out, "coeff: %g\n", svol->coeff_dB);
snd_output_printf(out, "resolution: %d\n", svol->max_val + 1);
if (pcm->setup) {
snd_output_printf(out, "Its setup is:\n");
@@ -465,7 +467,7 @@
static int add_user_ctl(snd_pcm_softvol_t *svol, snd_ctl_elem_info_t *cinfo, int count)
{
int err;
- unsigned int i;
+ int i;
err = snd_ctl_elem_add_integer(svol->ctl, &cinfo->id, count, 0, svol->max_val, 0);
if (err < 0)
@@ -484,7 +486,8 @@
*/
static int softvol_load_control(snd_pcm_t *pcm, snd_pcm_softvol_t *svol,
int ctl_card, snd_ctl_elem_id_t *ctl_id,
- int cchannels, double min_dB, int resolution)
+ int cchannels, int hwctl,
+ double min_dB, int resolution, double coeff)
{
char tmp_name[32];
snd_pcm_info_t *info;
@@ -513,6 +516,7 @@
svol->elem.id = *ctl_id;
svol->max_val = resolution - 1;
svol->min_dB = min_dB;
+ svol->coeff_dB = coeff;
snd_ctl_elem_info_alloca(&cinfo);
snd_ctl_elem_info_set_id(cinfo, ctl_id);
@@ -529,9 +533,10 @@
} else {
if (! (cinfo->access & SNDRV_CTL_ELEM_ACCESS_USER)) {
/* hardware control exists */
- return 1; /* notify */
-
- } else if (cinfo->type != SND_CTL_ELEM_TYPE_INTEGER ||
+ if (! hwctl)
+ return 1; /* notify */
+ }
+ if (cinfo->type != SND_CTL_ELEM_TYPE_INTEGER ||
cinfo->count != (unsigned int)cchannels ||
cinfo->value.integer.min != 0 ||
cinfo->value.integer.max != resolution - 1) {
@@ -547,7 +552,7 @@
}
}
- if (min_dB == PRESET_MIN_DB && resolution == PRESET_RESOLUTION)
+ if (min_dB == PRESET_MIN_DB && resolution == PRESET_RESOLUTION && coeff == 0)
svol->dB_value = preset_dB_value;
else {
#ifndef HAVE_SOFT_FLOAT
@@ -556,13 +561,15 @@
SNDERR("cannot allocate dB table");
return -ENOMEM;
}
- svol->min_dB = min_dB;
- for (i = 1; i < svol->max_val; i++) {
- double db = svol->min_dB - ((i - 1) * svol->min_dB) / (svol->max_val - 1);
+ for (i = 1; i <= svol->max_val; i++) {
+ double db = svol->coeff_dB + svol->min_dB - ((i - 1) * svol->min_dB) / (svol->max_val - 1);
double v = (pow(10.0, db / 20.0) * (double)(1 << VOL_SCALE_SHIFT));
+ if (v >= 65535)
+ v = 65535;
svol->dB_value[i] = (unsigned short)v;
}
- svol->dB_value[svol->max_val] = 65535;
+ if (coeff == 0)
+ svol->dB_value[svol->max_val] = 65535;
#else
SNDERR("Cannot handle the given min_dB and resolution");
return -EINVAL;
@@ -605,8 +612,8 @@
int snd_pcm_softvol_open(snd_pcm_t **pcmp, const char *name,
snd_pcm_format_t sformat,
int ctl_card, snd_ctl_elem_id_t *ctl_id,
- int cchannels,
- double min_dB, int resolution,
+ int cchannels, int hwctl,
+ double min_dB, int resolution, double coeff,
snd_pcm_t *slave, int close_slave)
{
snd_pcm_t *pcm;
@@ -620,8 +627,8 @@
svol = calloc(1, sizeof(*svol));
if (! svol)
return -ENOMEM;
- err = softvol_load_control(slave, svol, ctl_card, ctl_id, cchannels,
- min_dB, resolution);
+ err = softvol_load_control(slave, svol, ctl_card, ctl_id, cchannels, hwctl,
+ min_dB, resolution, coeff);
if (err < 0) {
softvol_free(svol);
return err;
@@ -664,7 +671,7 @@
* parse card index and id for the softvol control
*/
static int parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp,
- int *cchannelsp)
+ int *cchannelsp, int *hwctl)
{
snd_config_iterator_t i, next;
int iface = SND_CTL_ELEM_IFACE_MIXER;
@@ -676,6 +683,7 @@
*cardp = -1;
*cchannelsp = 2;
+ *hwctl = 0;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
const char *id;
@@ -746,6 +754,19 @@
*cchannelsp = v;
continue;
}
+ if (strcmp(id, "hwctl") == 0) {
+ char *tmp;
+ if ((err = snd_config_get_ascii(n, &tmp)) < 0) {
+ SNDERR("field %s has an invalid type", id);
+ goto _err;
+ }
+ if ((err = snd_config_get_bool_ascii(tmp)) < 0) {
+ SNDERR("field %s is not a boolean", id);
+ goto _err;
+ }
+ *hwctl = err;
+ continue;
+ }
SNDERR("Unknown field %s", id);
return -EINVAL;
}
@@ -804,9 +825,11 @@
[device INT] # device number of the element
[subdevice INT] # subdevice number of the element
[count INT] # control channels 1 or 2 (default: 2)
+ [hwctl BOOL] # accept h/w control
}
[min_dB REAL] # minimal dB value (default: -48.0)
[resolution INT] # resolution (default: 256)
+ [coeff REAL] # coefficient in dB
}
\endcode
@@ -845,7 +868,8 @@
snd_ctl_elem_id_t *ctl_id;
int resolution = PRESET_RESOLUTION;
double min_dB = PRESET_MIN_DB;
- int card = -1, cchannels = 2;
+ double coeff = 0;
+ int card = -1, cchannels = 2, hwctl = 0;
snd_config_for_each(i, next, conf) {
snd_config_t *n = snd_config_iterator_entry(i);
@@ -880,6 +904,16 @@
}
continue;
}
+#ifndef HAVE_SOFT_FLOAT
+ if (strcmp(id, "coeff") == 0) {
+ err = snd_config_get_real(n, &coeff);
+ if (err < 0) {
+ SNDERR("Invalid coeff value");
+ return err;
+ }
+ continue;
+ }
+#endif
SNDERR("Unknown field %s", id);
return -EINVAL;
}
@@ -915,12 +949,12 @@
if (err < 0)
return err;
snd_ctl_elem_id_alloca(&ctl_id);
- if ((err = parse_control_id(control, ctl_id, &card, &cchannels)) < 0) {
+ if ((err = parse_control_id(control, ctl_id, &card, &cchannels, &hwctl)) < 0) {
snd_pcm_close(spcm);
return err;
}
- err = snd_pcm_softvol_open(pcmp, name, sformat, card, ctl_id, cchannels,
- min_dB, resolution, spcm, 1);
+ err = snd_pcm_softvol_open(pcmp, name, sformat, card, ctl_id, cchannels, hwctl,
+ min_dB, resolution, coeff, spcm, 1);
if (err < 0)
snd_pcm_close(spcm);
return err;
prev parent reply other threads:[~2005-01-12 10:35 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-12-27 17:23 Notes on 1.0.8-rc1 (and post-rc1) Takashi Iwai
2004-12-27 21:44 ` [Alsa-devel] " Rui Nuno Capela
2004-12-29 13:08 ` Takashi Iwai
2005-01-12 5:51 ` Petr Gladkikh
2005-01-12 10:35 ` Takashi Iwai [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=s5h1xcrc4ui.wl@alsa2.suse.de \
--to=tiwai@suse.de \
--cc=alsa-devel@lists.sourceforge.net \
--cc=batyi@mail.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.