From 1543e529f1e52ec135a644bd3faf7496f92b0a38 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Sun, 22 Dec 2013 21:58:18 +0100
Subject: 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.
---
 src/pcm/PcmDither.cxx | 48 +++++++++++++++++++++++++++---------------------
 src/pcm/PcmDither.hxx | 17 ++++++++++++-----
 2 files changed, 39 insertions(+), 26 deletions(-)

(limited to 'src')

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
-- 
cgit v1.2.3