From e3f9e96eef7f51bf06905a6193037d9a72c72893 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Mon, 17 Jun 2019 12:25:24 +0200
Subject: [PATCH] pcm/Dop: convert public function to stateful class

Preparing to add more state.
---
 src/pcm/Dop.cxx    | 12 +++++++++---
 src/pcm/Dop.hxx    | 19 +++++++++++++++----
 src/pcm/Export.cxx | 17 ++++++++++++++---
 src/pcm/Export.hxx | 12 ++++++------
 4 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/src/pcm/Dop.cxx b/src/pcm/Dop.cxx
index 8120e200c..0ad6271d6 100644
--- a/src/pcm/Dop.cxx
+++ b/src/pcm/Dop.cxx
@@ -18,7 +18,6 @@
  */
 
 #include "Dop.hxx"
-#include "Buffer.hxx"
 #include "ChannelDefs.hxx"
 #include "util/ConstBuffer.hxx"
 
@@ -78,9 +77,16 @@ DsdToDop(uint32_t *dest, const uint8_t *src,
 	}
 }
 
+void
+DsdToDopConverter::Open(unsigned _channels) noexcept
+{
+	assert(audio_valid_channel_count(_channels));
+
+	channels = _channels;
+}
+
 ConstBuffer<uint32_t>
-pcm_dsd_to_dop(PcmBuffer &buffer, unsigned channels,
-	       ConstBuffer<uint8_t> src) noexcept
+DsdToDopConverter::Convert(ConstBuffer<uint8_t> src) noexcept
 {
 	assert(audio_valid_channel_count(channels));
 	assert(src.size % channels == 0);
diff --git a/src/pcm/Dop.hxx b/src/pcm/Dop.hxx
index 3bd089fe7..c1806b8c9 100644
--- a/src/pcm/Dop.hxx
+++ b/src/pcm/Dop.hxx
@@ -20,9 +20,10 @@
 #ifndef MPD_PCM_DOP_HXX
 #define MPD_PCM_DOP_HXX
 
+#include "Buffer.hxx"
+
 #include <stdint.h>
 
-class PcmBuffer;
 template<typename T> struct ConstBuffer;
 
 /**
@@ -30,8 +31,18 @@ template<typename T> struct ConstBuffer;
  * playback over USB, according to the DoP standard:
  * http://dsd-guide.com/dop-open-standard
  */
-ConstBuffer<uint32_t>
-pcm_dsd_to_dop(PcmBuffer &buffer, unsigned channels,
-	       ConstBuffer<uint8_t> src) noexcept;
+class DsdToDopConverter {
+	unsigned channels;
+
+	PcmBuffer buffer;
+
+public:
+	void Open(unsigned _channels) noexcept;
+
+	void Reset() noexcept {
+	}
+
+	ConstBuffer<uint32_t> Convert(ConstBuffer<uint8_t> src) noexcept;
+};
 
 #endif
diff --git a/src/pcm/Export.cxx b/src/pcm/Export.cxx
index 38bd5241d..fb77f43f8 100644
--- a/src/pcm/Export.cxx
+++ b/src/pcm/Export.cxx
@@ -61,10 +61,13 @@ PcmExport::Open(SampleFormat sample_format, unsigned _channels,
 		sample_format = SampleFormat::S32;
 
 	dop = params.dop && sample_format == SampleFormat::DSD;
-	if (dop)
+	if (dop) {
+		dop_converter.Open(_channels);
+
 		/* after the conversion to DoP, the DSD
 		   samples are stuffed inside fake 24 bit samples */
 		sample_format = SampleFormat::S24_P32;
+	}
 #endif
 
 	shift8 = params.shift8 && sample_format == SampleFormat::S24_P32;
@@ -84,6 +87,15 @@ PcmExport::Open(SampleFormat sample_format, unsigned _channels,
 	}
 }
 
+void
+PcmExport::Reset() noexcept
+{
+#ifdef ENABLE_DSD
+	if (dop)
+		dop_converter.Reset();
+#endif
+}
+
 size_t
 PcmExport::GetFrameSize(const AudioFormat &audio_format) const noexcept
 {
@@ -168,8 +180,7 @@ PcmExport::Export(ConstBuffer<void> data) noexcept
 			.ToVoid();
 
 	if (dop)
-		data = pcm_dsd_to_dop(dop_buffer, channels,
-				      ConstBuffer<uint8_t>::FromVoid(data))
+		data = dop_converter.Convert(ConstBuffer<uint8_t>::FromVoid(data))
 			.ToVoid();
 #endif
 
diff --git a/src/pcm/Export.hxx b/src/pcm/Export.hxx
index 8dfee34b6..91c50e2dc 100644
--- a/src/pcm/Export.hxx
+++ b/src/pcm/Export.hxx
@@ -24,6 +24,10 @@
 #include "Buffer.hxx"
 #include "config.h"
 
+#ifdef ENABLE_DSD
+#include "Dop.hxx"
+#endif
+
 template<typename T> struct ConstBuffer;
 struct AudioFormat;
 
@@ -49,12 +53,9 @@ class PcmExport {
 	PcmBuffer dsd_buffer;
 
 	/**
-	 * The buffer is used to convert DSD samples to the
-	 * DoP format.
-	 *
 	 * @see #dop
 	 */
-	PcmBuffer dop_buffer;
+	DsdToDopConverter dop_converter;
 #endif
 
 	/**
@@ -167,8 +168,7 @@ public:
 	/**
 	 * Reset the filter's state, e.g. drop/flush buffers.
 	 */
-	void Reset() noexcept {
-	}
+	void Reset() noexcept;
 
 	/**
 	 * Calculate the size of one output frame.