diff options
Diffstat (limited to 'src/pcm')
-rw-r--r-- | src/pcm/PcmDither.cxx | 48 | ||||
-rw-r--r-- | src/pcm/PcmDither.hxx | 17 |
2 files changed, 39 insertions, 26 deletions
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<typename T, T MIN, T MAX, unsigned scale_bits> -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<typename ST, typename DT> +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; - - return Dither<T, MIN, MAX, scale_bits>(sample) >> scale_bits; + static_assert(ST::BITS > DT::BITS, + "Sample formats cannot be dithered"); + + constexpr unsigned scale_bits = ST::BITS - DT::BITS; + + return Dither<typename ST::sum_type, ST::MIN, ST::MAX, + scale_bits>(sample) >> scale_bits; } -void -PcmDither::Dither24To16(int16_t *dest, const int32_t *src, - const int32_t *src_end) +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++ = Dither24To16(*src++); + *dest++ = DitherShift<ST, DT>(*src++); } -inline int16_t -PcmDither::Dither32To16(int_fast32_t sample) +void +PcmDither::Dither24To16(int16_t *dest, const int32_t *src, + const int32_t *src_end) { - return Dither24To16(sample >> 8); + typedef SampleTraits<SampleFormat::S24_P32> ST; + typedef SampleTraits<SampleFormat::S16> DT; + DitherShift<ST, DT>(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<SampleFormat::S32> ST; + typedef SampleTraits<SampleFormat::S16> DT; + DitherShift<ST, DT>(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 <stdint.h> +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<typename T, T MIN, T MAX, unsigned scale_bits> - 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<typename T, T MIN, T MAX, unsigned scale_bits> + 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 |