Commit 1543e529 authored by Max Kellermann's avatar Max Kellermann

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.
parent 4043f320
...@@ -20,9 +20,10 @@ ...@@ -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) ...@@ -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 unsigned scale_bits = ST::BITS - DT::BITS;
constexpr int_fast32_t ONE = 1 << (from_bits - 1);
constexpr int_fast32_t MIN = -ONE; return Dither<typename ST::sum_type, ST::MIN, ST::MAX,
constexpr int_fast32_t MAX = ONE - 1; scale_bits>(sample) >> scale_bits;
return Dither<T, MIN, MAX, scale_bits>(sample) >> scale_bits;
} }
void template<typename ST, typename DT>
PcmDither::Dither24To16(int16_t *dest, const int32_t *src, inline void
const int32_t *src_end) PcmDither::DitherShift(typename DT::pointer_type dest,
typename ST::const_pointer_type src,
typename ST::const_pointer_type src_end)
{ {
while (src < src_end) while (src < src_end)
*dest++ = Dither24To16(*src++); *dest++ = DitherShift<ST, DT>(*src++);
} }
inline int16_t void
PcmDither::Dither32To16(int_fast32_t sample) 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 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 @@ ...@@ -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: ...@@ -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: ...@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment