aboutsummaryrefslogtreecommitdiffstats
path: root/src/pcm/PcmChannels.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/pcm/PcmChannels.cxx')
-rw-r--r--src/pcm/PcmChannels.cxx297
1 files changed, 94 insertions, 203 deletions
diff --git a/src/pcm/PcmChannels.cxx b/src/pcm/PcmChannels.cxx
index eb69985c1..276f31045 100644
--- a/src/pcm/PcmChannels.cxx
+++ b/src/pcm/PcmChannels.cxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,9 @@
#include "config.h"
#include "PcmChannels.hxx"
#include "PcmBuffer.hxx"
-#include "PcmUtils.hxx"
+#include "Traits.hxx"
+#include "AudioFormat.hxx"
+#include "util/ConstBuffer.hxx"
#include <assert.h>
@@ -37,254 +39,143 @@ MonoToStereo(D dest, S src, S end)
}
-static void
-pcm_convert_channels_16_2_to_1(int16_t *gcc_restrict dest,
- const int16_t *gcc_restrict src,
- const int16_t *gcc_restrict src_end)
+template<SampleFormat F, class Traits=SampleTraits<F>>
+static typename Traits::value_type
+StereoToMono(typename Traits::value_type _a,
+ typename Traits::value_type _b)
{
- while (src < src_end) {
- int32_t a = *src++, b = *src++;
+ typename Traits::sum_type a(_a);
+ typename Traits::sum_type b(_b);
- *dest++ = (a + b) / 2;
- }
+ return typename Traits::value_type((a + b) / 2);
}
-static void
-pcm_convert_channels_16_n_to_2(int16_t *gcc_restrict dest,
- unsigned src_channels,
- const int16_t *gcc_restrict src,
- const int16_t *gcc_restrict src_end)
+template<SampleFormat F, class Traits=SampleTraits<F>>
+static typename Traits::pointer_type
+StereoToMono(typename Traits::pointer_type dest,
+ typename Traits::const_pointer_type src,
+ typename Traits::const_pointer_type end)
{
- unsigned c;
-
- assert(src_channels > 0);
-
- while (src < src_end) {
- int32_t sum = 0;
- int16_t value;
-
- for (c = 0; c < src_channels; ++c)
- sum += *src++;
- value = sum / (int)src_channels;
+ while (src != end) {
+ const auto a = *src++;
+ const auto b = *src++;
- /* XXX this is actually only mono ... */
- *dest++ = value;
- *dest++ = value;
+ *dest++ = StereoToMono<F, Traits>(a, b);
}
-}
-
-const int16_t *
-pcm_convert_channels_16(PcmBuffer &buffer,
- unsigned dest_channels,
- unsigned src_channels, const int16_t *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;
-
- int16_t *dest = (int16_t *)buffer.Get(dest_size);
- const int16_t *src_end = pcm_end_pointer(src, src_size);
-
- if (src_channels == 1 && dest_channels == 2)
- MonoToStereo(dest, src, src_end);
- else if (src_channels == 2 && dest_channels == 1)
- pcm_convert_channels_16_2_to_1(dest, src, src_end);
- else if (dest_channels == 2)
- pcm_convert_channels_16_n_to_2(dest, src_channels, src,
- src_end);
- else
- return nullptr;
return dest;
}
-static void
-pcm_convert_channels_24_2_to_1(int32_t *gcc_restrict dest,
- const int32_t *gcc_restrict src,
- const int32_t *gcc_restrict src_end)
-{
- while (src < src_end) {
- int32_t a = *src++, b = *src++;
-
- *dest++ = (a + b) / 2;
- }
-}
-
-static void
-pcm_convert_channels_24_n_to_2(int32_t *gcc_restrict dest,
- unsigned src_channels,
- const int32_t *gcc_restrict src,
- const int32_t *gcc_restrict src_end)
+template<SampleFormat F, class Traits=SampleTraits<F>>
+static typename Traits::pointer_type
+NToStereo(typename Traits::pointer_type dest,
+ unsigned src_channels,
+ typename Traits::const_pointer_type src,
+ typename Traits::const_pointer_type end)
{
- unsigned c;
+ assert((end - src) % src_channels == 0);
- assert(src_channels > 0);
-
- while (src < src_end) {
- int32_t sum = 0;
- int32_t value;
-
- for (c = 0; c < src_channels; ++c)
+ while (src != end) {
+ typename Traits::sum_type sum = *src++;
+ for (unsigned c = 1; c < src_channels; ++c)
sum += *src++;
- value = sum / (int)src_channels;
- /* XXX this is actually only mono ... */
+ typename Traits::value_type value(sum / int(src_channels));
+
+ /* TODO: this is actually only mono ... */
*dest++ = value;
*dest++ = value;
}
-}
-
-const int32_t *
-pcm_convert_channels_24(PcmBuffer &buffer,
- unsigned dest_channels,
- unsigned src_channels, const int32_t *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;
-
- int32_t *dest = (int32_t *)buffer.Get(dest_size);
- const int32_t *src_end = (const int32_t *)
- pcm_end_pointer(src, src_size);
-
- if (src_channels == 1 && dest_channels == 2)
- MonoToStereo(dest, src, src_end);
- else if (src_channels == 2 && dest_channels == 1)
- pcm_convert_channels_24_2_to_1(dest, src, src_end);
- else if (dest_channels == 2)
- pcm_convert_channels_24_n_to_2(dest, src_channels, src,
- src_end);
- else
- return nullptr;
return dest;
}
-static void
-pcm_convert_channels_32_2_to_1(int32_t *gcc_restrict dest,
- const int32_t *gcc_restrict src,
- const int32_t *gcc_restrict src_end)
-{
- while (src < src_end) {
- int64_t a = *src++, b = *src++;
-
- *dest++ = (a + b) / 2;
- }
-}
-
-static void
-pcm_convert_channels_32_n_to_2(int32_t *dest,
- unsigned src_channels, const int32_t *src,
- const int32_t *src_end)
+template<SampleFormat F, class Traits=SampleTraits<F>>
+static typename Traits::pointer_type
+NToM(typename Traits::pointer_type dest,
+ unsigned dest_channels,
+ unsigned src_channels,
+ typename Traits::const_pointer_type src,
+ typename Traits::const_pointer_type end)
{
- unsigned c;
+ assert((end - src) % src_channels == 0);
- assert(src_channels > 0);
-
- while (src < src_end) {
- int64_t sum = 0;
- int32_t value;
-
- for (c = 0; c < src_channels; ++c)
+ while (src != end) {
+ typename Traits::sum_type sum = *src++;
+ for (unsigned c = 1; c < src_channels; ++c)
sum += *src++;
- value = sum / (int64_t)src_channels;
- /* XXX this is actually only mono ... */
- *dest++ = value;
- *dest++ = value;
+ typename Traits::value_type value(sum / int(src_channels));
+
+ /* TODO: this is actually only mono ... */
+ for (unsigned c = 0; c < dest_channels; ++c)
+ *dest++ = value;
}
+
+ return dest;
}
-const int32_t *
-pcm_convert_channels_32(PcmBuffer &buffer,
- unsigned dest_channels,
- unsigned src_channels, const int32_t *src,
- size_t src_size, size_t *dest_size_r)
+template<SampleFormat F, class Traits=SampleTraits<F>>
+static ConstBuffer<typename Traits::value_type>
+ConvertChannels(PcmBuffer &buffer,
+ unsigned dest_channels,
+ unsigned src_channels,
+ ConstBuffer<typename Traits::value_type> src)
{
- assert(src_size % (sizeof(*src) * src_channels) == 0);
-
- size_t dest_size = src_size / src_channels * dest_channels;
- *dest_size_r = dest_size;
+ assert(src.size % src_channels == 0);
- int32_t *dest = (int32_t *)buffer.Get(dest_size);
- const int32_t *src_end = (const int32_t *)
- pcm_end_pointer(src, src_size);
+ const size_t dest_size = src.size / src_channels * dest_channels;
+ auto dest = buffer.GetT<typename Traits::value_type>(dest_size);
if (src_channels == 1 && dest_channels == 2)
- MonoToStereo(dest, src, src_end);
+ MonoToStereo(dest, src.begin(), src.end());
else if (src_channels == 2 && dest_channels == 1)
- pcm_convert_channels_32_2_to_1(dest, src, src_end);
+ StereoToMono<F>(dest, src.begin(), src.end());
else if (dest_channels == 2)
- pcm_convert_channels_32_n_to_2(dest, src_channels, src,
- src_end);
+ NToStereo<F>(dest, src_channels, src.begin(), src.end());
else
- return nullptr;
+ NToM<F>(dest, dest_channels,
+ src_channels, src.begin(), src.end());
- return dest;
+ return { dest, dest_size };
}
-static void
-pcm_convert_channels_float_2_to_1(float *gcc_restrict dest,
- const float *gcc_restrict src,
- const float *gcc_restrict src_end)
+ConstBuffer<int16_t>
+pcm_convert_channels_16(PcmBuffer &buffer,
+ unsigned dest_channels,
+ unsigned src_channels,
+ ConstBuffer<int16_t> src)
{
- while (src < src_end) {
- double a = *src++, b = *src++;
-
- *dest++ = (a + b) / 2;
- }
+ return ConvertChannels<SampleFormat::S16>(buffer, dest_channels,
+ src_channels, src);
}
-static void
-pcm_convert_channels_float_n_to_2(float *dest,
- unsigned src_channels, const float *src,
- const float *src_end)
+ConstBuffer<int32_t>
+pcm_convert_channels_24(PcmBuffer &buffer,
+ unsigned dest_channels,
+ unsigned src_channels,
+ ConstBuffer<int32_t> src)
{
- 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;
+ return ConvertChannels<SampleFormat::S24_P32>(buffer, dest_channels,
+ src_channels, src);
+}
- /* XXX this is actually only mono ... */
- *dest++ = value;
- *dest++ = value;
- }
+ConstBuffer<int32_t>
+pcm_convert_channels_32(PcmBuffer &buffer,
+ unsigned dest_channels,
+ unsigned src_channels,
+ ConstBuffer<int32_t> src)
+{
+ return ConvertChannels<SampleFormat::S32>(buffer, dest_channels,
+ src_channels, src);
}
-const float *
+ConstBuffer<float>
pcm_convert_channels_float(PcmBuffer &buffer,
unsigned dest_channels,
- unsigned src_channels, const float *src,
- size_t src_size, size_t *dest_size_r)
+ unsigned src_channels,
+ ConstBuffer<float> src)
{
- 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 = (float *)buffer.Get(dest_size);
- const float *src_end = (const float *)pcm_end_pointer(src, src_size);
-
- if (src_channels == 1 && dest_channels == 2)
- MonoToStereo(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 nullptr;
-
- return dest;
+ return ConvertChannels<SampleFormat::FLOAT>(buffer, dest_channels,
+ src_channels, src);
}