diff options
author | Max Kellermann <max@duempel.org> | 2013-01-31 22:07:10 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-02-01 13:47:29 +0100 |
commit | 86a0f9cf9b9cddb60a4fb58c7ef187d220e8abfd (patch) | |
tree | f1bb6df451bc8480862b4168d0ea2d2c83f33c4f | |
parent | e6a91d291d74bb341b9f7e47ac576fa97533ceb1 (diff) | |
download | mpd-86a0f9cf9b9cddb60a4fb58c7ef187d220e8abfd.tar.gz mpd-86a0f9cf9b9cddb60a4fb58c7ef187d220e8abfd.tar.xz mpd-86a0f9cf9b9cddb60a4fb58c7ef187d220e8abfd.zip |
PcmFormat: merge duplicate code with a template
-rw-r--r-- | src/PcmFormat.cxx | 145 | ||||
-rw-r--r-- | src/PcmUtils.hxx | 39 |
2 files changed, 95 insertions, 89 deletions
diff --git a/src/PcmFormat.cxx b/src/PcmFormat.cxx index 50e15c912..1385d161b 100644 --- a/src/PcmFormat.cxx +++ b/src/PcmFormat.cxx @@ -24,6 +24,16 @@ #include "pcm_pack.h" #include "PcmUtils.hxx" +#include <type_traits> + +template<typename S> +struct DefaultSampleBits { + typedef decltype(*S()) T; + typedef typename std::remove_reference<T>::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<typename S, unsigned bits=DefaultSampleBits<S>::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<T>::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<U, int, bits>(sample); } } +template<typename S, unsigned bits=DefaultSampleBits<S>::value> +static void +ConvertFromFloat(S dest, const float *src, size_t size) +{ + ConvertFromFloat<S, bits>(dest, src, pcm_end_pointer(src, size)); +} + +template<typename S, unsigned bits=sizeof(S)*8> +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<S *, bits>(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<int16_t>(*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<int32_t, 24>(*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<typename S, unsigned bits=DefaultSampleBits<S>::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<typename S, unsigned bits=DefaultSampleBits<S>::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<S, bits>(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<typename S, unsigned bits=DefaultSampleBits<S>::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<S, bits>(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<decltype(src), 24> + (*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 a95af7e68..5683a167d 100644 --- a/src/PcmUtils.hxx +++ b/src/PcmUtils.hxx @@ -22,6 +22,8 @@ #include "gcc.h" +#include <limits> + #include <stdint.h> /** @@ -64,32 +66,39 @@ pcm_range_64(int64_t sample, unsigned bits) return sample; } +template<typename T, typename U, unsigned bits> 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<T> 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<int16_t, int, 16>(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<int32_t, int, 24>(x); } #endif |