pcm/PcmExport: add flag to export to DSD_U32

This commit is contained in:
Max Kellermann 2016-02-26 18:17:11 +01:00
parent d1be643c0d
commit fb4f02cd38
4 changed files with 49 additions and 0 deletions

View File

@ -25,6 +25,7 @@
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
#include "PcmDsd.hxx"
#include "PcmDop.hxx" #include "PcmDop.hxx"
#endif #endif
@ -42,7 +43,15 @@ PcmExport::Open(SampleFormat sample_format, unsigned _channels,
: SampleFormat::UNDEFINED; : SampleFormat::UNDEFINED;
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
assert(!params.dsd_u32 || !params.dop);
assert(!params.dop || audio_valid_channel_count(_channels)); 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; dop = params.dop && sample_format == SampleFormat::DSD;
if (dop) if (dop)
/* after the conversion to DoP, the DSD /* after the conversion to DoP, the DSD
@ -77,6 +86,9 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const
return audio_format.channels * 3; return audio_format.channels * 3;
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
if (dsd_u32)
return channels * 4;
if (dop) if (dop)
/* the DSD-over-USB draft says that DSD 1-bit samples /* the DSD-over-USB draft says that DSD 1-bit samples
are enclosed within 24 bit samples, and MPD's are enclosed within 24 bit samples, and MPD's
@ -96,6 +108,11 @@ PcmExport::Export(ConstBuffer<void> data)
alsa_channel_order, channels); alsa_channel_order, channels);
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
if (dsd_u32)
data = Dsd8To32(dop_buffer, channels,
ConstBuffer<uint8_t>::FromVoid(data))
.ToVoid();
if (dop) if (dop)
data = pcm_dsd_to_dop(dop_buffer, channels, data = pcm_dsd_to_dop(dop_buffer, channels,
ConstBuffer<uint8_t>::FromVoid(data)) ConstBuffer<uint8_t>::FromVoid(data))

View File

@ -35,6 +35,7 @@ template<typename T> struct ConstBuffer;
struct PcmExport { struct PcmExport {
struct Params { struct Params {
bool alsa_channel_order = false; bool alsa_channel_order = false;
bool dsd_u32 = false;
bool dop = false; bool dop = false;
bool shift8 = false; bool shift8 = false;
bool pack24 = false; bool pack24 = false;
@ -88,6 +89,11 @@ struct PcmExport {
SampleFormat alsa_channel_order; SampleFormat alsa_channel_order;
#ifdef ENABLE_DSD #ifdef ENABLE_DSD
/**
* Convert DSD (U8) to DSD_U32?
*/
bool dsd_u32;
/** /**
* Convert DSD to DSD-over-PCM (DoP)? Input format must be * Convert DSD to DSD-over-PCM (DoP)? Input format must be
* SampleFormat::DSD and output format must be * SampleFormat::DSD and output format must be

View File

@ -125,6 +125,7 @@ class PcmExportTest : public CppUnit::TestFixture {
CPPUNIT_TEST(TestShift8); CPPUNIT_TEST(TestShift8);
CPPUNIT_TEST(TestPack24); CPPUNIT_TEST(TestPack24);
CPPUNIT_TEST(TestReverseEndian); CPPUNIT_TEST(TestReverseEndian);
CPPUNIT_TEST(TestDsdU32);
CPPUNIT_TEST(TestDop); CPPUNIT_TEST(TestDop);
CPPUNIT_TEST(TestAlsaChannelOrder); CPPUNIT_TEST(TestAlsaChannelOrder);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
@ -133,6 +134,7 @@ public:
void TestShift8(); void TestShift8();
void TestPack24(); void TestPack24();
void TestReverseEndian(); void TestReverseEndian();
void TestDsdU32();
void TestDop(); void TestDop();
void TestAlsaChannelOrder(); void TestAlsaChannelOrder();
}; };

View File

@ -115,6 +115,30 @@ PcmExportTest::TestReverseEndian()
CPPUNIT_ASSERT(memcmp(dest.data, expected4, dest.size) == 0); 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 void
PcmExportTest::TestDop() PcmExportTest::TestDop()
{ {