[alsa-devel] [PATCH - alsa-lib 2/3] tlv: Handle 'holes' in SND_CTL_TLVT_DB_RANGE array
Takashi Iwai
tiwai at suse.de
Mon Jul 19 17:51:27 CEST 2010
At Mon, 19 Jul 2010 10:14:05 +0300,
Peter Ujfalusi wrote:
>
> When converting from dB to raw value, and DB_RANGE is
> used with non overlapping map, dB value in between the
> sub ranges will be not found.
>
> For example, if the control has the following:
> 0: -10dB
> 1: -5dB
> 2: 0dB
> 3: 2dB
> 4: 4dB
>
> static const unsigned int nonoverlapping_tlv[] = {
> TLV_DB_RANGE_HEAD(2),
> 0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0),
> 3, 4, TLV_DB_SCALE_ITEM(200, 200, 0),
> };
>
> Range 1: -10 .. 0dB
> Range 2: 2 .. 4dB
>
> If user asks for 1dB the snd_tlv_convert_from_dB will not find
> the raw value, since the 1dB is not part of either range.
In the case above, can't you set like
TLV_DB_RANGE_HEAD(2),
0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0),
2, 4, TLV_DB_SCALE_ITEM(0, 200, 0)
??
Takashi
> static const unsigned int nonoverlapping_tlv[] = {
> TLV_DB_RANGE_HEAD(2),
> 0, 2, TLV_DB_SCALE_ITEM(-1000, 500, 0),
> 3, 4, TLV_DB_SCALE_ITEM(200, 200, 0),
> };
> To fix this, we will store the previous non maching range's
> maximum raw value. If the dB value is not found in the next range,
> we will check, if the requested dB value is in between the current
> and the previous range, and if it is than pick the apropriate raw
> value based on the xdir (up or down rounding).
>
> Signed-off-by: Peter Ujfalusi <peter.ujfalusi at nokia.com>
> ---
> src/control/tlv.c | 8 +++++++-
> 1 files changed, 7 insertions(+), 1 deletions(-)
>
> diff --git a/src/control/tlv.c b/src/control/tlv.c
> index d09766a..1767118 100644
> --- a/src/control/tlv.c
> +++ b/src/control/tlv.c
> @@ -285,7 +285,7 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax,
> {
> switch (tlv[0]) {
> case SND_CTL_TLVT_DB_RANGE: {
> - long dbmin, dbmax;
> + long dbmin, dbmax, prev_rangemax;
> unsigned int pos, len;
> len = int_index(tlv[1]);
> if (len > MAX_TLV_RANGE_SIZE)
> @@ -298,6 +298,7 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax,
> return 0;
> }
> pos = 2;
> + prev_rangemax = 0;
> while (pos + 4 <= len) {
> rangemin = (int)tlv[pos];
> rangemax = (int)tlv[pos + 1];
> @@ -308,6 +309,11 @@ int snd_tlv_convert_from_dB(unsigned int *tlv, long rangemin, long rangemax,
> return snd_tlv_convert_from_dB(tlv + pos + 2,
> rangemin, rangemax,
> db_gain, value, xdir);
> + else if (db_gain < dbmin) {
> + *value = xdir ? rangemin : prev_rangemax;
> + return 0;
> + }
> + prev_rangemax = rangemax;
> pos += int_index(tlv[pos + 3]) + 4;
> }
> return -EINVAL;
> --
> 1.7.1.1
>
More information about the Alsa-devel
mailing list