From fb4f02cd388c13093deebc4d7168600f259845a5 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 26 Feb 2016 18:17:11 +0100 Subject: [PATCH] pcm/PcmExport: add flag to export to DSD_U32 --- src/pcm/PcmExport.cxx | 17 +++++++++++++++++ src/pcm/PcmExport.hxx | 6 ++++++ test/test_pcm_all.hxx | 2 ++ test/test_pcm_export.cxx | 24 ++++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/src/pcm/PcmExport.cxx b/src/pcm/PcmExport.cxx index b40129ad1..5a9bf4558 100644 --- a/src/pcm/PcmExport.cxx +++ b/src/pcm/PcmExport.cxx @@ -25,6 +25,7 @@ #include "util/ConstBuffer.hxx" #ifdef ENABLE_DSD +#include "PcmDsd.hxx" #include "PcmDop.hxx" #endif @@ -42,7 +43,15 @@ PcmExport::Open(SampleFormat sample_format, unsigned _channels, : SampleFormat::UNDEFINED; #ifdef ENABLE_DSD + assert(!params.dsd_u32 || !params.dop); assert(!params.dop || audio_valid_channel_count(_channels)); + + dsd_u32 = params.dsd_u32 && sample_format == SampleFormat::DSD; + if (dsd_u32) + /* after the conversion to DSD_U32, the DSD samples + are stuffed inside fake 32 bit samples */ + sample_format = SampleFormat::S32; + dop = params.dop && sample_format == SampleFormat::DSD; if (dop) /* after the conversion to DoP, the DSD @@ -77,6 +86,9 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const return audio_format.channels * 3; #ifdef ENABLE_DSD + if (dsd_u32) + return channels * 4; + if (dop) /* the DSD-over-USB draft says that DSD 1-bit samples are enclosed within 24 bit samples, and MPD's @@ -96,6 +108,11 @@ PcmExport::Export(ConstBuffer data) alsa_channel_order, channels); #ifdef ENABLE_DSD + if (dsd_u32) + data = Dsd8To32(dop_buffer, channels, + ConstBuffer::FromVoid(data)) + .ToVoid(); + if (dop) data = pcm_dsd_to_dop(dop_buffer, channels, ConstBuffer::FromVoid(data)) diff --git a/src/pcm/PcmExport.hxx b/src/pcm/PcmExport.hxx index a03cdc903..b33d7b800 100644 --- a/src/pcm/PcmExport.hxx +++ b/src/pcm/PcmExport.hxx @@ -35,6 +35,7 @@ template struct ConstBuffer; struct PcmExport { struct Params { bool alsa_channel_order = false; + bool dsd_u32 = false; bool dop = false; bool shift8 = false; bool pack24 = false; @@ -88,6 +89,11 @@ struct PcmExport { SampleFormat alsa_channel_order; #ifdef ENABLE_DSD + /** + * Convert DSD (U8) to DSD_U32? + */ + bool dsd_u32; + /** * Convert DSD to DSD-over-PCM (DoP)? Input format must be * SampleFormat::DSD and output format must be diff --git a/test/test_pcm_all.hxx b/test/test_pcm_all.hxx index ad0d245c3..c59d2e1f2 100644 --- a/test/test_pcm_all.hxx +++ b/test/test_pcm_all.hxx @@ -125,6 +125,7 @@ class PcmExportTest : public CppUnit::TestFixture { CPPUNIT_TEST(TestShift8); CPPUNIT_TEST(TestPack24); CPPUNIT_TEST(TestReverseEndian); + CPPUNIT_TEST(TestDsdU32); CPPUNIT_TEST(TestDop); CPPUNIT_TEST(TestAlsaChannelOrder); CPPUNIT_TEST_SUITE_END(); @@ -133,6 +134,7 @@ public: void TestShift8(); void TestPack24(); void TestReverseEndian(); + void TestDsdU32(); void TestDop(); void TestAlsaChannelOrder(); }; diff --git a/test/test_pcm_export.cxx b/test/test_pcm_export.cxx index cea0de634..bd4deb42a 100644 --- a/test/test_pcm_export.cxx +++ b/test/test_pcm_export.cxx @@ -115,6 +115,30 @@ PcmExportTest::TestReverseEndian() CPPUNIT_ASSERT(memcmp(dest.data, expected4, dest.size) == 0); } +void +PcmExportTest::TestDsdU32() +{ + static constexpr uint8_t src[] = { + 0x01, 0x23, 0x45, 0x67, + 0x89, 0xab, 0xcd, 0xef, + }; + + static constexpr uint32_t expected[] = { + 0xcd894501, + 0xefab6723, + }; + + PcmExport::Params params; + params.dsd_u32 = true; + + PcmExport e; + e.Open(SampleFormat::DSD, 2, params); + + auto dest = e.Export({src, sizeof(src)}); + CPPUNIT_ASSERT_EQUAL(sizeof(expected), dest.size); + CPPUNIT_ASSERT(memcmp(dest.data, expected, dest.size) == 0); +} + void PcmExportTest::TestDop() {