PcmFormat: merge duplicate code with a template
This commit is contained in:
parent
e6a91d291d
commit
86a0f9cf9b
|
@ -24,6 +24,16 @@
|
||||||
#include "pcm_pack.h"
|
#include "pcm_pack.h"
|
||||||
#include "PcmUtils.hxx"
|
#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
|
static void
|
||||||
pcm_convert_8_to_16(int16_t *out, const int8_t *in, const int8_t *in_end)
|
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);
|
dither.Dither32To16(out, in, in_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
|
||||||
static void
|
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;
|
typedef decltype(*S()) T;
|
||||||
const float factor = 1 << (OUT_BITS - 1);
|
typedef typename std::remove_reference<T>::type U;
|
||||||
|
|
||||||
while (in < in_end) {
|
const float factor = 1 << (bits - 1);
|
||||||
int sample = *in++ * factor;
|
|
||||||
*out++ = pcm_clamp_16(sample);
|
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 *
|
static int16_t *
|
||||||
pcm_allocate_8_to_16(struct pcm_buffer *buffer,
|
pcm_allocate_8_to_16(struct pcm_buffer *buffer,
|
||||||
const int8_t *src, size_t src_size, size_t *dest_size_r)
|
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,
|
const float *src, size_t src_size,
|
||||||
size_t *dest_size_r)
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
int16_t *dest;
|
return AllocateFromFloat<int16_t>(*buffer, src, src_size, dest_size_r);
|
||||||
*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int16_t *
|
const int16_t *
|
||||||
|
@ -174,18 +203,6 @@ pcm_convert_32_to_24(int32_t *restrict out,
|
||||||
*out++ = *in++ >> 8;
|
*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 *
|
static int32_t *
|
||||||
pcm_allocate_8_to_24(struct pcm_buffer *buffer,
|
pcm_allocate_8_to_24(struct pcm_buffer *buffer,
|
||||||
const int8_t *src, size_t src_size, size_t *dest_size_r)
|
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,
|
const float *src, size_t src_size,
|
||||||
size_t *dest_size_r)
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
*dest_size_r = src_size;
|
return AllocateFromFloat<int32_t, 24>(*buffer, src, src_size,
|
||||||
int32_t *dest = (int32_t *)pcm_buffer_get(buffer, *dest_size_r);
|
dest_size_r);
|
||||||
pcm_convert_float_to_24(dest, src, pcm_end_pointer(src, src_size));
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const int32_t *
|
const int32_t *
|
||||||
|
@ -381,40 +396,36 @@ pcm_convert_to_32(struct pcm_buffer *buffer,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
|
||||||
static void
|
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 };
|
constexpr float factor = 0.5 / (1 << (bits - 2));
|
||||||
static const float factor = 2.0f / (1 << in_bits);
|
while (src != end)
|
||||||
while (in < in_end)
|
*dest++ = float(*src++) * factor;
|
||||||
*out++ = (float)*in++ * factor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
|
||||||
static void
|
static void
|
||||||
pcm_convert_16_to_float(float *out, const int16_t *in, const int16_t *in_end)
|
ConvertToFloat(float *dest, S src, size_t size)
|
||||||
{
|
{
|
||||||
enum { in_bits = sizeof(*in) * 8 };
|
ConvertToFloat<S, bits>(dest, src, pcm_end_pointer(src, size));
|
||||||
static const float factor = 2.0f / (1 << in_bits);
|
|
||||||
while (in < in_end)
|
|
||||||
*out++ = (float)*in++ * factor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
template<typename S, unsigned bits=DefaultSampleBits<S>::value>
|
||||||
pcm_convert_24_to_float(float *out, const int32_t *in, const int32_t *in_end)
|
static float *
|
||||||
|
AllocateToFloat(pcm_buffer &buffer, S src, size_t src_size,
|
||||||
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
enum { in_bits = 24 };
|
constexpr size_t src_sample_size = sizeof(*S());
|
||||||
static const float factor = 2.0f / (1 << in_bits);
|
assert(src_size % src_sample_size == 0);
|
||||||
while (in < in_end)
|
|
||||||
*out++ = (float)*in++ * factor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
const size_t num_samples = src_size / src_sample_size;
|
||||||
pcm_convert_32_to_float(float *out, const int32_t *in, const int32_t *in_end)
|
*dest_size_r = num_samples * sizeof(float);
|
||||||
{
|
float *dest = (float *)pcm_buffer_get(&buffer, *dest_size_r);
|
||||||
enum { in_bits = sizeof(*in) * 8 };
|
ConvertToFloat<S, bits>(dest, src, src_size);
|
||||||
static const float factor = 0.5f / (1 << (in_bits - 2));
|
return dest;
|
||||||
while (in < in_end)
|
|
||||||
*out++ = (float)*in++ * factor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float *
|
static float *
|
||||||
|
@ -422,11 +433,7 @@ pcm_allocate_8_to_float(struct pcm_buffer *buffer,
|
||||||
const int8_t *src, size_t src_size,
|
const int8_t *src, size_t src_size,
|
||||||
size_t *dest_size_r)
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
float *dest;
|
return AllocateToFloat(*buffer, src, src_size, dest_size_r);
|
||||||
*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float *
|
static float *
|
||||||
|
@ -434,23 +441,16 @@ pcm_allocate_16_to_float(struct pcm_buffer *buffer,
|
||||||
const int16_t *src, size_t src_size,
|
const int16_t *src, size_t src_size,
|
||||||
size_t *dest_size_r)
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
float *dest;
|
return AllocateToFloat(*buffer, src, src_size, dest_size_r);
|
||||||
*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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float *
|
static float *
|
||||||
pcm_allocate_24p32_to_float(struct pcm_buffer *buffer,
|
pcm_allocate_24p32_to_float(struct pcm_buffer *buffer,
|
||||||
const int32_t *src, size_t src_size,
|
const int32_t *src, size_t src_size,
|
||||||
size_t *dest_size_r)
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
*dest_size_r = src_size;
|
return AllocateToFloat<decltype(src), 24>
|
||||||
float *dest = (float *)pcm_buffer_get(buffer, *dest_size_r);
|
(*buffer, src, src_size, dest_size_r);
|
||||||
pcm_convert_24_to_float(dest, src, pcm_end_pointer(src, src_size));
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float *
|
static float *
|
||||||
|
@ -458,10 +458,7 @@ pcm_allocate_32_to_float(struct pcm_buffer *buffer,
|
||||||
const int32_t *src, size_t src_size,
|
const int32_t *src, size_t src_size,
|
||||||
size_t *dest_size_r)
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
*dest_size_r = src_size;
|
return AllocateToFloat(*buffer, src, src_size, dest_size_r);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const float *
|
const float *
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#include "gcc.h"
|
#include "gcc.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,32 +66,39 @@ pcm_range_64(int64_t sample, unsigned bits)
|
||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U, unsigned bits>
|
||||||
|
gcc_const
|
||||||
|
static inline T
|
||||||
|
PcmClamp(U x)
|
||||||
|
{
|
||||||
|
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 T(MIN_VALUE);
|
||||||
|
|
||||||
|
if (gcc_unlikely(x > MAX_VALUE))
|
||||||
|
return T(MAX_VALUE);
|
||||||
|
|
||||||
|
return T(x);
|
||||||
|
}
|
||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
static inline int16_t
|
static inline int16_t
|
||||||
pcm_clamp_16(int x)
|
pcm_clamp_16(int x)
|
||||||
{
|
{
|
||||||
static const int32_t MIN_VALUE = -(1 << 15);
|
return PcmClamp<int16_t, int, 16>(x);
|
||||||
static const int32_t MAX_VALUE = (1 << 15) - 1;
|
|
||||||
|
|
||||||
if (gcc_unlikely(x < MIN_VALUE))
|
|
||||||
return MIN_VALUE;
|
|
||||||
if (gcc_unlikely(x > MAX_VALUE))
|
|
||||||
return MAX_VALUE;
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
static inline int32_t
|
static inline int32_t
|
||||||
pcm_clamp_24(int x)
|
pcm_clamp_24(int x)
|
||||||
{
|
{
|
||||||
static const int32_t MIN_VALUE = -(1 << 23);
|
return PcmClamp<int32_t, int, 24>(x);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue