From e5a28bfd8d07fe5ca5dee1bfb55ce414c8f7e9fc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 31 Aug 2014 16:12:26 +0200 Subject: output/alsa, pcm: rename "DSD over USB" to "DoP" The standard has been renamed since the early draft that was implemented in MPD. --- src/output/plugins/AlsaOutputPlugin.cxx | 41 +++++++------- src/pcm/PcmDop.cxx | 96 +++++++++++++++++++++++++++++++++ src/pcm/PcmDop.hxx | 40 ++++++++++++++ src/pcm/PcmDsdUsb.cxx | 96 --------------------------------- src/pcm/PcmDsdUsb.hxx | 41 -------------- src/pcm/PcmExport.cxx | 22 ++++---- src/pcm/PcmExport.hxx | 14 ++--- 7 files changed, 175 insertions(+), 175 deletions(-) create mode 100644 src/pcm/PcmDop.cxx create mode 100644 src/pcm/PcmDop.hxx delete mode 100644 src/pcm/PcmDsdUsb.cxx delete mode 100644 src/pcm/PcmDsdUsb.hxx (limited to 'src') diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 0ebf3ddbe..33a090274 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -62,12 +62,11 @@ struct AlsaOutput { bool use_mmap; /** - * Enable DSD over USB according to the dCS suggested - * standard? + * Enable DSD over PCM according to the DoP standard standard? * - * @see http://www.dcsltd.co.uk/page/assets/DSDoverUSB.pdf + * @see http://dsd-guide.com/dop-open-standard */ - bool dsd_usb; + bool dop; /** libasound's buffer_time setting (in microseconds) */ unsigned int buffer_time; @@ -153,7 +152,9 @@ AlsaOutput::Configure(const config_param ¶m, Error &error) use_mmap = param.GetBlockValue("use_mmap", false); - dsd_usb = param.GetBlockValue("dsd_usb", false); + dop = param.GetBlockValue("dop", false) || + /* legacy name from MPD 0.18 and older: */ + param.GetBlockValue("dsd_usb", false); buffer_time = param.GetBlockValue("buffer_time", MPD_ALSA_BUFFER_TIME_US); @@ -639,34 +640,34 @@ alsa_setup_dsd(AlsaOutput *ad, const AudioFormat audio_format, bool *shift8_r, bool *packed_r, bool *reverse_endian_r, Error &error) { - assert(ad->dsd_usb); + assert(ad->dop); assert(audio_format.format == SampleFormat::DSD); /* pass 24 bit to alsa_setup() */ - AudioFormat usb_format = audio_format; - usb_format.format = SampleFormat::S24_P32; - usb_format.sample_rate /= 2; + AudioFormat dop_format = audio_format; + dop_format.format = SampleFormat::S24_P32; + dop_format.sample_rate /= 2; - const AudioFormat check = usb_format; + const AudioFormat check = dop_format; - if (!alsa_setup(ad, usb_format, packed_r, reverse_endian_r, error)) + if (!alsa_setup(ad, dop_format, packed_r, reverse_endian_r, error)) return false; - /* if the device allows only 32 bit, shift all DSD-over-USB + /* if the device allows only 32 bit, shift all DoP samples left by 8 bit and leave the lower 8 bit cleared; the DSD-over-USB documentation does not specify whether this is legal, but there is anecdotical evidence that this is possible (and the only option for some devices) */ - *shift8_r = usb_format.format == SampleFormat::S32; - if (usb_format.format == SampleFormat::S32) - usb_format.format = SampleFormat::S24_P32; + *shift8_r = dop_format.format == SampleFormat::S32; + if (dop_format.format == SampleFormat::S32) + dop_format.format = SampleFormat::S24_P32; - if (usb_format != check) { + if (dop_format != check) { /* no bit-perfect playback, which is required for DSD over USB */ error.Format(alsa_output_domain, - "Failed to configure DSD-over-USB on ALSA device \"%s\"", + "Failed to configure DSD-over-PCM on ALSA device \"%s\"", alsa_device(ad)); delete[] ad->silence; return false; @@ -681,9 +682,9 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, { bool shift8 = false, packed, reverse_endian; - const bool dsd_usb = ad->dsd_usb && + const bool dop = ad->dop && audio_format.format == SampleFormat::DSD; - const bool success = dsd_usb + const bool success = dop ? alsa_setup_dsd(ad, audio_format, &shift8, &packed, &reverse_endian, error) @@ -694,7 +695,7 @@ alsa_setup_or_dsd(AlsaOutput *ad, AudioFormat &audio_format, ad->pcm_export->Open(audio_format.format, audio_format.channels, - dsd_usb, shift8, packed, reverse_endian); + dop, shift8, packed, reverse_endian); return true; } diff --git a/src/pcm/PcmDop.cxx b/src/pcm/PcmDop.cxx new file mode 100644 index 000000000..b2096d9e4 --- /dev/null +++ b/src/pcm/PcmDop.cxx @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "PcmDop.hxx" +#include "PcmBuffer.hxx" +#include "AudioFormat.hxx" +#include "util/ConstBuffer.hxx" + +#include + +constexpr +static inline uint32_t +pcm_two_dsd_to_dop_marker1(uint8_t a, uint8_t b) +{ + return 0xff050000 | (a << 8) | b; +} + +constexpr +static inline uint32_t +pcm_two_dsd_to_dop_marker2(uint8_t a, uint8_t b) +{ + return 0xfffa0000 | (a << 8) | b; +} + +ConstBuffer +pcm_dsd_to_dop(PcmBuffer &buffer, unsigned channels, + ConstBuffer _src) +{ + assert(audio_valid_channel_count(channels)); + assert(!_src.IsNull()); + assert(_src.size > 0); + assert(_src.size % channels == 0); + + const unsigned num_src_samples = _src.size; + const unsigned num_src_frames = num_src_samples / channels; + + /* this rounds down and discards the last odd frame; not + elegant, but good enough for now */ + const unsigned num_frames = num_src_frames / 2; + const unsigned num_samples = num_frames * channels; + + uint32_t *const dest0 = (uint32_t *)buffer.GetT(num_samples), + *dest = dest0; + + auto src = _src.data; + 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_dop_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 0xfa marker */ + + *dest++ = pcm_two_dsd_to_dop_marker2(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; + } + + return { dest0, num_samples }; +} diff --git a/src/pcm/PcmDop.hxx b/src/pcm/PcmDop.hxx new file mode 100644 index 000000000..03161c456 --- /dev/null +++ b/src/pcm/PcmDop.hxx @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2003-2014 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PCM_DOP_HXX +#define MPD_PCM_DOP_HXX + +#include "check.h" + +#include +#include + +class PcmBuffer; +template struct ConstBuffer; + +/** + * Pack DSD 1 bit samples into (padded) 24 bit PCM samples for + * playback over USB, according to the DoP standard: + * http://dsd-guide.com/dop-open-standard + */ +ConstBuffer +pcm_dsd_to_dop(PcmBuffer &buffer, unsigned channels, + ConstBuffer src); + +#endif diff --git a/src/pcm/PcmDsdUsb.cxx b/src/pcm/PcmDsdUsb.cxx deleted file mode 100644 index 9b854ad07..000000000 --- a/src/pcm/PcmDsdUsb.cxx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "PcmDsdUsb.hxx" -#include "PcmBuffer.hxx" -#include "AudioFormat.hxx" -#include "util/ConstBuffer.hxx" - -#include - -constexpr -static inline uint32_t -pcm_two_dsd_to_usb_marker1(uint8_t a, uint8_t b) -{ - return 0xff050000 | (a << 8) | b; -} - -constexpr -static inline uint32_t -pcm_two_dsd_to_usb_marker2(uint8_t a, uint8_t b) -{ - return 0xfffa0000 | (a << 8) | b; -} - -ConstBuffer -pcm_dsd_to_usb(PcmBuffer &buffer, unsigned channels, - ConstBuffer _src) -{ - assert(audio_valid_channel_count(channels)); - assert(!_src.IsNull()); - assert(_src.size > 0); - assert(_src.size % channels == 0); - - const unsigned num_src_samples = _src.size; - const unsigned num_src_frames = num_src_samples / channels; - - /* this rounds down and discards the last odd frame; not - elegant, but good enough for now */ - const unsigned num_frames = num_src_frames / 2; - const unsigned num_samples = num_frames * channels; - - uint32_t *const dest0 = (uint32_t *)buffer.GetT(num_samples), - *dest = dest0; - - auto src = _src.data; - 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 0xfa marker */ - - *dest++ = pcm_two_dsd_to_usb_marker2(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; - } - - return { dest0, num_samples }; -} diff --git a/src/pcm/PcmDsdUsb.hxx b/src/pcm/PcmDsdUsb.hxx deleted file mode 100644 index 5e05c009b..000000000 --- a/src/pcm/PcmDsdUsb.hxx +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_PCM_DSD_USB_HXX -#define MPD_PCM_DSD_USB_HXX - -#include "check.h" - -#include -#include - -class PcmBuffer; -template struct ConstBuffer; - -/** - * Pack DSD 1 bit samples into (padded) 24 bit PCM samples for - * playback over USB, according to the proposed standard by - * dCS and others: - * http://www.sonore.us/DoP_openStandard_1v1.pdf - */ -ConstBuffer -pcm_dsd_to_usb(PcmBuffer &buffer, unsigned channels, - ConstBuffer src); - -#endif diff --git a/src/pcm/PcmExport.cxx b/src/pcm/PcmExport.cxx index 5f567f3c6..ef099ba71 100644 --- a/src/pcm/PcmExport.cxx +++ b/src/pcm/PcmExport.cxx @@ -19,7 +19,7 @@ #include "config.h" #include "PcmExport.hxx" -#include "PcmDsdUsb.hxx" +#include "PcmDop.hxx" #include "PcmPack.hxx" #include "util/ByteReverse.hxx" #include "util/ConstBuffer.hxx" @@ -28,15 +28,15 @@ void PcmExport::Open(SampleFormat sample_format, unsigned _channels, - bool _dsd_usb, bool _shift8, bool _pack, bool _reverse_endian) + bool _dop, bool _shift8, bool _pack, bool _reverse_endian) { assert(audio_valid_sample_format(sample_format)); - assert(!_dsd_usb || audio_valid_channel_count(_channels)); + assert(!_dop || audio_valid_channel_count(_channels)); channels = _channels; - dsd_usb = _dsd_usb && sample_format == SampleFormat::DSD; - if (dsd_usb) - /* after the conversion to DSD-over-USB, the DSD + dop = _dop && sample_format == SampleFormat::DSD; + if (dop) + /* after the conversion to DoP, the DSD samples are stuffed inside fake 24 bit samples */ sample_format = SampleFormat::S24_P32; @@ -64,7 +64,7 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const /* packed 24 bit samples (3 bytes per sample) */ return audio_format.channels * 3; - if (dsd_usb) + if (dop) /* the DSD-over-USB draft says that DSD 1-bit samples are enclosed within 24 bit samples, and MPD's representation of 24 bit is padded to 32 bit (4 @@ -77,8 +77,8 @@ PcmExport::GetFrameSize(const AudioFormat &audio_format) const ConstBuffer PcmExport::Export(ConstBuffer data) { - if (dsd_usb) - data = pcm_dsd_to_usb(dsd_buffer, channels, + if (dop) + data = pcm_dsd_to_dop(dop_buffer, channels, ConstBuffer::FromVoid(data)) .ToVoid(); @@ -125,8 +125,8 @@ PcmExport::CalcSourceSize(size_t size) const /* 32 bit to 24 bit conversion (4 to 3 bytes) */ size = (size / 3) * 4; - if (dsd_usb) - /* DSD over USB doubles the transport size */ + if (dop) + /* DoP doubles the transport size */ size /= 2; return size; diff --git a/src/pcm/PcmExport.hxx b/src/pcm/PcmExport.hxx index 8169dad7b..b99a35835 100644 --- a/src/pcm/PcmExport.hxx +++ b/src/pcm/PcmExport.hxx @@ -35,11 +35,11 @@ template struct ConstBuffer; struct PcmExport { /** * The buffer is used to convert DSD samples to the - * DSD-over-USB format. + * DoP format. * - * @see #dsd_usb + * @see #dop */ - PcmBuffer dsd_buffer; + PcmBuffer dop_buffer; /** * The buffer is used to pack samples, removing padding. @@ -61,11 +61,11 @@ struct PcmExport { uint8_t channels; /** - * Convert DSD to DSD-over-USB? Input format must be + * Convert DSD to DSD-over-PCM (DoP)? Input format must be * SampleFormat::DSD and output format must be * SampleFormat::S24_P32. */ - bool dsd_usb; + bool dop; /** * Convert (padded) 24 bit samples to 32 bit by shifting 8 @@ -93,10 +93,10 @@ struct PcmExport { * * This function cannot fail. * - * @param channels the number of channels; ignored unless dsd_usb is set + * @param channels the number of channels; ignored unless dop is set */ void Open(SampleFormat sample_format, unsigned channels, - bool dsd_usb, bool shift8, bool pack, bool reverse_endian); + bool dop, bool shift8, bool pack, bool reverse_endian); /** * Calculate the size of one output frame. -- cgit v1.2.3