]> code.delx.au - pulseaudio/blobdiff - polyp/sample-util.c
* add support for asynchronous name resolution
[pulseaudio] / polyp / sample-util.c
index d608ce1bc105533ed0dc2d78377be07de58ed7f7..d521afe4a15f68ef5f6fe0fdd9be70cecad6f73c 100644 (file)
@@ -4,7 +4,7 @@
   This file is part of polypaudio.
  
   polypaudio is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
+  it under the terms of the GNU Lesser General Public License as published
   by the Free Software Foundation; either version 2 of the License,
   or (at your option) any later version.
  
@@ -13,7 +13,7 @@
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.
  
-  You should have received a copy of the GNU General Public License
+  You should have received a copy of the GNU Lesser General Public License
   along with polypaudio; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA.
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
+#include <stdlib.h>
 
 #include "sample-util.h"
 
@@ -37,16 +38,16 @@ struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_s
 
 void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec) {
     assert(c && c->memblock && c->memblock->data && spec && c->length);
-    pa_silence_memory(c->memblock->data+c->index, c->length, spec);
+    pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec);
 }
 
 void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec) {
-    char c = 0;
+    uint8_t c = 0;
     assert(p && length && spec);
 
     switch (spec->format) {
         case PA_SAMPLE_U8:
-            c = 127;
+            c = 0x80;
             break;
         case PA_SAMPLE_S16LE:
         case PA_SAMPLE_S16BE:
@@ -64,81 +65,204 @@ void pa_silence_memory(void *p, size_t length, const struct pa_sample_spec *spec
     memset(p, c, length);
 }
 
-size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, uint32_t volume) {
-    unsigned c, d;
+size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const struct pa_sample_spec *spec, pa_volume_t volume) {
     assert(channels && data && length && spec);
-    assert(spec->format == PA_SAMPLE_S16NE);
-
-    for (d = 0;; d += sizeof(int16_t)) {
-        int32_t sum = 0;
-
-        if (d >= length)
-            return d;
+    
+    if (spec->format == PA_SAMPLE_S16NE) {
+        size_t d;
         
-        for (c = 0; c < nchannels; c++) {
-            int32_t v;
-            uint32_t volume = channels[c].volume;
+        for (d = 0;; d += sizeof(int16_t)) {
+            unsigned c;
+            int32_t sum = 0;
             
-            if (d >= channels[c].chunk.length)
+            if (d >= length)
                 return d;
-
-            if (volume == PA_VOLUME_MUTE)
-                v = 0;
-            else {
-                v = *((int16_t*) (channels[c].chunk.memblock->data + channels[c].chunk.index + d));
-
-                if (volume != PA_VOLUME_NORM)
-                    v = (int32_t) ((float)v*volume/PA_VOLUME_NORM);
+            
+            for (c = 0; c < nchannels; c++) {
+                int32_t v;
+                pa_volume_t cvolume = channels[c].volume;
+                
+                if (d >= channels[c].chunk.length)
+                    return d;
+                
+                if (cvolume == PA_VOLUME_MUTED)
+                    v = 0;
+                else {
+                    v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
+                    
+                    if (cvolume != PA_VOLUME_NORM) {
+                        v *= cvolume;
+                        v /= PA_VOLUME_NORM;
+                    }
+                }
+                
+                sum += v;
             }
-
-            sum += v;
+            
+            if (volume == PA_VOLUME_MUTED)
+                sum = 0;
+            else if (volume != PA_VOLUME_NORM) {
+                sum *= volume;
+                sum /= PA_VOLUME_NORM;
+            }
+            
+            if (sum < -0x8000) sum = -0x8000;
+            if (sum > 0x7FFF) sum = 0x7FFF;
+            
+            *((int16_t*) data) = sum;
+            data = (uint8_t*) data + sizeof(int16_t);
+        }
+    } else if (spec->format == PA_SAMPLE_U8) {
+        size_t d;
+        
+        for (d = 0;; d ++) {
+            int32_t sum = 0;
+            unsigned c;
+            
+            if (d >= length)
+                return d;
+            
+            for (c = 0; c < nchannels; c++) {
+                int32_t v;
+                pa_volume_t cvolume = channels[c].volume;
+                
+                if (d >= channels[c].chunk.length)
+                    return d;
+                
+                if (cvolume == PA_VOLUME_MUTED)
+                    v = 0;
+                else {
+                    v = (int32_t) *((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d) - 0x80;
+                    
+                    if (cvolume != PA_VOLUME_NORM) {
+                        v *= cvolume;
+                        v /= PA_VOLUME_NORM;
+                    }
+                }
+                
+                sum += v;
+            }
+            
+            if (volume == PA_VOLUME_MUTED)
+                sum = 0;
+            else if (volume != PA_VOLUME_NORM) {
+                sum *= volume;
+                sum /= PA_VOLUME_NORM;
+            }
+            
+            if (sum < -0x80) sum = -0x80;
+            if (sum > 0x7F) sum = 0x7F;
+            
+            *((uint8_t*) data) = (uint8_t) (sum + 0x80);
+            data = (uint8_t*) data + 1;
         }
-
-        if (volume == PA_VOLUME_MUTE)
-            sum = 0;
-        else if (volume != PA_VOLUME_NORM)
-            sum = (int32_t) ((float) sum*volume/PA_VOLUME_NORM);
         
-        if (sum < -0x8000) sum = -0x8000;
-        if (sum > 0x7FFF) sum = 0x7FFF;
+    } else if (spec->format == PA_SAMPLE_FLOAT32NE) {
+        size_t d;
         
-        *((int16_t*) data) = sum;
-        data += sizeof(int16_t);
+        for (d = 0;; d += sizeof(float)) {
+            float_t sum = 0;
+            unsigned c;
+            
+            if (d >= length)
+                return d;
+            
+            for (c = 0; c < nchannels; c++) {
+                float v;
+                pa_volume_t cvolume = channels[c].volume;
+                
+                if (d >= channels[c].chunk.length)
+                    return d;
+                
+                if (cvolume == PA_VOLUME_MUTED)
+                    v = 0;
+                else {
+                    v = *((float*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
+                    
+                    if (cvolume != PA_VOLUME_NORM)
+                        v = v*cvolume/PA_VOLUME_NORM;
+                }
+                
+                sum += v;
+            }
+            
+            if (volume == PA_VOLUME_MUTED)
+                sum = 0;
+            else if (volume != PA_VOLUME_NORM)
+                sum = sum*volume/PA_VOLUME_NORM;
+            
+            if (sum < -1) sum = -1;
+            if (sum > 1) sum = 1;
+            
+            *((float*) data) = sum;
+            data = (uint8_t*) data + sizeof(float);
+        }
+    } else {
+        abort();
     }
 }
 
 
-void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume) {
-    int16_t *d;
-    size_t n;
-    assert(c && spec && (c->length % pa_sample_size(spec) == 0));
-    assert(spec->format == PA_SAMPLE_S16NE);
+void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, pa_volume_t volume) {
+    assert(c && spec && (c->length % pa_frame_size(spec) == 0));
 
     if (volume == PA_VOLUME_NORM)
         return;
 
-    if (volume == PA_VOLUME_MUTE) {
+    if (volume == PA_VOLUME_MUTED) {
         pa_silence_memchunk(c, spec);
         return;
     }
 
-    for (d = (c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
-        int32_t t = (int32_t)(*d);
+    if (spec->format == PA_SAMPLE_S16NE) {
+        int16_t *d;
+        size_t n;
+        
+        for (d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
+            int32_t t = (int32_t)(*d);
+            
+            t *= volume;
+            t /= PA_VOLUME_NORM;
+            
+            if (t < -0x8000) t = -0x8000;
+            if (t > 0x7FFF) t = 0x7FFF;
+            
+            *d = (int16_t) t;
+        }
+    } else if (spec->format == PA_SAMPLE_U8) {
+        uint8_t *d;
+        size_t n;
+
+        for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
+            int32_t t = (int32_t) *d - 0x80;
+
+            t *= volume;
+            t /= PA_VOLUME_NORM;
 
-        t *= volume;
-        t /= PA_VOLUME_NORM;
+            if (t < -0x80) t = -0x80;
+            if (t > 0x7F) t = 0x7F;
+
+            *d = (uint8_t) (t + 0x80);
+            
+        }
+    } else if (spec->format == PA_SAMPLE_FLOAT32NE) {
+        float *d;
+        size_t n;
 
-        if (t < -0x8000) t = -0x8000;
-        if (t > 0x7FFF) t = 0x7FFF;
+        for (d = (float*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(float); n > 0; d++, n--) {
+            float t = *d;
+
+            t *= volume;
+            t /= PA_VOLUME_NORM;
+
+            if (t < -1) t = -1;
+            if (t > 1) t = 1;
+
+            *d = t;
+        }
         
-        *d = (int16_t) t;
+    } else {
+        abort();
     }
 }
 
-uint32_t pa_volume_multiply(uint32_t a, uint32_t b) {
-    uint64_t p = a;
-    p *= b;
-    p /= PA_VOLUME_NORM;
-
-    return (uint32_t) p;
-}