aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2013-01-31 22:07:10 +0100
committerMax Kellermann <max@duempel.org>2013-02-01 13:47:29 +0100
commit86a0f9cf9b9cddb60a4fb58c7ef187d220e8abfd (patch)
treef1bb6df451bc8480862b4168d0ea2d2c83f33c4f
parente6a91d291d74bb341b9f7e47ac576fa97533ceb1 (diff)
PcmFormat: merge duplicate code with a template
-rw-r--r--src/PcmFormat.cxx145
-rw-r--r--src/PcmUtils.hxx39
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 <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 a95af7e6..5683a167 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