aboutsummaryrefslogtreecommitdiffstats
path: root/src/pcm_channels.c
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2012-10-02 08:29:52 +0200
committerMax Kellermann <max@duempel.org>2012-10-02 08:39:12 +0200
commite166ddf46f16ca115372bc05a880e47deafc23c1 (patch)
tree285d5607f5b9e894d8815e043e6b01137bb96876 /src/pcm_channels.c
parent31e1be75709e7ca69184b9277cfe13e71594b029 (diff)
downloadmpd-e166ddf46f16ca115372bc05a880e47deafc23c1.tar.gz
mpd-e166ddf46f16ca115372bc05a880e47deafc23c1.tar.xz
mpd-e166ddf46f16ca115372bc05a880e47deafc23c1.zip
pcm_channels: support floating point samples
Diffstat (limited to 'src/pcm_channels.c')
-rw-r--r--src/pcm_channels.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/pcm_channels.c b/src/pcm_channels.c
index ec2bd69a5..9d166a437 100644
--- a/src/pcm_channels.c
+++ b/src/pcm_channels.c
@@ -244,3 +244,74 @@ pcm_convert_channels_32(struct pcm_buffer *buffer,
return dest;
}
+
+static void
+pcm_convert_channels_float_1_to_2(float *dest, const float *src,
+ const float *src_end)
+{
+ pcm_convert_channels_24_1_to_2((int32_t *)dest,
+ (const int32_t *)src,
+ (const int32_t *)src_end);
+}
+
+static void
+pcm_convert_channels_float_2_to_1(float *restrict dest,
+ const float *restrict src,
+ const float *restrict src_end)
+{
+ while (src < src_end) {
+ double a = *src++, b = *src++;
+
+ *dest++ = (a + b) / 2;
+ }
+}
+
+static void
+pcm_convert_channels_float_n_to_2(float *dest,
+ unsigned src_channels, const float *src,
+ const float *src_end)
+{
+ unsigned c;
+
+ assert(src_channels > 0);
+
+ while (src < src_end) {
+ double sum = 0;
+ float value;
+
+ for (c = 0; c < src_channels; ++c)
+ sum += *src++;
+ value = sum / (double)src_channels;
+
+ /* XXX this is actually only mono ... */
+ *dest++ = value;
+ *dest++ = value;
+ }
+}
+
+const float *
+pcm_convert_channels_float(struct pcm_buffer *buffer,
+ unsigned dest_channels,
+ unsigned src_channels, const float *src,
+ size_t src_size, size_t *dest_size_r)
+{
+ assert(src_size % (sizeof(*src) * src_channels) == 0);
+
+ size_t dest_size = src_size / src_channels * dest_channels;
+ *dest_size_r = dest_size;
+
+ float *dest = pcm_buffer_get(buffer, dest_size);
+ const float *src_end = pcm_end_pointer(src, src_size);
+
+ if (src_channels == 1 && dest_channels == 2)
+ pcm_convert_channels_float_1_to_2(dest, src, src_end);
+ else if (src_channels == 2 && dest_channels == 1)
+ pcm_convert_channels_float_2_to_1(dest, src, src_end);
+ else if (dest_channels == 2)
+ pcm_convert_channels_float_n_to_2(dest, src_channels, src,
+ src_end);
+ else
+ return NULL;
+
+ return dest;
+}