All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] dB range compound
@ 2006-09-01 17:46 Takashi Iwai
  2006-09-04 12:40 ` James Courtier-Dutton
  0 siblings, 1 reply; 5+ messages in thread
From: Takashi Iwai @ 2006-09-01 17:46 UTC (permalink / raw)
  To: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 482 bytes --]

Hi,

I found that some hardwares require the combination of dB scale
ranges.  For example, es1938 has volume controls with two curves,
e.g. the volume step in the value 0-8 is 3 dB while it's 1.5 dB in the
values 8-15.

The patch below introduces a new TLV type, DB_RANGE, to implement
the compound dB scales.  It can contain one or more child TLVs,
together with min and max values for each.

The first patch is for the kernel and the second for alsa-lib.

Any comments?


Takashi

[-- Attachment #2: tlv-range-kernel.diff --]
[-- Type: application/octet-stream, Size: 8101 bytes --]

diff -r a42a910c5302 include/tlv.h
--- a/include/tlv.h	Fri Sep 01 17:09:44 2006 +0200
+++ b/include/tlv.h	Fri Sep 01 19:11:32 2006 +0200
@@ -34,19 +34,26 @@
 #define SNDRV_CTL_TLVT_CONTAINER 0	/* one level down - group of TLVs */
 #define SNDRV_CTL_TLVT_DB_SCALE	1       /* dB scale */
 #define SNDRV_CTL_TLVT_DB_LINEAR 2	/* linear volume */
+#define SNDRV_CTL_TLVT_DB_RANGE 3	/* dB range container */
 
+#define TLV_DB_SCALE_ITEM(min, step, mute)			\
+	SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int),	\
+	(min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0)
 #define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
-unsigned int name[] = { \
-        SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \
-        (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) \
-}
+	unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) }
 
 /* linear volume between min_dB and max_dB (.01dB unit) */
+#define TLV_DB_LINEAR_ITEM(min_dB, max_dB)		    \
+	SNDRV_CTL_TLVT_DB_LINEAR, 2 * sizeof(unsigned int), \
+	(min_dB), (max_dB)
 #define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB)	\
-unsigned int name[] = { \
-        SNDRV_CTL_TLVT_DB_LINEAR, 2 * sizeof(unsigned int), \
-        (min_dB), (max_dB)				\
-}
+	unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) }
+
+/* dB range container */
+/* Each item is: <min> <max> <TLV> */
+/* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */
+#define TLV_DB_RANGE_HEAD(num)			\
+	SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int)
 
 #define TLV_DB_GAIN_MUTE	-9999999
 
diff -r a42a910c5302 pci/es1938.c
--- a/pci/es1938.c	Fri Sep 01 17:09:44 2006 +0200
+++ b/pci/es1938.c	Fri Sep 01 19:11:11 2006 +0200
@@ -62,6 +62,7 @@
 #include <sound/opl3.h>
 #include <sound/mpu401.h>
 #include <sound/initval.h>
+#include <sound/tlv.h>
 
 #include <asm/io.h>
 
@@ -1164,6 +1165,14 @@ static int snd_es1938_reg_read(struct es
 		return snd_es1938_read(chip, reg);
 }
 
+#define ES1938_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv)    \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\
+  .name = xname, .index = xindex, \
+  .info = snd_es1938_info_single, \
+  .get = snd_es1938_get_single, .put = snd_es1938_put_single, \
+  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
+  .tlv = { .p = xtlv } }
 #define ES1938_SINGLE(xname, xindex, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
   .info = snd_es1938_info_single, \
@@ -1217,6 +1226,14 @@ static int snd_es1938_put_single(struct 
 	return snd_es1938_reg_bits(chip, reg, mask, val) != val;
 }
 
+#define ES1938_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\
+  .name = xname, .index = xindex, \
+  .info = snd_es1938_info_double, \
+  .get = snd_es1938_get_double, .put = snd_es1938_put_double, \
+  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \
+  .tlv = { .p = xtlv } }
 #define ES1938_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
   .info = snd_es1938_info_double, \
@@ -1297,8 +1314,41 @@ static int snd_es1938_put_double(struct 
 	return change;
 }
 
+static unsigned int db_scale_master[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 54, TLV_DB_SCALE_ITEM(-3600, 50, 1),
+	54, 63, TLV_DB_SCALE_ITEM(-900, 100, 0),
+};
+
+static unsigned int db_scale_audio1[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 8, TLV_DB_SCALE_ITEM(-3300, 300, 1),
+	8, 15, TLV_DB_SCALE_ITEM(-900, 150, 0),
+};
+
+static unsigned int db_scale_audio2[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 8, TLV_DB_SCALE_ITEM(-3450, 300, 1),
+	8, 15, TLV_DB_SCALE_ITEM(-1050, 150, 0),
+};
+
+static unsigned int db_scale_mic[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 8, TLV_DB_SCALE_ITEM(-2400, 300, 1),
+	8, 15, TLV_DB_SCALE_ITEM(0, 150, 0),
+};
+
+static unsigned int db_scale_line[] = {
+	TLV_DB_RANGE_HEAD(2),
+	0, 8, TLV_DB_SCALE_ITEM(-3150, 300, 1),
+	8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0),
+};
+
+static DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0);
+
 static struct snd_kcontrol_new snd_es1938_controls[] = {
-ES1938_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0),
+ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0,
+		  db_scale_master),
 ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1),
 {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1309,19 +1359,28 @@ ES1938_DOUBLE("Master Playback Switch", 
 },
 {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
 	.name = "Hardware Master Playback Switch",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
 	.info = snd_es1938_info_hw_switch,
 	.get = snd_es1938_get_hw_switch,
+	.tlv = { .p = db_scale_master },
 },
 ES1938_SINGLE("Hardware Volume Split", 0, 0x64, 7, 1, 0),
-ES1938_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0),
+ES1938_DOUBLE_TLV("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0,
+		  db_scale_line),
 ES1938_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0),
-ES1938_DOUBLE("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0),
-ES1938_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
-ES1938_DOUBLE("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0),
-ES1938_DOUBLE("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0),
-ES1938_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0),
+ES1938_DOUBLE_TLV("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0,
+		  db_scale_mic),
+ES1938_DOUBLE_TLV("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0,
+		  db_scale_line),
+ES1938_DOUBLE_TLV("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0,
+		  db_scale_mic),
+ES1938_DOUBLE_TLV("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0,
+		  db_scale_line),
+ES1938_DOUBLE_TLV("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0,
+		  db_scale_capture),
 ES1938_SINGLE("PC Speaker Volume", 0, 0x3c, 0, 7, 0),
 ES1938_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0),
 ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
@@ -1332,16 +1391,26 @@ ES1938_SINGLE("Capture Switch", 0, 0x1c,
 	.get = snd_es1938_get_mux,
 	.put = snd_es1938_put_mux,
 },
-ES1938_DOUBLE("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
-ES1938_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0),
-ES1938_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0),
-ES1938_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0),
-ES1938_DOUBLE("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0),
-ES1938_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0),
-ES1938_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0),
-ES1938_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0),
-ES1938_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0),
-ES1938_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0),
+ES1938_DOUBLE_TLV("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0,
+		  db_scale_line),
+ES1938_DOUBLE_TLV("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0,
+		  db_scale_audio2),
+ES1938_DOUBLE_TLV("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0,
+		  db_scale_mic),
+ES1938_DOUBLE_TLV("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0,
+		  db_scale_line),
+ES1938_DOUBLE_TLV("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0,
+		  db_scale_mic),
+ES1938_DOUBLE_TLV("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0,
+		  db_scale_line),
+ES1938_DOUBLE_TLV("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0,
+		  db_scale_line),
+ES1938_DOUBLE_TLV("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0,
+		  db_scale_line),
+ES1938_DOUBLE_TLV("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0,
+		  db_scale_audio2),
+ES1938_DOUBLE_TLV("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0,
+		  db_scale_audio1),
 ES1938_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0),
 {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,

[-- Attachment #3: tlv-range-lib.diff --]
[-- Type: application/octet-stream, Size: 8436 bytes --]

diff -r 0c766669b691 include/control.h
--- a/include/control.h	Thu Aug 31 10:06:08 2006 +0200
+++ b/include/control.h	Fri Sep 01 19:12:02 2006 +0200
@@ -172,6 +172,8 @@ typedef enum _snd_ctl_event_type {
 #define SND_CTL_TLVT_DB_SCALE		0x0001
 /** TLV type - linear volume */
 #define SND_CTL_TLVT_DB_LINEAR		0x0002
+/** TLV type - dB range container */
+#define SND_CTL_TLVT_DB_RANGE		0x0003
 
 /** Mute state */
 #define SND_CTL_TLV_DB_GAIN_MUTE	-9999999
diff -r 0c766669b691 src/mixer/simple_none.c
--- a/src/mixer/simple_none.c	Thu Aug 31 10:06:08 2006 +0200
+++ b/src/mixer/simple_none.c	Fri Sep 01 19:12:02 2006 +0200
@@ -1011,7 +1011,13 @@ static int parse_db_range(struct selem_s
 #ifndef HAVE_SOFT_FLOAT
 	case SND_CTL_TLVT_DB_LINEAR:
 #endif
-		if (size < 2 * sizeof(int)) {
+	case SND_CTL_TLVT_DB_RANGE: {
+		unsigned int minsize;
+		if (type == SND_CTL_TLVT_DB_RANGE)
+			minsize = 4 * sizeof(int);
+		else
+			minsize = 2 * sizeof(int);
+		if (size < minsize) {
 			SNDERR("Invalid dB_scale TLV size");
 			return -EINVAL;
 		}
@@ -1020,6 +1026,7 @@ static int parse_db_range(struct selem_s
 			return -ENOMEM;
 		memcpy(rec->db_info, tlv, size + sizeof(int) * 2);
 		return 0;
+	}
 	default:
 		break;
 	}
@@ -1029,35 +1036,47 @@ static int parse_db_range(struct selem_s
 /* convert the given raw volume value to a dB gain
  */
 
-static int convert_to_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
-			 long volume, long *db_gain)
-{
-	if (init_db_range(ctl, rec) < 0)
+static int do_convert_to_dB(unsigned int *tlv, long rangemin, long rangemax,
+			    long volume, long *db_gain)
+{
+	switch (tlv[0]) {
+	case SND_CTL_TLVT_DB_RANGE: {
+		unsigned int pos, len;
+		len = tlv[1] / sizeof(int);
+		pos = 2;
+		while (pos + 4 <= len) {
+			rangemin = (int)tlv[pos];
+			rangemax = (int)tlv[pos + 1];
+			if (volume >= rangemin && volume <= rangemax)
+				return do_convert_to_dB(tlv + pos + 2,
+							rangemin, rangemax,
+							volume, db_gain);
+			pos += tlv[pos + 3] + 4;
+		}
 		return -EINVAL;
-
-	switch (rec->db_info[0]) {
+	}
 	case SND_CTL_TLVT_DB_SCALE: {
 		int min, step, mute;
-		min = rec->db_info[2];
-		step = (rec->db_info[3] & 0xffff);
-		mute = (rec->db_info[3] >> 16) & 1;
-		if (mute && volume == rec->min)
+		min = tlv[2];
+		step = (tlv[3] & 0xffff);
+		mute = (tlv[3] >> 16) & 1;
+		if (mute && volume == rangemin)
 			*db_gain = SND_CTL_TLV_DB_GAIN_MUTE;
 		else
-			*db_gain = (volume - rec->min) * step + min;
+			*db_gain = (volume - rangemin) * step + min;
 		return 0;
 	}
 #ifndef HAVE_SOFT_FLOAT
 	case SND_CTL_TLVT_DB_LINEAR: {
-		int mindb = rec->db_info[2];
-		int maxdb = rec->db_info[3];
-		if (volume <= rec->min || rec->max <= rec->min)
+		int mindb = tlv[2];
+		int maxdb = tlv[3];
+		if (volume <= rangemin || rangemax <= rangemin)
 			*db_gain = mindb;
-		else if (volume >= rec->max)
+		else if (volume >= rangemax)
 			*db_gain = maxdb;
 		else {
-			double val = (double)(volume - rec->min) /
-				(double)(rec->max - rec->min);
+			double val = (double)(volume - rangemin) /
+				(double)(rangemax - rangemin);
 			if (mindb <= SND_CTL_TLV_DB_GAIN_MUTE)
 				*db_gain = (long)(100.0 * 20.0 * log10(val)) +
 					maxdb;
@@ -1074,6 +1093,15 @@ static int convert_to_dB(snd_hctl_elem_t
 #endif
 	}
 	return -EINVAL;
+}
+
+static int convert_to_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
+			 long volume, long *db_gain)
+{
+	if (init_db_range(ctl, rec) < 0)
+		return -EINVAL;
+	return do_convert_to_dB(rec->db_info, rec->min, rec->max,
+				volume, db_gain);
 }
 
 /* initialize dB range information, reading TLV via hcontrol
@@ -1133,26 +1161,55 @@ static selem_ctl_t *get_selem_ctl(selem_
 
 /* Get the dB min/max values
  */
+static int do_get_dB_range(unsigned int *tlv, long rangemin, long rangemax,
+			   long *min, long *max)
+{
+	switch (tlv[0]) {
+	case SND_CTL_TLVT_DB_RANGE: {
+		unsigned int pos, len;
+		len = tlv[1] / sizeof(int);
+		pos = 2;
+		while (pos + 4 <= len) {
+			long rmin, rmax;
+			rangemin = (int)tlv[pos];
+			rangemax = (int)tlv[pos + 1];
+			do_get_dB_range(tlv + pos + 2, rangemin, rangemax,
+					&rmin, &rmax);
+			if (pos > 2) {
+				if (rmin < *min)
+					*min = rmin;
+				if (rmax > *max)
+					*max = rmax;
+			} else {
+				*min = rmin;
+				*max = rmax;
+			}
+			pos += tlv[pos + 3] + 4;
+		}
+		return 0;
+	}
+	case SND_CTL_TLVT_DB_SCALE: {
+		int step;
+		*min = (int)tlv[2];
+		step = (tlv[3] & 0xffff);
+		*max = *min + (long)(step * (rangemax - rangemin));
+		return 0;
+	}
+	case SND_CTL_TLVT_DB_LINEAR:
+		*min = (int)tlv[2];
+		*max = (int)tlv[3];
+		return 0;
+	}
+	return -EINVAL;
+}
+
 static int get_dB_range(snd_hctl_elem_t *ctl, struct selem_str *rec,
 			long *min, long *max)
 {
-	int step;
-
 	if (init_db_range(ctl, rec) < 0)
 		return -EINVAL;
 
-	switch (rec->db_info[0]) {
-	case SND_CTL_TLVT_DB_SCALE:
-		*min = (int)rec->db_info[2];
-		step = (rec->db_info[3] & 0xffff);
-		*max = *min + (long)(step * (rec->max - rec->min));
-		return 0;
-	case SND_CTL_TLVT_DB_LINEAR:
-		*min = (int)rec->db_info[2];
-		*max = (int)rec->db_info[3];
-		return 0;
-	}
-	return -EINVAL;
+	return do_get_dB_range(rec->db_info, rec->min, rec->max, min, max);
 }
 	
 static int get_dB_range_ops(snd_mixer_elem_t *elem, int dir,
@@ -1160,7 +1217,6 @@ static int get_dB_range_ops(snd_mixer_el
 {
 	selem_none_t *s = snd_mixer_elem_get_private(elem);
 	selem_ctl_t *c;
-	int err;
 
 	c = get_selem_ctl(s, dir);
 	if (! c)
@@ -1171,27 +1227,42 @@ static int get_dB_range_ops(snd_mixer_el
 /* Convert from dB gain to the corresponding raw value.
  * The value is round up when xdir > 0.
  */
-static int convert_from_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
-			   long db_gain, long *value, int xdir)
-{
-	if (init_db_range(ctl, rec) < 0)
+static int do_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax,
+			      long db_gain, long *value, int xdir)
+{
+	switch (tlv[0]) {
+	case SND_CTL_TLVT_DB_RANGE: {
+		unsigned int pos, len;
+		len = tlv[1] / sizeof(int);
+		pos = 2;
+		while (pos + 4 <= len) {
+			long dbmin, dbmax;
+			rangemin = (int)tlv[pos];
+			rangemax = (int)tlv[pos + 1];
+			if (! do_get_dB_range(tlv + pos + 2, rangemin, rangemax,
+					      &dbmin, &dbmax) &&
+			    db_gain >= dbmin && db_gain <= dbmax)
+				return do_convert_from_dB(tlv + pos + 2,
+							  rangemin, rangemax,
+							  db_gain, value, xdir);
+			pos += tlv[pos + 3] + 4;
+		}
 		return -EINVAL;
-
-	switch (rec->db_info[0]) {
+	}
 	case SND_CTL_TLVT_DB_SCALE: {
 		int min, step, max;
-		min = rec->db_info[2];
-		step = (rec->db_info[3] & 0xffff);
-		max = min + (int)(step * rec->max);
+		min = tlv[2];
+		step = (tlv[3] & 0xffff);
+		max = min + (int)(step * rangemax);
 		if (db_gain <= min)
-			*value = rec->min;
+			*value = rangemin;
 		else if (db_gain >= max)
-			*value = rec->max;
+			*value = rangemax;
 		else {
-			long v = (db_gain - min) * (rec->max - rec->min);
+			long v = (db_gain - min) * (rangemax - rangemin);
 			if (xdir > 0)
 				v += (max - min) - 1;
-			v = v / (max - min) + rec->min;
+			v = v / (max - min) + rangemin;
 			*value = v;
 		}
 		return 0;
@@ -1199,12 +1270,12 @@ static int convert_from_dB(snd_hctl_elem
 #ifndef HAVE_SOFT_FLOAT
 	case SND_CTL_TLVT_DB_LINEAR: {
 		int min, max;
-		min = rec->db_info[2];
-		max = rec->db_info[3];
+		min = tlv[2];
+		max = tlv[3];
 		if (db_gain <= min)
-			*value = rec->min;
+			*value = rangemin;
 		else if (db_gain >= max)
-			*value = rec->max;
+			*value = rangemax;
 		else {
 			/* FIXME: precalculate and cache vmin and vmax */
 			double vmin, vmax, v;
@@ -1212,10 +1283,10 @@ static int convert_from_dB(snd_hctl_elem
 				pow(10.0,  (double)min / 20.0);
 			vmax = !max ? 1.0 : pow(10.0,  (double)max / 20.0);
 			v = pow(10.0, (double)db_gain / 20.0);
-			v = (v - vmin) * (rec->max - rec->min) / (vmax - vmin);
+			v = (v - vmin) * (rangemax - rangemin) / (vmax - vmin);
 			if (xdir > 0)
 				v = ceil(v);
-			*value = (long)v + rec->min;
+			*value = (long)v + rangemin;
 		}
 		return 0;
 	}
@@ -1224,6 +1295,16 @@ static int convert_from_dB(snd_hctl_elem
 		break;
 	}
 	return -EINVAL;
+}
+
+static int convert_from_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
+			   long db_gain, long *value, int xdir)
+{
+	if (init_db_range(ctl, rec) < 0)
+		return -EINVAL;
+
+	return do_convert_from_dB(rec->db_info, rec->min, rec->max,
+				  db_gain, value, xdir);
 }
 
 static int get_dB_ops(snd_mixer_elem_t *elem,

[-- Attachment #4: Type: text/plain, Size: 373 bytes --]

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

[-- Attachment #5: Type: text/plain, Size: 161 bytes --]

_______________________________________________
Alsa-devel mailing list
Alsa-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2006-09-05 14:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-01 17:46 [RFC] dB range compound Takashi Iwai
2006-09-04 12:40 ` James Courtier-Dutton
2006-09-04 13:31   ` Takashi Iwai
2006-09-04 18:40     ` Takashi Iwai
2006-09-05 14:36       ` Takashi Iwai

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.