diff options
author | Max Kellermann <max@duempel.org> | 2013-12-22 16:09:07 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-12-22 22:06:25 +0100 |
commit | 4043f320fe6f9d2128e1a7be52ab89b380e208cc (patch) | |
tree | 3badb591800d4844f147116507be3317d1214d9c /src/pcm | |
parent | 32b834aa04bd05dade4e9db7759f2473f3e24b7e (diff) | |
download | mpd-4043f320fe6f9d2128e1a7be52ab89b380e208cc.tar.gz mpd-4043f320fe6f9d2128e1a7be52ab89b380e208cc.tar.xz mpd-4043f320fe6f9d2128e1a7be52ab89b380e208cc.zip |
pcm/Dither: generic sample dithering using template
Diffstat (limited to 'src/pcm')
-rw-r--r-- | src/pcm/PcmDither.cxx | 35 | ||||
-rw-r--r-- | src/pcm/PcmDither.hxx | 3 |
2 files changed, 25 insertions, 13 deletions
diff --git a/src/pcm/PcmDither.cxx b/src/pcm/PcmDither.cxx index 98d0d443e..07a1fc94b 100644 --- a/src/pcm/PcmDither.cxx +++ b/src/pcm/PcmDither.cxx @@ -21,17 +21,12 @@ #include "PcmDither.hxx" #include "PcmPrng.hxx" -inline int16_t -PcmDither::Dither24To16(int_fast32_t sample) +template<typename T, T MIN, T MAX, unsigned scale_bits> +T +PcmDither::Dither(T sample) { - constexpr unsigned from_bits = 24; - constexpr unsigned to_bits = 16; - constexpr unsigned scale_bits = from_bits - to_bits; - constexpr int_fast32_t round = 1 << (scale_bits - 1); - constexpr int_fast32_t mask = (1 << scale_bits) - 1; - constexpr int_fast32_t ONE = 1 << (from_bits - 1); - constexpr int_fast32_t MIN = -ONE; - constexpr int_fast32_t MAX = ONE - 1; + constexpr T round = 1 << (scale_bits - 1); + constexpr T mask = (1 << scale_bits) - 1; sample += error[0] - error[1] + error[2]; @@ -39,9 +34,9 @@ PcmDither::Dither24To16(int_fast32_t sample) error[1] = error[0] / 2; /* round */ - int_fast32_t output = sample + round; + T output = sample + round; - int_fast32_t rnd = pcm_prng(random); + const T rnd = pcm_prng(random); output += (rnd & mask) - (random & mask); random = rnd; @@ -63,7 +58,21 @@ PcmDither::Dither24To16(int_fast32_t sample) error[0] = sample - output; - return (int16_t)(output >> scale_bits); + return output; +} + +inline int16_t +PcmDither::Dither24To16(int_fast32_t 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; } void diff --git a/src/pcm/PcmDither.hxx b/src/pcm/PcmDither.hxx index 106382307..f3213a6e6 100644 --- a/src/pcm/PcmDither.hxx +++ b/src/pcm/PcmDither.hxx @@ -30,6 +30,9 @@ 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); |