From cac3c159bc84d5163c87a40383d3eda64a4c9f69 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 29 Jul 2013 07:56:40 +0200 Subject: pcm_dsd: convert to C++ --- Makefile.am | 4 +-- src/pcm/PcmConvert.cxx | 11 +++--- src/pcm/PcmConvert.hxx | 4 +-- src/pcm/PcmDsd.cxx | 85 +++++++++++++++++++++++++++++++++++++++++++ src/pcm/PcmDsd.hxx | 46 ++++++++++++++++++++++++ src/pcm/PcmDsdUsb.cxx | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/pcm/PcmDsdUsb.hxx | 41 +++++++++++++++++++++ src/pcm/PcmExport.cxx | 2 +- src/pcm/pcm_dsd.c | 85 ------------------------------------------- src/pcm/pcm_dsd.h | 52 --------------------------- src/pcm/pcm_dsd_usb.c | 97 -------------------------------------------------- src/pcm/pcm_dsd_usb.h | 42 ---------------------- 12 files changed, 278 insertions(+), 288 deletions(-) create mode 100644 src/pcm/PcmDsd.cxx create mode 100644 src/pcm/PcmDsd.hxx create mode 100644 src/pcm/PcmDsdUsb.cxx create mode 100644 src/pcm/PcmDsdUsb.hxx delete mode 100644 src/pcm/pcm_dsd.c delete mode 100644 src/pcm/pcm_dsd.h delete mode 100644 src/pcm/pcm_dsd_usb.c delete mode 100644 src/pcm/pcm_dsd_usb.h diff --git a/Makefile.am b/Makefile.am index 7b10163fd..0185f8e5e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -307,8 +307,8 @@ libpcm_a_SOURCES = \ src/pcm/PcmExport.cxx src/pcm/PcmExport.hxx \ src/pcm/PcmConvert.cxx src/pcm/PcmConvert.hxx \ src/pcm/dsd2pcm/dsd2pcm.c src/pcm/dsd2pcm/dsd2pcm.h \ - src/pcm/pcm_dsd.c src/pcm/pcm_dsd.h \ - src/pcm/pcm_dsd_usb.c src/pcm/pcm_dsd_usb.h \ + src/pcm/PcmDsd.cxx src/pcm/PcmDsd.hxx \ + src/pcm/PcmDsdUsb.cxx src/pcm/PcmDsdUsb.hxx \ src/pcm/PcmVolume.cxx src/pcm/PcmVolume.hxx \ src/pcm/PcmMix.cxx src/pcm/PcmMix.hxx \ src/pcm/PcmChannels.cxx src/pcm/PcmChannels.hxx \ diff --git a/src/pcm/PcmConvert.cxx b/src/pcm/PcmConvert.cxx index 9618b9642..383df9156 100644 --- a/src/pcm/PcmConvert.cxx +++ b/src/pcm/PcmConvert.cxx @@ -36,7 +36,6 @@ PcmConvert::PcmConvert() { memset(this, 0, sizeof(*this)); - pcm_dsd_init(&dsd); pcm_resample_init(&resample); pcm_buffer_init(&format_buffer); @@ -45,7 +44,6 @@ PcmConvert::PcmConvert() PcmConvert::~PcmConvert() { - pcm_dsd_deinit(&dsd); pcm_resample_deinit(&resample); pcm_buffer_deinit(&format_buffer); @@ -55,7 +53,7 @@ PcmConvert::~PcmConvert() void PcmConvert::Reset() { - pcm_dsd_reset(&dsd); + dsd.Reset(); pcm_resample_reset(&resample); } @@ -278,10 +276,9 @@ PcmConvert::Convert(const audio_format *src_format, struct audio_format float_format; if (src_format->format == SAMPLE_FORMAT_DSD) { size_t f_size; - const float *f = pcm_dsd_to_float(&dsd, - src_format->channels, - false, (const uint8_t *)src, - src_size, &f_size); + const float *f = dsd.ToFloat(src_format->channels, + false, (const uint8_t *)src, + src_size, &f_size); if (f == NULL) { g_set_error_literal(error_r, pcm_convert_quark(), 0, "DSD to PCM conversion failed"); diff --git a/src/pcm/PcmConvert.hxx b/src/pcm/PcmConvert.hxx index f08188a9c..62f67ed8e 100644 --- a/src/pcm/PcmConvert.hxx +++ b/src/pcm/PcmConvert.hxx @@ -21,9 +21,9 @@ #define PCM_CONVERT_HXX #include "PcmDither.hxx" +#include "PcmDsd.hxx" extern "C" { -#include "pcm_dsd.h" #include "pcm_resample.h" #include "pcm_buffer.h" } @@ -38,7 +38,7 @@ struct audio_format; * conversions. */ class PcmConvert { - struct pcm_dsd dsd; + PcmDsd dsd; struct pcm_resample_state resample; diff --git a/src/pcm/PcmDsd.cxx b/src/pcm/PcmDsd.cxx new file mode 100644 index 000000000..fb2dfd033 --- /dev/null +++ b/src/pcm/PcmDsd.cxx @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2003-2013 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 "PcmDsd.hxx" +#include "dsd2pcm/dsd2pcm.h" + +#include + +#include + +#include + +PcmDsd::PcmDsd() +{ + pcm_buffer_init(&buffer); + + std::fill_n(dsd2pcm, G_N_ELEMENTS(dsd2pcm), nullptr); +} + +PcmDsd::~PcmDsd() +{ + pcm_buffer_deinit(&buffer); + + for (unsigned i = 0; i < G_N_ELEMENTS(dsd2pcm); ++i) + if (dsd2pcm[i] != nullptr) + dsd2pcm_destroy(dsd2pcm[i]); +} + +void +PcmDsd::Reset() +{ + for (unsigned i = 0; i < G_N_ELEMENTS(dsd2pcm); ++i) + if (dsd2pcm[i] != nullptr) + dsd2pcm_reset(dsd2pcm[i]); +} + +const float * +PcmDsd::ToFloat(unsigned channels, bool lsbfirst, + const uint8_t *src, size_t src_size, + size_t *dest_size_r) +{ + assert(src != nullptr); + assert(src_size > 0); + assert(src_size % channels == 0); + assert(channels <= G_N_ELEMENTS(dsd2pcm)); + + const unsigned num_samples = src_size; + const unsigned num_frames = src_size / channels; + + float *dest; + const size_t dest_size = num_samples * sizeof(*dest); + *dest_size_r = dest_size; + dest = (float *)pcm_buffer_get(&buffer, dest_size); + + for (unsigned c = 0; c < channels; ++c) { + if (dsd2pcm[c] == nullptr) { + dsd2pcm[c] = dsd2pcm_init(); + if (dsd2pcm[c] == nullptr) + return nullptr; + } + + dsd2pcm_translate(dsd2pcm[c], num_frames, + src + c, channels, + lsbfirst, dest + c, channels); + } + + return dest; +} diff --git a/src/pcm/PcmDsd.hxx b/src/pcm/PcmDsd.hxx new file mode 100644 index 000000000..ef71411e9 --- /dev/null +++ b/src/pcm/PcmDsd.hxx @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2003-2013 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_HXX +#define MPD_PCM_DSD_HXX + +#include "check.h" +#include "pcm_buffer.h" + +#include + +/** + * Wrapper for the dsd2pcm library. + */ +struct PcmDsd { + struct pcm_buffer buffer; + + struct dsd2pcm_ctx_s *dsd2pcm[32]; + + PcmDsd(); + ~PcmDsd(); + + void Reset(); + + const float *ToFloat(unsigned channels, bool lsbfirst, + const uint8_t *src, size_t src_size, + size_t *dest_size_r); +}; + +#endif diff --git a/src/pcm/PcmDsdUsb.cxx b/src/pcm/PcmDsdUsb.cxx new file mode 100644 index 000000000..30231e144 --- /dev/null +++ b/src/pcm/PcmDsdUsb.cxx @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2003-2013 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 "pcm_buffer.h" +#include "audio_format.h" + +G_GNUC_CONST +static inline uint32_t +pcm_two_dsd_to_usb_marker1(uint8_t a, uint8_t 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, + size_t *dest_size_r) +{ + assert(buffer != NULL); + assert(audio_valid_channel_count(channels)); + assert(src != NULL); + 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; + + const size_t dest_size = num_samples * 4; + *dest_size_r = dest_size; + uint32_t *const dest0 = (uint32_t *)pcm_buffer_get(buffer, dest_size), + *dest = dest0; + + 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; +} diff --git a/src/pcm/PcmDsdUsb.hxx b/src/pcm/PcmDsdUsb.hxx new file mode 100644 index 000000000..d4b414324 --- /dev/null +++ b/src/pcm/PcmDsdUsb.hxx @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2003-2013 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 + +struct pcm_buffer; + +/** + * 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 + */ +const uint32_t * +pcm_dsd_to_usb(struct pcm_buffer *buffer, unsigned channels, + const uint8_t *src, size_t src_size, + size_t *dest_size_r); + +#endif diff --git a/src/pcm/PcmExport.cxx b/src/pcm/PcmExport.cxx index 288b59ab4..a148e2873 100644 --- a/src/pcm/PcmExport.cxx +++ b/src/pcm/PcmExport.cxx @@ -19,9 +19,9 @@ #include "config.h" #include "PcmExport.hxx" +#include "PcmDsdUsb.hxx" extern "C" { -#include "pcm_dsd_usb.h" #include "pcm_pack.h" #include "util/byte_reverse.h" } diff --git a/src/pcm/pcm_dsd.c b/src/pcm/pcm_dsd.c deleted file mode 100644 index 76266b4cc..000000000 --- a/src/pcm/pcm_dsd.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2003-2012 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 "pcm_dsd.h" -#include "dsd2pcm/dsd2pcm.h" - -#include -#include - -void -pcm_dsd_init(struct pcm_dsd *dsd) -{ - pcm_buffer_init(&dsd->buffer); - - memset(dsd->dsd2pcm, 0, sizeof(dsd->dsd2pcm)); -} - -void -pcm_dsd_deinit(struct pcm_dsd *dsd) -{ - pcm_buffer_deinit(&dsd->buffer); - - for (unsigned i = 0; i < G_N_ELEMENTS(dsd->dsd2pcm); ++i) - if (dsd->dsd2pcm[i] != NULL) - dsd2pcm_destroy(dsd->dsd2pcm[i]); -} - -void -pcm_dsd_reset(struct pcm_dsd *dsd) -{ - for (unsigned i = 0; i < G_N_ELEMENTS(dsd->dsd2pcm); ++i) - if (dsd->dsd2pcm[i] != NULL) - dsd2pcm_reset(dsd->dsd2pcm[i]); -} - -const float * -pcm_dsd_to_float(struct pcm_dsd *dsd, unsigned channels, bool lsbfirst, - const uint8_t *src, size_t src_size, - size_t *dest_size_r) -{ - assert(dsd != NULL); - assert(src != NULL); - assert(src_size > 0); - assert(src_size % channels == 0); - assert(channels <= G_N_ELEMENTS(dsd->dsd2pcm)); - - const unsigned num_samples = src_size; - const unsigned num_frames = src_size / channels; - - float *dest; - const size_t dest_size = num_samples * sizeof(*dest); - *dest_size_r = dest_size; - dest = pcm_buffer_get(&dsd->buffer, dest_size); - - for (unsigned c = 0; c < channels; ++c) { - if (dsd->dsd2pcm[c] == NULL) { - dsd->dsd2pcm[c] = dsd2pcm_init(); - if (dsd->dsd2pcm[c] == NULL) - return NULL; - } - - dsd2pcm_translate(dsd->dsd2pcm[c], num_frames, - src + c, channels, - lsbfirst, dest + c, channels); - } - - return dest; -} diff --git a/src/pcm/pcm_dsd.h b/src/pcm/pcm_dsd.h deleted file mode 100644 index 85c2455aa..000000000 --- a/src/pcm/pcm_dsd.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2003-2012 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_H -#define MPD_PCM_DSD_H - -#include "check.h" -#include "pcm_buffer.h" - -#include -#include - -/** - * Wrapper for the dsd2pcm library. - */ -struct pcm_dsd { - struct pcm_buffer buffer; - - struct dsd2pcm_ctx_s *dsd2pcm[32]; -}; - -void -pcm_dsd_init(struct pcm_dsd *dsd); - -void -pcm_dsd_deinit(struct pcm_dsd *dsd); - -void -pcm_dsd_reset(struct pcm_dsd *dsd); - -const float * -pcm_dsd_to_float(struct pcm_dsd *dsd, unsigned channels, bool lsbfirst, - const uint8_t *src, size_t src_size, - size_t *dest_size_r); - -#endif diff --git a/src/pcm/pcm_dsd_usb.c b/src/pcm/pcm_dsd_usb.c deleted file mode 100644 index 4b5e39f39..000000000 --- a/src/pcm/pcm_dsd_usb.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2003-2012 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 "pcm_dsd_usb.h" -#include "pcm_buffer.h" -#include "audio_format.h" - -G_GNUC_CONST -static inline uint32_t -pcm_two_dsd_to_usb_marker1(uint8_t a, uint8_t 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, - size_t *dest_size_r) -{ - assert(buffer != NULL); - assert(audio_valid_channel_count(channels)); - assert(src != NULL); - 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; - - const size_t dest_size = num_samples * 4; - *dest_size_r = dest_size; - uint32_t *const dest0 = pcm_buffer_get(buffer, dest_size), - *dest = dest0; - - 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; -} diff --git a/src/pcm/pcm_dsd_usb.h b/src/pcm/pcm_dsd_usb.h deleted file mode 100644 index 389358459..000000000 --- a/src/pcm/pcm_dsd_usb.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2003-2012 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_H -#define MPD_PCM_DSD_USB_H - -#include "check.h" - -#include -#include -#include - -struct pcm_buffer; - -/** - * 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 - */ -const uint32_t * -pcm_dsd_to_usb(struct pcm_buffer *buffer, unsigned channels, - const uint8_t *src, size_t src_size, - size_t *dest_size_r); - -#endif -- cgit v1.2.3