[RFC PATCH] softvolume: implement fast volume translation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



if all channels have same volume setting, use fast way to
do volume change. this patch intended to work for two formats:
s16ne/s16re.

Signed-off-by: Wang Xingchao <xingchao.wang at intel.com>
---
 src/pulsecore/svolume_c.c |   70 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/src/pulsecore/svolume_c.c b/src/pulsecore/svolume_c.c
index 272e7a7..7919faa 100644
--- a/src/pulsecore/svolume_c.c
+++ b/src/pulsecore/svolume_c.c
@@ -90,9 +90,43 @@ static void pa_volume_ulaw_c(uint8_t *samples, int32_t *volumes, unsigned channe
 
 static void pa_volume_s16ne_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
     unsigned channel;
+    int32_t same_vol = volumes[0];
+    unsigned fast_vol;
 
     length /= sizeof(int16_t);
 
+    for (channel = 0; channel < channels; channel++) {
+	    if (volumes[channel] != same_vol)
+		    break;
+    }
+
+    fast_vol = channel < channels? 0 : 1;
+
+    if (fast_vol) {
+	int32_t t, hi, lo;
+	int32_t ht, lt;
+
+	hi = same_vol >> 16;
+	lo = same_vol & 0xffff;
+	while (length) {
+		t = *((int32_t *)samples);	
+		ht = t >> 16; 
+		lt = t & 0xffff;
+
+        	ht = ((ht * lo) >> 16) + (ht * hi);
+	        ht = PA_CLAMP_UNLIKELY(ht, -0x8000, 0x7FFF);
+
+        	lt = ((lt * lo) >> 16) + (lt * hi);
+	        lt = PA_CLAMP_UNLIKELY(lt, -0x8000, 0x7FFF);
+		
+		*((int32_t *)samples) = ht<<16|lt;
+
+		samples += 2;
+		length -= 2;
+	}
+
+	return;
+    }
     for (channel = 0; length; length--) {
         int32_t t, hi, lo;
 
@@ -117,9 +151,45 @@ static void pa_volume_s16ne_c(int16_t *samples, int32_t *volumes, unsigned chann
 
 static void pa_volume_s16re_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
     unsigned channel;
+    int32_t same_vol = volumes[0];
+    unsigned fast_vol;
 
     length /= sizeof(int16_t);
 
+    for (channel = 0; channel < channels; channel++) {
+	    if (volumes[channel] != same_vol)
+		    break;
+    }
+
+    fast_vol = channel < channels? 0 : 1;
+
+    if (fast_vol) {
+	int32_t t, hi, lo;
+	int32_t ht, lt;
+
+	hi = same_vol >> 16;
+	lo = same_vol & 0xffff;
+
+	while (length) {
+		t = *((int32_t *)samples);	
+		ht = (int32_t)PA_INT16_SWAP((int16_t)(t >> 16)); 
+		lt = (int32_t)PA_INT16_SWAP((int16_t)(t & 0xffff));
+
+        	ht = ((ht * lo) >> 16) + (ht * hi);
+	        ht = PA_CLAMP_UNLIKELY(ht, -0x8000, 0x7FFF);
+
+        	lt = ((lt * lo) >> 16) + (lt * hi);
+	        lt = PA_CLAMP_UNLIKELY(lt, -0x8000, 0x7FFF);
+		
+		*((int32_t *)samples) = PA_INT16_SWAP((int16_t) ht<<16)|PA_INT16_SWAP((int16_t) lt);
+
+		samples += 2;
+		length -= 2;
+	}
+
+	return;
+    }
+
     for (channel = 0; length; length--) {
         int32_t t, hi, lo;
 
-- 
1.7.1



[Index of Archives]     [Linux Audio Users]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux