|
perex |
96d951 |
From bdf80e58af79d4e989cd8d701d97f888c9e2dadc Mon Sep 17 00:00:00 2001
|
|
perex |
96d951 |
From: Zerg Cannibal <cnb_zerg@yahoo.com>
|
|
perex |
96d951 |
Date: Mon, 21 Dec 2009 22:19:14 +0100
|
|
perex |
96d951 |
Subject: [PATCH] pcm: Fix the sound distortions for S24_3LE stream in pcm_softvol plugin
|
|
perex |
96d951 |
|
|
perex |
96d951 |
This patch fixes sound distortions in alsa-lib "softvol"
|
|
perex |
96d951 |
for S24_3LE sound stream, when softvol slider is not at 0.0dB
|
|
perex |
96d951 |
position.
|
|
perex |
96d951 |
|
|
perex |
96d951 |
Signed-off-by: CannibalZerg <cnb_zerg@yahoo.com>
|
|
perex |
96d951 |
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
|
perex |
96d951 |
---
|
|
perex |
96d951 |
src/pcm/pcm_softvol.c | 22 ++++++++++++++++++++--
|
|
perex |
96d951 |
1 files changed, 20 insertions(+), 2 deletions(-)
|
|
perex |
96d951 |
|
|
perex |
96d951 |
diff --git a/src/pcm/pcm_softvol.c b/src/pcm/pcm_softvol.c
|
|
perex |
96d951 |
index 637e5cb..2c7c006 100644
|
|
perex |
96d951 |
--- a/src/pcm/pcm_softvol.c
|
|
perex |
96d951 |
+++ b/src/pcm/pcm_softvol.c
|
|
perex |
96d951 |
@@ -107,7 +107,8 @@ static inline int MULTI_DIV_32x16(int a, unsigned short b)
|
|
perex |
96d951 |
v.i = a;
|
|
perex |
96d951 |
y.i = 0;
|
|
perex |
96d951 |
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
perex |
96d951 |
- x.i = (unsigned int)v.s[0] * b;
|
|
perex |
96d951 |
+ x.i = (unsigned short)v.s[0];
|
|
perex |
96d951 |
+ x.i *= b;
|
|
perex |
96d951 |
y.s[0] = x.s[1];
|
|
perex |
96d951 |
y.i += (int)v.s[1] * b;
|
|
perex |
96d951 |
#else
|
|
perex |
96d951 |
@@ -135,6 +136,23 @@ static inline int MULTI_DIV_int(int a, unsigned int b, int swap)
|
|
perex |
96d951 |
return swap ? (int)bswap_32(fraction) : fraction;
|
|
perex |
96d951 |
}
|
|
perex |
96d951 |
|
|
perex |
96d951 |
+/* always little endian */
|
|
perex |
96d951 |
+static inline int MULTI_DIV_24(int a, unsigned int b)
|
|
perex |
96d951 |
+{
|
|
perex |
96d951 |
+ unsigned int gain = b >> VOL_SCALE_SHIFT;
|
|
perex |
96d951 |
+ int fraction;
|
|
perex |
96d951 |
+ fraction = MULTI_DIV_32x16(a, b & VOL_SCALE_MASK);
|
|
perex |
96d951 |
+ if (gain) {
|
|
perex |
96d951 |
+ long long amp = (long long)a * gain + fraction;
|
|
perex |
96d951 |
+ if (amp > (int)0x7fffff)
|
|
perex |
96d951 |
+ amp = (int)0x7fffff;
|
|
perex |
96d951 |
+ else if (amp < (int)0x800000)
|
|
perex |
96d951 |
+ amp = (int)0x800000;
|
|
perex |
96d951 |
+ return (int)amp;
|
|
perex |
96d951 |
+ }
|
|
perex |
96d951 |
+ return fraction;
|
|
perex |
96d951 |
+}
|
|
perex |
96d951 |
+
|
|
perex |
96d951 |
static inline short MULTI_DIV_short(short a, unsigned int b, int swap)
|
|
perex |
96d951 |
{
|
|
perex |
96d951 |
unsigned int gain = b >> VOL_SCALE_SHIFT;
|
|
perex |
96d951 |
@@ -223,7 +241,7 @@ static inline short MULTI_DIV_short(short a, unsigned int b, int swap)
|
|
perex |
96d951 |
tmp = src[0] | \
|
|
perex |
96d951 |
(src[1] << 8) | \
|
|
perex |
96d951 |
(((signed char *) src)[2] << 16); \
|
|
perex |
96d951 |
- tmp = MULTI_DIV_int(tmp, vol_scale, 0); \
|
|
perex |
96d951 |
+ tmp = MULTI_DIV_24(tmp, vol_scale); \
|
|
perex |
96d951 |
dst[0] = tmp; \
|
|
perex |
96d951 |
dst[1] = tmp >> 8; \
|
|
perex |
96d951 |
dst[2] = tmp >> 16; \
|
|
perex |
96d951 |
--
|
|
perex |
96d951 |
1.5.5.1
|
|
perex |
96d951 |
|