add new API function pa_cvolume_remap()
authorLennart Poettering <lennart@poettering.net>
Mon, 4 Aug 2008 16:40:53 +0000 (18:40 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 4 Aug 2008 16:40:53 +0000 (18:40 +0200)
src/pulse/volume.c
src/pulse/volume.h

index 70d6f86..625eb19 100644 (file)
@@ -176,3 +176,88 @@ int pa_cvolume_valid(const pa_cvolume *v) {
 
     return 1;
 }
+
+static pa_bool_t on_left(pa_channel_position_t p) {
+
+    return
+        p == PA_CHANNEL_POSITION_FRONT_LEFT ||
+        p == PA_CHANNEL_POSITION_REAR_LEFT ||
+        p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
+        p == PA_CHANNEL_POSITION_SIDE_LEFT ||
+        p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
+        p == PA_CHANNEL_POSITION_TOP_REAR_LEFT;
+}
+
+static pa_bool_t on_right(pa_channel_position_t p) {
+
+    return
+        p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
+        p == PA_CHANNEL_POSITION_REAR_RIGHT ||
+        p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER ||
+        p == PA_CHANNEL_POSITION_SIDE_RIGHT ||
+        p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
+        p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
+}
+
+static pa_bool_t on_center(pa_channel_position_t p) {
+
+    return
+        p == PA_CHANNEL_POSITION_FRONT_CENTER ||
+        p == PA_CHANNEL_POSITION_REAR_CENTER ||
+        p == PA_CHANNEL_POSITION_TOP_CENTER ||
+        p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER ||
+        p == PA_CHANNEL_POSITION_TOP_REAR_CENTER;
+}
+
+static pa_bool_t on_lfe(pa_channel_position_t p) {
+    return
+        p == PA_CHANNEL_POSITION_LFE;
+}
+
+pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to) {
+    int a, b;
+    pa_cvolume result;
+
+    pa_assert(v);
+    pa_assert(from);
+    pa_assert(to);
+    pa_assert(v->channels == from->channels);
+
+    if (pa_channel_map_equal(from, to))
+        return v;
+
+    result.channels = to->channels;
+
+    for (b = 0; b < to->channels; b++) {
+        pa_volume_t k = 0;
+        int n = 0;
+
+        for (a = 0; a < from->channels; a++)
+            if (from->map[a] == to->map[b]) {
+                k += v->values[a];
+                n ++;
+            }
+
+        if (n <= 0) {
+            for (a = 0; a < from->channels; a++)
+                if ((on_left(from->map[a]) && on_left(to->map[b])) ||
+                    (on_right(from->map[a]) && on_right(to->map[b])) ||
+                    (on_center(from->map[a]) && on_center(to->map[b])) ||
+                    (on_lfe(from->map[a]) && on_lfe(to->map[b]))) {
+
+                    k += v->values[a];
+                    n ++;
+                }
+        }
+
+        if (n <= 0)
+            k = pa_cvolume_avg(v);
+        else
+            k /= n;
+
+        result.values[b] = k;
+    }
+
+    *v = result;
+    return v;
+}
index 3befb1d..4fdbf65 100644 (file)
@@ -28,6 +28,7 @@
 #include <pulse/cdecl.h>
 #include <pulse/gccmacro.h>
 #include <pulse/sample.h>
+#include <pulse/channelmap.h>
 
 /** \page volume Volume Control
  *
@@ -170,6 +171,9 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
 #define PA_DECIBEL_MININFTY ((double) -200.0)
 #endif
 
+/** Remap a volume from one channel mapping to a different channel mapping. \since 0.9.12 */
+pa_cvolume *pa_cvolume_remap(pa_cvolume *v, pa_channel_map *from, pa_channel_map *to);
+
 PA_C_DECL_END
 
 #endif