From f930f37d35995f0fc07f70aefc41babc0db1757e Mon Sep 17 00:00:00 2001 From: Jurgen Kramer Date: Sun, 1 Apr 2012 11:10:12 +0200 Subject: Add support for DSD-over-USB version 1.0, remove pre-v1 support --- doc/user.xml | 4 ++-- src/pcm_dsd_usb.c | 33 ++++++++++++++++++++++++++++----- src/pcm_dsd_usb.h | 5 +++-- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/doc/user.xml b/doc/user.xml index 6c0547f0..cd36528d 100644 --- a/doc/user.xml +++ b/doc/user.xml @@ -1127,8 +1127,8 @@ systemctl start mpd.socket If set to yes, then DSD over USB according to the dCS - suggested standard is enabled. This wrapsa + url="http://www.sonore.us/DoP_openStandard_1v1.pdf">pro + posed standard by dCS and others is enabled. This wraps DSD samples in fake 24 bit PCM, and is understood by some DSD capable products, but may be harmful to other hardware. Therefore, the default is diff --git a/src/pcm_dsd_usb.c b/src/pcm_dsd_usb.c index 976420c0..4b5e39f3 100644 --- a/src/pcm_dsd_usb.c +++ b/src/pcm_dsd_usb.c @@ -24,11 +24,19 @@ G_GNUC_CONST static inline uint32_t -pcm_two_dsd_to_usb(uint8_t a, uint8_t b) +pcm_two_dsd_to_usb_marker1(uint8_t a, uint8_t b) { - return 0xffaa0000 | (a << 8) | b; + return 0xff050000 | (a << 8) | b; } +G_GNUC_CONST +static inline uint32_t +pcm_two_dsd_to_usb_marker2(uint8_t a, uint8_t b) +{ + return 0xfffa0000 | (a << 8) | b; +} + + const uint32_t * pcm_dsd_to_usb(struct pcm_buffer *buffer, unsigned channels, const uint8_t *src, size_t src_size, @@ -53,12 +61,27 @@ pcm_dsd_to_usb(struct pcm_buffer *buffer, unsigned channels, uint32_t *const dest0 = pcm_buffer_get(buffer, dest_size), *dest = dest0; - for (unsigned i = num_frames; i > 0; --i) { + for (unsigned i = num_frames / 2; i > 0; --i) { + for (unsigned c = channels; c > 0; --c) { + /* each 24 bit sample has 16 DSD sample bits + plus the magic 0x05 marker */ + + *dest++ = pcm_two_dsd_to_usb_marker1(src[0], src[channels]); + + /* seek the source pointer to the next + channel */ + ++src; + } + + /* skip the second byte of each channel, because we + have already copied it */ + src += channels; + for (unsigned c = channels; c > 0; --c) { /* each 24 bit sample has 16 DSD sample bits - plus the magic 0xaa marker */ + plus the magic 0xfa marker */ - *dest++ = pcm_two_dsd_to_usb(src[0], src[channels]); + *dest++ = pcm_two_dsd_to_usb_marker2(src[0], src[channels]); /* seek the source pointer to the next channel */ diff --git a/src/pcm_dsd_usb.h b/src/pcm_dsd_usb.h index 3e7ad8fa..38935845 100644 --- a/src/pcm_dsd_usb.h +++ b/src/pcm_dsd_usb.h @@ -30,8 +30,9 @@ struct pcm_buffer; /** * Pack DSD 1 bit samples into (padded) 24 bit PCM samples for - * playback over USB, according to the dCS suggested standard: - * http://www.dcsltd.co.uk/page/assets/DSDoverUSB.pdf + * playback over USB, according to the proposed standard by + * dCS and others: + * http://www.sonore.us/DoP_openStandard_1v1.pdf */ const uint32_t * pcm_dsd_to_usb(struct pcm_buffer *buffer, unsigned channels, -- cgit v1.2.3