From f2491c88c86707cc35c7dfc30a1b5a0a29886540 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Thu, 31 Jan 2013 22:43:28 +0100
Subject: [PATCH] PcmDither: convert struct to a class

---
 src/PcmConvert.cxx       |  3 +--
 src/PcmConvert.hxx       |  2 +-
 src/PcmDither.cxx        | 40 +++++++++++++++++++---------------------
 src/PcmDither.hxx        | 31 +++++++++++++++----------------
 src/PcmFormat.cxx        | 14 +++++++-------
 src/PcmFormat.hxx        |  4 ++--
 test/test_pcm_dither.cxx | 12 ++++--------
 7 files changed, 49 insertions(+), 57 deletions(-)

diff --git a/src/PcmConvert.cxx b/src/PcmConvert.cxx
index ed260d074..9618b9642 100644
--- a/src/PcmConvert.cxx
+++ b/src/PcmConvert.cxx
@@ -38,7 +38,6 @@ PcmConvert::PcmConvert()
 
 	pcm_dsd_init(&dsd);
 	pcm_resample_init(&resample);
-	pcm_dither_24_init(&dither);
 
 	pcm_buffer_init(&format_buffer);
 	pcm_buffer_init(&channels_buffer);
@@ -71,7 +70,7 @@ PcmConvert::Convert16(const audio_format *src_format,
 
 	assert(dest_format->format == SAMPLE_FORMAT_S16);
 
-	buf = pcm_convert_to_16(&format_buffer, &dither,
+	buf = pcm_convert_to_16(&format_buffer, dither,
 				sample_format(src_format->format),
 				src_buffer, src_size,
 				&len);
diff --git a/src/PcmConvert.hxx b/src/PcmConvert.hxx
index d76ecc125..f08188a9c 100644
--- a/src/PcmConvert.hxx
+++ b/src/PcmConvert.hxx
@@ -42,7 +42,7 @@ class PcmConvert {
 
 	struct pcm_resample_state resample;
 
-	struct pcm_dither dither;
+	PcmDither dither;
 
 	/** the buffer for converting the sample format */
 	struct pcm_buffer format_buffer;
diff --git a/src/PcmDither.cxx b/src/PcmDither.cxx
index e18119082..2560a1aa3 100644
--- a/src/PcmDither.cxx
+++ b/src/PcmDither.cxx
@@ -21,11 +21,9 @@
 #include "PcmDither.hxx"
 #include "PcmPrng.hxx"
 
-static int16_t
-pcm_dither_sample_24_to_16(int32_t sample, struct pcm_dither *dither)
+inline int16_t
+PcmDither::Dither24To16(int_fast32_t sample)
 {
-	int32_t output, rnd;
-
 	enum {
 		from_bits = 24,
 		to_bits = 16,
@@ -37,18 +35,18 @@ pcm_dither_sample_24_to_16(int32_t sample, struct pcm_dither *dither)
 		MAX = ONE - 1
 	};
 
-	sample += dither->error[0] - dither->error[1] + dither->error[2];
+	sample += error[0] - error[1] + error[2];
 
-	dither->error[2] = dither->error[1];
-	dither->error[1] = dither->error[0] / 2;
+	error[2] = error[1];
+	error[1] = error[0] / 2;
 
 	/* round */
-	output = sample + round;
+	int_fast32_t output = sample + round;
 
-	rnd = pcm_prng(dither->random);
-	output += (rnd & mask) - (dither->random & mask);
+	int_fast32_t rnd = pcm_prng(random);
+	output += (rnd & mask) - (random & mask);
 
-	dither->random = rnd;
+	random = rnd;
 
 	/* clip */
 	if (output > MAX) {
@@ -65,29 +63,29 @@ pcm_dither_sample_24_to_16(int32_t sample, struct pcm_dither *dither)
 
 	output &= ~mask;
 
-	dither->error[0] = sample - output;
+	error[0] = sample - output;
 
 	return (int16_t)(output >> scale_bits);
 }
 
 void
-pcm_dither_24_to_16(struct pcm_dither *dither,
-		    int16_t *dest, const int32_t *src, const int32_t *src_end)
+PcmDither::Dither24To16(int16_t *dest, const int32_t *src,
+			const int32_t *src_end)
 {
 	while (src < src_end)
-		*dest++ = pcm_dither_sample_24_to_16(*src++, dither);
+		*dest++ = Dither24To16(*src++);
 }
 
-static int16_t
-pcm_dither_sample_32_to_16(int32_t sample, struct pcm_dither *dither)
+inline int16_t
+PcmDither::Dither32To16(int_fast32_t sample)
 {
-	return pcm_dither_sample_24_to_16(sample >> 8, dither);
+	return Dither24To16(sample >> 8);
 }
 
 void
-pcm_dither_32_to_16(struct pcm_dither *dither,
-		    int16_t *dest, const int32_t *src, const int32_t *src_end)
+PcmDither::Dither32To16(int16_t *dest, const int32_t *src,
+			const int32_t *src_end)
 {
 	while (src < src_end)
-		*dest++ = pcm_dither_sample_32_to_16(*src++, dither);
+		*dest++ = Dither32To16(*src++);
 }
diff --git a/src/PcmDither.hxx b/src/PcmDither.hxx
index 59affa088..106382307 100644
--- a/src/PcmDither.hxx
+++ b/src/PcmDither.hxx
@@ -22,24 +22,23 @@
 
 #include <stdint.h>
 
-struct pcm_dither {
+class PcmDither {
 	int32_t error[3];
 	int32_t random;
+
+public:
+	constexpr PcmDither()
+		:error{0, 0, 0}, random(0) {}
+
+	void Dither24To16(int16_t *dest, const int32_t *src,
+			  const int32_t *src_end);
+
+	void Dither32To16(int16_t *dest, const int32_t *src,
+			  const int32_t *src_end);
+
+private:
+	int16_t Dither24To16(int_fast32_t sample);
+	int16_t Dither32To16(int_fast32_t sample);
 };
 
-static inline void
-pcm_dither_24_init(struct pcm_dither *dither)
-{
-	dither->error[0] = dither->error[1] = dither->error[2] = 0;
-	dither->random = 0;
-}
-
-void
-pcm_dither_24_to_16(struct pcm_dither *dither,
-		    int16_t *dest, const int32_t *src, const int32_t *src_end);
-
-void
-pcm_dither_32_to_16(struct pcm_dither *dither,
-		    int16_t *dest, const int32_t *src, const int32_t *src_end);
-
 #endif
diff --git a/src/PcmFormat.cxx b/src/PcmFormat.cxx
index cf601684a..50e15c912 100644
--- a/src/PcmFormat.cxx
+++ b/src/PcmFormat.cxx
@@ -33,17 +33,17 @@ pcm_convert_8_to_16(int16_t *out, const int8_t *in, const int8_t *in_end)
 }
 
 static void
-pcm_convert_24_to_16(struct pcm_dither *dither,
+pcm_convert_24_to_16(PcmDither &dither,
 		     int16_t *out, const int32_t *in, const int32_t *in_end)
 {
-	pcm_dither_24_to_16(dither, out, in, in_end);
+	dither.Dither24To16(out, in, in_end);
 }
 
 static void
-pcm_convert_32_to_16(struct pcm_dither *dither,
+pcm_convert_32_to_16(PcmDither &dither,
 		     int16_t *out, const int32_t *in, const int32_t *in_end)
 {
-	pcm_dither_32_to_16(dither, out, in, in_end);
+	dither.Dither32To16(out, in, in_end);
 }
 
 static void
@@ -70,7 +70,7 @@ pcm_allocate_8_to_16(struct pcm_buffer *buffer,
 }
 
 static int16_t *
-pcm_allocate_24p32_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
+pcm_allocate_24p32_to_16(struct pcm_buffer *buffer, PcmDither &dither,
 			 const int32_t *src, size_t src_size,
 			 size_t *dest_size_r)
 {
@@ -84,7 +84,7 @@ pcm_allocate_24p32_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
 }
 
 static int16_t *
-pcm_allocate_32_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
+pcm_allocate_32_to_16(struct pcm_buffer *buffer, PcmDither &dither,
 		      const int32_t *src, size_t src_size,
 		      size_t *dest_size_r)
 {
@@ -112,7 +112,7 @@ pcm_allocate_float_to_16(struct pcm_buffer *buffer,
 }
 
 const int16_t *
-pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
+pcm_convert_to_16(struct pcm_buffer *buffer, PcmDither &dither,
 		  enum sample_format src_format, const void *src,
 		  size_t src_size, size_t *dest_size_r)
 {
diff --git a/src/PcmFormat.hxx b/src/PcmFormat.hxx
index d739f60d1..a5970b2d2 100644
--- a/src/PcmFormat.hxx
+++ b/src/PcmFormat.hxx
@@ -26,7 +26,7 @@
 #include <stddef.h>
 
 struct pcm_buffer;
-struct pcm_dither;
+class PcmDither;
 
 /**
  * Converts PCM samples to 16 bit.  If the source format is 24 bit,
@@ -41,7 +41,7 @@ struct pcm_dither;
  * @return the destination buffer
  */
 const int16_t *
-pcm_convert_to_16(struct pcm_buffer *buffer, struct pcm_dither *dither,
+pcm_convert_to_16(struct pcm_buffer *buffer, PcmDither &dither,
 		  enum sample_format src_format, const void *src,
 		  size_t src_size, size_t *dest_size_r);
 
diff --git a/test/test_pcm_dither.cxx b/test/test_pcm_dither.cxx
index 44830746f..6d1ed686a 100644
--- a/test/test_pcm_dither.cxx
+++ b/test/test_pcm_dither.cxx
@@ -37,9 +37,7 @@ random24()
 void
 test_pcm_dither_24()
 {
-	struct pcm_dither dither;
-
-	pcm_dither_24_init(&dither);
+	PcmDither dither;
 
 	enum { N = 256 };
 	int32_t src[N];
@@ -48,7 +46,7 @@ test_pcm_dither_24()
 
 	int16_t dest[N];
 
-	pcm_dither_24_to_16(&dither, dest, src, src + N);
+	dither.Dither24To16(dest, src, src + N);
 
 	for (unsigned i = 0; i < N; ++i) {
 		g_assert_cmpint(dest[i], >=, (src[i] >> 8) - 8);
@@ -59,9 +57,7 @@ test_pcm_dither_24()
 void
 test_pcm_dither_32()
 {
-	struct pcm_dither dither;
-
-	pcm_dither_24_init(&dither);
+	PcmDither dither;
 
 	enum { N = 256 };
 	int32_t src[N];
@@ -70,7 +66,7 @@ test_pcm_dither_32()
 
 	int16_t dest[N];
 
-	pcm_dither_32_to_16(&dither, dest, src, src + N);
+	dither.Dither32To16(dest, src, src + N);
 
 	for (unsigned i = 0; i < N; ++i) {
 		g_assert_cmpint(dest[i], >=, (src[i] >> 16) - 8);