diff options
author | Max Kellermann <max@duempel.org> | 2013-12-02 09:36:56 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-12-02 11:28:54 +0100 |
commit | 71b47ae3efc1c683c07ea6d682b0b7d876f35457 (patch) | |
tree | 0f5c1e30bff743cc6151fe1188b1e2af704dffb8 | |
parent | 36e3fda554921ef4024cfb6c61f0ba981b7c963c (diff) |
pcm/PcmChannels: use the SampleTraits library
-rw-r--r-- | src/pcm/PcmChannels.cxx | 242 |
1 files changed, 60 insertions, 182 deletions
diff --git a/src/pcm/PcmChannels.cxx b/src/pcm/PcmChannels.cxx index 74f9416f9..8f00c01be 100644 --- a/src/pcm/PcmChannels.cxx +++ b/src/pcm/PcmChannels.cxx @@ -20,6 +20,8 @@ #include "config.h" #include "PcmChannels.hxx" #include "PcmBuffer.hxx" +#include "Traits.hxx" +#include "AudioFormat.hxx" #include "util/ConstBuffer.hxx" #include <assert.h> @@ -37,100 +39,89 @@ 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::long_type a(_a); + typename Traits::long_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; + while (src != end) { + const auto a = *src++; + const auto b = *src++; - assert(src_channels > 0); + *dest++ = StereoToMono<F, Traits>(a, b); + } + + return dest; +} - while (src < src_end) { - int32_t sum = 0; - int16_t value; +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) +{ + assert((end - src) % src_channels == 0); - for (c = 0; c < src_channels; ++c) + while (src != end) { + typename Traits::long_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; } + + return dest; } -ConstBuffer<int16_t> -pcm_convert_channels_16(PcmBuffer &buffer, - unsigned dest_channels, - unsigned src_channels, - ConstBuffer<int16_t> src) +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 % src_channels == 0); const size_t dest_size = src.size / src_channels * dest_channels; - int16_t *dest = buffer.GetT<int16_t>(dest_size); + auto dest = buffer.GetT<typename Traits::value_type>(dest_size); if (src_channels == 1 && dest_channels == 2) MonoToStereo(dest, src.begin(), src.end()); else if (src_channels == 2 && dest_channels == 1) - pcm_convert_channels_16_2_to_1(dest, src.begin(), src.end()); + StereoToMono<F>(dest, src.begin(), src.end()); else if (dest_channels == 2) - pcm_convert_channels_16_n_to_2(dest, src_channels, - src.begin(), src.end()); + NToStereo<F>(dest, src_channels, src.begin(), src.end()); else return nullptr; return { dest, dest_size }; } -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) +ConstBuffer<int16_t> +pcm_convert_channels_16(PcmBuffer &buffer, + unsigned dest_channels, + unsigned src_channels, + ConstBuffer<int16_t> src) { - unsigned c; - - assert(src_channels > 0); - - while (src < src_end) { - int32_t sum = 0; - int32_t value; - - for (c = 0; c < src_channels; ++c) - sum += *src++; - value = sum / (int)src_channels; - - /* XXX this is actually only mono ... */ - *dest++ = value; - *dest++ = value; - } + return ConvertChannels<SampleFormat::S16>(buffer, dest_channels, + src_channels, src); } ConstBuffer<int32_t> @@ -139,57 +130,8 @@ pcm_convert_channels_24(PcmBuffer &buffer, unsigned src_channels, ConstBuffer<int32_t> src) { - assert(src.size % src_channels == 0); - - size_t dest_size = src.size / src_channels * dest_channels; - int32_t *dest = buffer.GetT<int32_t>(dest_size); - - if (src_channels == 1 && dest_channels == 2) - MonoToStereo(dest, src.begin(), src.end()); - else if (src_channels == 2 && dest_channels == 1) - pcm_convert_channels_24_2_to_1(dest, src.begin(), src.end()); - else if (dest_channels == 2) - pcm_convert_channels_24_n_to_2(dest, src_channels, - src.begin(), src.end()); - else - return nullptr; - - return { dest, dest_size }; -} - -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) -{ - unsigned c; - - assert(src_channels > 0); - - while (src < src_end) { - int64_t sum = 0; - int32_t value; - - for (c = 0; c < src_channels; ++c) - sum += *src++; - value = sum / (int64_t)src_channels; - - /* XXX this is actually only mono ... */ - *dest++ = value; - *dest++ = value; - } + return ConvertChannels<SampleFormat::S24_P32>(buffer, dest_channels, + src_channels, src); } ConstBuffer<int32_t> @@ -198,57 +140,8 @@ pcm_convert_channels_32(PcmBuffer &buffer, unsigned src_channels, ConstBuffer<int32_t> src) { - assert(src.size % src_channels == 0); - - size_t dest_size = src.size / src_channels * dest_channels; - int32_t *dest = buffer.GetT<int32_t>(dest_size); - - if (src_channels == 1 && dest_channels == 2) - MonoToStereo(dest, src.begin(), src.end()); - else if (src_channels == 2 && dest_channels == 1) - pcm_convert_channels_32_2_to_1(dest, src.begin(), src.end()); - else if (dest_channels == 2) - pcm_convert_channels_32_n_to_2(dest, src_channels, - src.begin(), src.end()); - else - return nullptr; - - 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) -{ - 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; - } + return ConvertChannels<SampleFormat::S32>(buffer, dest_channels, + src_channels, src); } ConstBuffer<float> @@ -257,21 +150,6 @@ pcm_convert_channels_float(PcmBuffer &buffer, unsigned src_channels, ConstBuffer<float> src) { - assert(src.size % src_channels == 0); - - size_t dest_size = src.size / src_channels * dest_channels; - float *dest = buffer.GetT<float>(dest_size); - - if (src_channels == 1 && dest_channels == 2) - MonoToStereo(dest, src.begin(), src.end()); - else if (src_channels == 2 && dest_channels == 1) - pcm_convert_channels_float_2_to_1(dest, - src.begin(), src.end()); - else if (dest_channels == 2) - pcm_convert_channels_float_n_to_2(dest, src_channels, - src.begin(), src.end()); - else - return nullptr; - - return { dest, dest_size }; + return ConvertChannels<SampleFormat::FLOAT>(buffer, dest_channels, + src_channels, src); } |