From 86a0f9cf9b9cddb60a4fb58c7ef187d220e8abfd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 31 Jan 2013 22:07:10 +0100 Subject: PcmFormat: merge duplicate code with a template --- src/PcmFormat.cxx | 145 ++++++++++++++++++++++++++---------------------------- src/PcmUtils.hxx | 39 +++++++++------ 2 files changed, 95 insertions(+), 89 deletions(-) diff --git a/src/PcmFormat.cxx b/src/PcmFormat.cxx index 50e15c91..1385d161 100644 --- a/src/PcmFormat.cxx +++ b/src/PcmFormat.cxx @@ -24,6 +24,16 @@ #include "pcm_pack.h" #include "PcmUtils.hxx" +#include + +template +struct DefaultSampleBits { + typedef decltype(*S()) T; + typedef typename std::remove_reference::type U; + + static constexpr auto value = sizeof(U) * 8; +}; + static void pcm_convert_8_to_16(int16_t *out, const int8_t *in, const int8_t *in_end) { @@ -46,18 +56,43 @@ pcm_convert_32_to_16(PcmDither &dither, dither.Dither32To16(out, in, in_end); } +template::value> static void -pcm_convert_float_to_16(int16_t *out, const float *in, const float *in_end) +ConvertFromFloat(S dest, const float *src, const float *end) { - const unsigned OUT_BITS = 16; - const float factor = 1 << (OUT_BITS - 1); + typedef decltype(*S()) T; + typedef typename std::remove_reference::type U; - while (in < in_end) { - int sample = *in++ * factor; - *out++ = pcm_clamp_16(sample); + const float factor = 1 << (bits - 1); + + while (src != end) { + int sample(*src++ * factor); + *dest++ = PcmClamp(sample); } } +template::value> +static void +ConvertFromFloat(S dest, const float *src, size_t size) +{ + ConvertFromFloat(dest, src, pcm_end_pointer(src, size)); +} + +template +static S * +AllocateFromFloat(pcm_buffer &buffer, const float *src, size_t src_size, + size_t *dest_size_r) +{ + constexpr size_t src_sample_size = sizeof(*src); + assert(src_size % src_sample_size == 0); + + const size_t num_samples = src_size / src_sample_size; + *dest_size_r = num_samples * sizeof(S); + S *dest = (S *)pcm_buffer_get(&buffer, *dest_size_r); + ConvertFromFloat(dest, src, src_size); + return dest; +} + static int16_t * pcm_allocate_8_to_16(struct pcm_buffer *buffer, const int8_t *src, size_t src_size, size_t *dest_size_r) @@ -102,13 +137,7 @@ pcm_allocate_float_to_16(struct pcm_buffer *buffer, const float *src, size_t src_size, size_t *dest_size_r) { - int16_t *dest; - *dest_size_r = src_size / 2; - assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest)); - dest = (int16_t *)pcm_buffer_get(buffer, *dest_size_r); - pcm_convert_float_to_16(dest, src, - pcm_end_pointer(src, src_size)); - return dest; + return AllocateFromFloat(*buffer, src, src_size, dest_size_r); } const int16_t * @@ -174,18 +203,6 @@ pcm_convert_32_to_24(int32_t *restrict out, *out++ = *in++ >> 8; } -static void -pcm_convert_float_to_24(int32_t *out, const float *in, const float *in_end) -{ - const unsigned OUT_BITS = 24; - const float factor = 1 << (OUT_BITS - 1); - - while (in < in_end) { - int sample = *in++ * factor; - *out++ = pcm_clamp_24(sample); - } -} - static int32_t * pcm_allocate_8_to_24(struct pcm_buffer *buffer, const int8_t *src, size_t src_size, size_t *dest_size_r) @@ -224,10 +241,8 @@ pcm_allocate_float_to_24(struct pcm_buffer *buffer, const float *src, size_t src_size, size_t *dest_size_r) { - *dest_size_r = src_size; - int32_t *dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r); - pcm_convert_float_to_24(dest, src, pcm_end_pointer(src, src_size)); - return dest; + return AllocateFromFloat(*buffer, src, src_size, + dest_size_r); } const int32_t * @@ -381,40 +396,36 @@ pcm_convert_to_32(struct pcm_buffer *buffer, return NULL; } +template::value> static void -pcm_convert_8_to_float(float *out, const int8_t *in, const int8_t *in_end) +ConvertToFloat(float *dest, S src, S end) { - enum { in_bits = sizeof(*in) * 8 }; - static const float factor = 2.0f / (1 << in_bits); - while (in < in_end) - *out++ = (float)*in++ * factor; -} + constexpr float factor = 0.5 / (1 << (bits - 2)); + while (src != end) + *dest++ = float(*src++) * factor; -static void -pcm_convert_16_to_float(float *out, const int16_t *in, const int16_t *in_end) -{ - enum { in_bits = sizeof(*in) * 8 }; - static const float factor = 2.0f / (1 << in_bits); - while (in < in_end) - *out++ = (float)*in++ * factor; } +template::value> static void -pcm_convert_24_to_float(float *out, const int32_t *in, const int32_t *in_end) +ConvertToFloat(float *dest, S src, size_t size) { - enum { in_bits = 24 }; - static const float factor = 2.0f / (1 << in_bits); - while (in < in_end) - *out++ = (float)*in++ * factor; + ConvertToFloat(dest, src, pcm_end_pointer(src, size)); } -static void -pcm_convert_32_to_float(float *out, const int32_t *in, const int32_t *in_end) +template::value> +static float * +AllocateToFloat(pcm_buffer &buffer, S src, size_t src_size, + size_t *dest_size_r) { - enum { in_bits = sizeof(*in) * 8 }; - static const float factor = 0.5f / (1 << (in_bits - 2)); - while (in < in_end) - *out++ = (float)*in++ * factor; + constexpr size_t src_sample_size = sizeof(*S()); + assert(src_size % src_sample_size == 0); + + const size_t num_samples = src_size / src_sample_size; + *dest_size_r = num_samples * sizeof(float); + float *dest = (float *)pcm_buffer_get(&buffer, *dest_size_r); + ConvertToFloat(dest, src, src_size); + return dest; } static float * @@ -422,11 +433,7 @@ pcm_allocate_8_to_float(struct pcm_buffer *buffer, const int8_t *src, size_t src_size, size_t *dest_size_r) { - float *dest; - *dest_size_r = src_size / sizeof(*src) * sizeof(*dest); - dest = (float *)pcm_buffer_get(buffer, *dest_size_r); - pcm_convert_8_to_float(dest, src, pcm_end_pointer(src, src_size)); - return dest; + return AllocateToFloat(*buffer, src, src_size, dest_size_r); } static float * @@ -434,23 +441,16 @@ pcm_allocate_16_to_float(struct pcm_buffer *buffer, const int16_t *src, size_t src_size, size_t *dest_size_r) { - float *dest; - *dest_size_r = src_size * 2; - assert(*dest_size_r == src_size / sizeof(*src) * sizeof(*dest)); - dest = (float *)pcm_buffer_get(buffer, *dest_size_r); - pcm_convert_16_to_float(dest, src, pcm_end_pointer(src, src_size)); - return dest; + return AllocateToFloat(*buffer, src, src_size, dest_size_r); } static float * pcm_allocate_24p32_to_float(struct pcm_buffer *buffer, - const int32_t *src, size_t src_size, - size_t *dest_size_r) + const int32_t *src, size_t src_size, + size_t *dest_size_r) { - *dest_size_r = src_size; - float *dest = (float *)pcm_buffer_get(buffer, *dest_size_r); - pcm_convert_24_to_float(dest, src, pcm_end_pointer(src, src_size)); - return dest; + return AllocateToFloat + (*buffer, src, src_size, dest_size_r); } static float * @@ -458,10 +458,7 @@ pcm_allocate_32_to_float(struct pcm_buffer *buffer, const int32_t *src, size_t src_size, size_t *dest_size_r) { - *dest_size_r = src_size; - float *dest = (float *)pcm_buffer_get(buffer, *dest_size_r); - pcm_convert_32_to_float(dest, src, pcm_end_pointer(src, src_size)); - return dest; + return AllocateToFloat(*buffer, src, src_size, dest_size_r); } const float * diff --git a/src/PcmUtils.hxx b/src/PcmUtils.hxx index a95af7e6..5683a167 100644 --- a/src/PcmUtils.hxx +++ b/src/PcmUtils.hxx @@ -22,6 +22,8 @@ #include "gcc.h" +#include + #include /** @@ -64,32 +66,39 @@ pcm_range_64(int64_t sample, unsigned bits) return sample; } +template gcc_const -static inline int16_t -pcm_clamp_16(int x) +static inline T +PcmClamp(U x) { - static const int32_t MIN_VALUE = -(1 << 15); - static const int32_t MAX_VALUE = (1 << 15) - 1; + constexpr U MIN_VALUE = -(1 << (bits - 1)); + constexpr U MAX_VALUE = (1 << (bits - 1)) - 1; + + typedef std::numeric_limits limits; + static_assert(MIN_VALUE >= limits::min(), "out of range"); + static_assert(MAX_VALUE <= limits::max(), "out of range"); if (gcc_unlikely(x < MIN_VALUE)) - return MIN_VALUE; + return T(MIN_VALUE); + if (gcc_unlikely(x > MAX_VALUE)) - return MAX_VALUE; - return x; + return T(MAX_VALUE); + + return T(x); +} + +gcc_const +static inline int16_t +pcm_clamp_16(int x) +{ + return PcmClamp(x); } gcc_const static inline int32_t pcm_clamp_24(int x) { - static const int32_t MIN_VALUE = -(1 << 23); - static const int32_t MAX_VALUE = (1 << 23) - 1; - - if (gcc_unlikely(x < MIN_VALUE)) - return MIN_VALUE; - if (gcc_unlikely(x > MAX_VALUE)) - return MAX_VALUE; - return x; + return PcmClamp(x); } #endif -- cgit v1.2.3