diff --git a/src/pcm/PcmDither.cxx b/src/pcm/PcmDither.cxx index 07a1fc94b..71ec5db1e 100644 --- a/src/pcm/PcmDither.cxx +++ b/src/pcm/PcmDither.cxx @@ -20,9 +20,10 @@ #include "config.h" #include "PcmDither.hxx" #include "PcmPrng.hxx" +#include "Traits.hxx" template -T +inline T PcmDither::Dither(T sample) { constexpr T round = 1 << (scale_bits - 1); @@ -61,38 +62,43 @@ PcmDither::Dither(T sample) return output; } -inline int16_t -PcmDither::Dither24To16(int_fast32_t sample) +template +inline typename DT::value_type +PcmDither::DitherShift(typename ST::value_type sample) { - typedef decltype(sample) T; - constexpr unsigned from_bits = 24; - 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; + static_assert(ST::BITS > DT::BITS, + "Sample formats cannot be dithered"); - return Dither(sample) >> scale_bits; + constexpr unsigned scale_bits = ST::BITS - DT::BITS; + + return Dither(sample) >> scale_bits; +} + +template +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(*src++); } void PcmDither::Dither24To16(int16_t *dest, const int32_t *src, const int32_t *src_end) { - while (src < src_end) - *dest++ = Dither24To16(*src++); -} - -inline int16_t -PcmDither::Dither32To16(int_fast32_t sample) -{ - return Dither24To16(sample >> 8); + typedef SampleTraits ST; + typedef SampleTraits DT; + DitherShift(dest, src, src_end); } void PcmDither::Dither32To16(int16_t *dest, const int32_t *src, const int32_t *src_end) { - while (src < src_end) - *dest++ = Dither32To16(*src++); + typedef SampleTraits ST; + typedef SampleTraits DT; + DitherShift(dest, src, src_end); } diff --git a/src/pcm/PcmDither.hxx b/src/pcm/PcmDither.hxx index f3213a6e6..2b75cdaeb 100644 --- a/src/pcm/PcmDither.hxx +++ b/src/pcm/PcmDither.hxx @@ -22,6 +22,8 @@ #include +enum class SampleFormat : uint8_t; + class PcmDither { int32_t error[3]; int32_t random; @@ -30,9 +32,6 @@ public: constexpr PcmDither() :error{0, 0, 0}, random(0) {} - template - T Dither(T sample); - void Dither24To16(int16_t *dest, const int32_t *src, const int32_t *src_end); @@ -40,8 +39,16 @@ public: const int32_t *src_end); private: - int16_t Dither24To16(int_fast32_t sample); - int16_t Dither32To16(int_fast32_t sample); + template + T Dither(T sample); + + template + typename DT::value_type DitherShift(typename ST::value_type sample); + + template + void DitherShift(typename DT::pointer_type dest, + typename ST::const_pointer_type src, + typename ST::const_pointer_type src_end); }; #endif