pcm/Dither: convert remaining methods to templates
Use the SampleTraits template and let the compiler generate a special case for S32 instead of reusing S24_P32.
This commit is contained in:
parent
4043f320fe
commit
1543e529f1
|
@ -20,9 +20,10 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "PcmDither.hxx"
|
#include "PcmDither.hxx"
|
||||||
#include "PcmPrng.hxx"
|
#include "PcmPrng.hxx"
|
||||||
|
#include "Traits.hxx"
|
||||||
|
|
||||||
template<typename T, T MIN, T MAX, unsigned scale_bits>
|
template<typename T, T MIN, T MAX, unsigned scale_bits>
|
||||||
T
|
inline T
|
||||||
PcmDither::Dither(T sample)
|
PcmDither::Dither(T sample)
|
||||||
{
|
{
|
||||||
constexpr T round = 1 << (scale_bits - 1);
|
constexpr T round = 1 << (scale_bits - 1);
|
||||||
|
@ -61,38 +62,43 @@ PcmDither::Dither(T sample)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int16_t
|
template<typename ST, typename DT>
|
||||||
PcmDither::Dither24To16(int_fast32_t sample)
|
inline typename DT::value_type
|
||||||
|
PcmDither::DitherShift(typename ST::value_type sample)
|
||||||
{
|
{
|
||||||
typedef decltype(sample) T;
|
static_assert(ST::BITS > DT::BITS,
|
||||||
constexpr unsigned from_bits = 24;
|
"Sample formats cannot be dithered");
|
||||||
constexpr unsigned to_bits = 16;
|
|
||||||
constexpr unsigned scale_bits = from_bits - to_bits;
|
|
||||||
constexpr int_fast32_t ONE = 1 << (from_bits - 1);
|
|
||||||
constexpr int_fast32_t MIN = -ONE;
|
|
||||||
constexpr int_fast32_t MAX = ONE - 1;
|
|
||||||
|
|
||||||
return Dither<T, MIN, MAX, scale_bits>(sample) >> scale_bits;
|
constexpr unsigned scale_bits = ST::BITS - DT::BITS;
|
||||||
|
|
||||||
|
return Dither<typename ST::sum_type, ST::MIN, ST::MAX,
|
||||||
|
scale_bits>(sample) >> scale_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ST, typename DT>
|
||||||
|
inline void
|
||||||
|
PcmDither::DitherShift(typename DT::pointer_type dest,
|
||||||
|
typename ST::const_pointer_type src,
|
||||||
|
typename ST::const_pointer_type src_end)
|
||||||
|
{
|
||||||
|
while (src < src_end)
|
||||||
|
*dest++ = DitherShift<ST, DT>(*src++);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PcmDither::Dither24To16(int16_t *dest, const int32_t *src,
|
PcmDither::Dither24To16(int16_t *dest, const int32_t *src,
|
||||||
const int32_t *src_end)
|
const int32_t *src_end)
|
||||||
{
|
{
|
||||||
while (src < src_end)
|
typedef SampleTraits<SampleFormat::S24_P32> ST;
|
||||||
*dest++ = Dither24To16(*src++);
|
typedef SampleTraits<SampleFormat::S16> DT;
|
||||||
}
|
DitherShift<ST, DT>(dest, src, src_end);
|
||||||
|
|
||||||
inline int16_t
|
|
||||||
PcmDither::Dither32To16(int_fast32_t sample)
|
|
||||||
{
|
|
||||||
return Dither24To16(sample >> 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PcmDither::Dither32To16(int16_t *dest, const int32_t *src,
|
PcmDither::Dither32To16(int16_t *dest, const int32_t *src,
|
||||||
const int32_t *src_end)
|
const int32_t *src_end)
|
||||||
{
|
{
|
||||||
while (src < src_end)
|
typedef SampleTraits<SampleFormat::S32> ST;
|
||||||
*dest++ = Dither32To16(*src++);
|
typedef SampleTraits<SampleFormat::S16> DT;
|
||||||
|
DitherShift<ST, DT>(dest, src, src_end);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum class SampleFormat : uint8_t;
|
||||||
|
|
||||||
class PcmDither {
|
class PcmDither {
|
||||||
int32_t error[3];
|
int32_t error[3];
|
||||||
int32_t random;
|
int32_t random;
|
||||||
|
@ -30,9 +32,6 @@ public:
|
||||||
constexpr PcmDither()
|
constexpr PcmDither()
|
||||||
:error{0, 0, 0}, random(0) {}
|
:error{0, 0, 0}, random(0) {}
|
||||||
|
|
||||||
template<typename T, T MIN, T MAX, unsigned scale_bits>
|
|
||||||
T Dither(T sample);
|
|
||||||
|
|
||||||
void Dither24To16(int16_t *dest, const int32_t *src,
|
void Dither24To16(int16_t *dest, const int32_t *src,
|
||||||
const int32_t *src_end);
|
const int32_t *src_end);
|
||||||
|
|
||||||
|
@ -40,8 +39,16 @@ public:
|
||||||
const int32_t *src_end);
|
const int32_t *src_end);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int16_t Dither24To16(int_fast32_t sample);
|
template<typename T, T MIN, T MAX, unsigned scale_bits>
|
||||||
int16_t Dither32To16(int_fast32_t sample);
|
T Dither(T sample);
|
||||||
|
|
||||||
|
template<typename ST, typename DT>
|
||||||
|
typename DT::value_type DitherShift(typename ST::value_type sample);
|
||||||
|
|
||||||
|
template<typename ST, typename DT>
|
||||||
|
void DitherShift(typename DT::pointer_type dest,
|
||||||
|
typename ST::const_pointer_type src,
|
||||||
|
typename ST::const_pointer_type src_end);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue