From c69c8ffa9ec55c94dee7ce69af26b4edbd61647e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 23 Apr 2013 11:26:34 +0200 Subject: Drop DSD support for now. It should be later reintroduces in a less invasive way, e.g. through lavc. --- src/Makefile | 4 - src/audio_format.c | 3 - src/audio_format.h | 11 --- src/audio_parser.c | 6 -- src/dsd2pcm/dsd2pcm.c | 184 ---------------------------------------- src/dsd2pcm/dsd2pcm.h | 64 -------------- src/dsd2pcm/dsd2pcm.hpp | 41 --------- src/dsd2pcm/info.txt | 38 --------- src/dsd2pcm/main.cpp | 120 -------------------------- src/dsd2pcm/noiseshape.c | 83 ------------------ src/dsd2pcm/noiseshape.h | 57 ------------- src/dsd2pcm/noiseshape.hpp | 46 ---------- src/output/alsa_output_plugin.c | 64 +------------- src/output/oss_output_plugin.c | 3 +- src/pcm_convert.c | 28 ------ src/pcm_convert.h | 5 +- src/pcm_dsd.c | 85 ------------------- src/pcm_dsd.h | 52 ------------ src/pcm_dsd_usb.c | 97 --------------------- src/pcm_dsd_usb.h | 42 --------- src/pcm_export.c | 30 +------ src/pcm_export.h | 24 +----- src/pcm_mix.c | 2 - src/pcm_volume.c | 1 - 24 files changed, 10 insertions(+), 1080 deletions(-) delete mode 100644 src/dsd2pcm/dsd2pcm.c delete mode 100644 src/dsd2pcm/dsd2pcm.h delete mode 100644 src/dsd2pcm/dsd2pcm.hpp delete mode 100644 src/dsd2pcm/info.txt delete mode 100644 src/dsd2pcm/main.cpp delete mode 100644 src/dsd2pcm/noiseshape.c delete mode 100644 src/dsd2pcm/noiseshape.h delete mode 100644 src/dsd2pcm/noiseshape.hpp delete mode 100644 src/pcm_dsd.c delete mode 100644 src/pcm_dsd.h delete mode 100644 src/pcm_dsd_usb.c delete mode 100644 src/pcm_dsd_usb.h diff --git a/src/Makefile b/src/Makefile index 057f40ee..b342a1ad 100644 --- a/src/Makefile +++ b/src/Makefile @@ -87,8 +87,6 @@ OBJS = aiff.o \ pcm_buffer.o \ pcm_convert.o \ pcm_dither.o \ - pcm_dsd.o \ - pcm_dsd_usb.o \ pcm_export.o \ pcm_mix.o \ pcm_pack.o \ @@ -164,8 +162,6 @@ OBJS = aiff.o \ db/simple_db_plugin.o \ decoder/libav_decoder_plugin.o \ decoder/libav_metadata.o \ - dsd2pcm/dsd2pcm.o \ - dsd2pcm/noiseshape.o \ filter/autoconvert_filter_plugin.o \ filter/chain_filter_plugin.o \ filter/convert_filter_plugin.o \ diff --git a/src/audio_format.c b/src/audio_format.c index dc46604f..1ac29d1c 100644 --- a/src/audio_format.c +++ b/src/audio_format.c @@ -64,9 +64,6 @@ sample_format_to_string(enum sample_format format) case SAMPLE_FORMAT_FLOAT: return "f"; - - case SAMPLE_FORMAT_DSD: - return "dsd"; } /* unreachable */ diff --git a/src/audio_format.h b/src/audio_format.h index c6527e6a..bb79de39 100644 --- a/src/audio_format.h +++ b/src/audio_format.h @@ -46,12 +46,6 @@ enum sample_format { * range is -1.0f to +1.0f. */ SAMPLE_FORMAT_FLOAT, - - /** - * Direct Stream Digital. 1-bit samples; each frame has one - * byte (8 samples) per channel. - */ - SAMPLE_FORMAT_DSD, }; static const unsigned MAX_CHANNELS = 8; @@ -168,7 +162,6 @@ audio_valid_sample_format(enum sample_format format) case SAMPLE_FORMAT_S24_P32: case SAMPLE_FORMAT_S32: case SAMPLE_FORMAT_FLOAT: - case SAMPLE_FORMAT_DSD: return true; case SAMPLE_FORMAT_UNDEFINED: @@ -241,10 +234,6 @@ sample_format_size(enum sample_format format) case SAMPLE_FORMAT_FLOAT: return 4; - case SAMPLE_FORMAT_DSD: - /* each frame has 8 samples per channel */ - return 1; - case SAMPLE_FORMAT_UNDEFINED: return 0; } diff --git a/src/audio_parser.c b/src/audio_parser.c index 152eab5d..c37effff 100644 --- a/src/audio_parser.c +++ b/src/audio_parser.c @@ -88,12 +88,6 @@ parse_sample_format(const char *src, bool mask, return true; } - if (memcmp(src, "dsd", 3) == 0) { - *sample_format_r = SAMPLE_FORMAT_DSD; - *endptr_r = src + 3; - return true; - } - value = strtoul(src, &endptr, 10); if (endptr == src) { g_set_error(error_r, audio_parser_quark(), 0, diff --git a/src/dsd2pcm/dsd2pcm.c b/src/dsd2pcm/dsd2pcm.c deleted file mode 100644 index 4c764085..00000000 --- a/src/dsd2pcm/dsd2pcm.c +++ /dev/null @@ -1,184 +0,0 @@ -#include "util/bit_reverse.h" - -#include -#include - -#include "dsd2pcm.h" - -#define HTAPS 48 /* number of FIR constants */ -#define FIFOSIZE 16 /* must be a power of two */ -#define FIFOMASK (FIFOSIZE-1) /* bit mask for FIFO offsets */ -#define CTABLES ((HTAPS+7)/8) /* number of "8 MACs" lookup tables */ - -#if FIFOSIZE*8 < HTAPS*2 -#error "FIFOSIZE too small" -#endif - -/* - * Properties of this 96-tap lowpass filter when applied on a signal - * with sampling rate of 44100*64 Hz: - * - * () has a delay of 17 microseconds. - * - * () flat response up to 48 kHz - * - * () if you downsample afterwards by a factor of 8, the - * spectrum below 70 kHz is practically alias-free. - * - * () stopband rejection is about 160 dB - * - * The coefficient tables ("ctables") take only 6 Kibi Bytes and - * should fit into a modern processor's fast cache. - */ - -/* - * The 2nd half (48 coeffs) of a 96-tap symmetric lowpass filter - */ -static const double htaps[HTAPS] = { - 0.09950731974056658, - 0.09562845727714668, - 0.08819647126516944, - 0.07782552527068175, - 0.06534876523171299, - 0.05172629311427257, - 0.0379429484910187, - 0.02490921351762261, - 0.0133774746265897, - 0.003883043418804416, - -0.003284703416210726, - -0.008080250212687497, - -0.01067241812471033, - -0.01139427235000863, - -0.0106813877974587, - -0.009007905078766049, - -0.006828859761015335, - -0.004535184322001496, - -0.002425035959059578, - -0.0006922187080790708, - 0.0005700762133516592, - 0.001353838005269448, - 0.001713709169690937, - 0.001742046839472948, - 0.001545601648013235, - 0.001226696225277855, - 0.0008704322683580222, - 0.0005381636200535649, - 0.000266446345425276, - 7.002968738383528e-05, - -5.279407053811266e-05, - -0.0001140625650874684, - -0.0001304796361231895, - -0.0001189970287491285, - -9.396247155265073e-05, - -6.577634378272832e-05, - -4.07492895872535e-05, - -2.17407957554587e-05, - -9.163058931391722e-06, - -2.017460145032201e-06, - 1.249721855219005e-06, - 2.166655190537392e-06, - 1.930520892991082e-06, - 1.319400334374195e-06, - 7.410039764949091e-07, - 3.423230509967409e-07, - 1.244182214744588e-07, - 3.130441005359396e-08 -}; - -static float ctables[CTABLES][256]; -static int precalculated = 0; - -static void precalc(void) -{ - int t, e, m, k; - double acc; - if (precalculated) return; - for (t=0; t8) k=8; - for (e=0; e<256; ++e) { - acc = 0.0; - for (m=0; m> (7-m)) & 1)*2-1) * htaps[t*8+m]; - } - ctables[CTABLES-1-t][e] = (float)acc; - } - } - precalculated = 1; -} - -struct dsd2pcm_ctx_s -{ - unsigned char fifo[FIFOSIZE]; - unsigned fifopos; -}; - -extern dsd2pcm_ctx* dsd2pcm_init(void) -{ - dsd2pcm_ctx* ptr; - if (!precalculated) precalc(); - ptr = (dsd2pcm_ctx*) malloc(sizeof(dsd2pcm_ctx)); - if (ptr) dsd2pcm_reset(ptr); - return ptr; -} - -extern void dsd2pcm_destroy(dsd2pcm_ctx* ptr) -{ - free(ptr); -} - -extern dsd2pcm_ctx* dsd2pcm_clone(dsd2pcm_ctx* ptr) -{ - dsd2pcm_ctx* p2; - p2 = (dsd2pcm_ctx*) malloc(sizeof(dsd2pcm_ctx)); - if (p2) { - memcpy(p2,ptr,sizeof(dsd2pcm_ctx)); - } - return p2; -} - -extern void dsd2pcm_reset(dsd2pcm_ctx* ptr) -{ - int i; - for (i=0; ififo[i] = 0x69; /* my favorite silence pattern */ - ptr->fifopos = 0; - /* 0x69 = 01101001 - * This pattern "on repeat" makes a low energy 352.8 kHz tone - * and a high energy 1.0584 MHz tone which should be filtered - * out completely by any playback system --> silence - */ -} - -extern void dsd2pcm_translate( - dsd2pcm_ctx* ptr, - size_t samples, - const unsigned char *src, ptrdiff_t src_stride, - int lsbf, - float *dst, ptrdiff_t dst_stride) -{ - unsigned ffp; - unsigned i; - unsigned bite1, bite2; - unsigned char* p; - double acc; - ffp = ptr->fifopos; - lsbf = lsbf ? 1 : 0; - while (samples-- > 0) { - bite1 = *src & 0xFFu; - if (lsbf) bite1 = bit_reverse(bite1); - ptr->fifo[ffp] = bite1; src += src_stride; - p = ptr->fifo + ((ffp-CTABLES) & FIFOMASK); - *p = bit_reverse(*p); - acc = 0; - for (i=0; ififo[(ffp -i) & FIFOMASK] & 0xFF; - bite2 = ptr->fifo[(ffp-(CTABLES*2-1)+i) & FIFOMASK] & 0xFF; - acc += ctables[i][bite1] + ctables[i][bite2]; - } - *dst = (float)acc; dst += dst_stride; - ffp = (ffp + 1) & FIFOMASK; - } - ptr->fifopos = ffp; -} - diff --git a/src/dsd2pcm/dsd2pcm.h b/src/dsd2pcm/dsd2pcm.h deleted file mode 100644 index 80e8ce0c..00000000 --- a/src/dsd2pcm/dsd2pcm.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef DSD2PCM_H_INCLUDED -#define DSD2PCM_H_INCLUDED - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct dsd2pcm_ctx_s; - -typedef struct dsd2pcm_ctx_s dsd2pcm_ctx; - -/** - * initializes a "dsd2pcm engine" for one channel - * (precomputes tables and allocates memory) - * - * This is the only function that is not thread-safe in terms of the - * POSIX thread-safety definition because it modifies global state - * (lookup tables are computed during the first call) - */ -extern dsd2pcm_ctx* dsd2pcm_init(void); - -/** - * deinitializes a "dsd2pcm engine" - * (releases memory, don't forget!) - */ -extern void dsd2pcm_destroy(dsd2pcm_ctx *ctx); - -/** - * clones the context and returns a pointer to the - * newly allocated copy - */ -extern dsd2pcm_ctx* dsd2pcm_clone(dsd2pcm_ctx *ctx); - -/** - * resets the internal state for a fresh new stream - */ -extern void dsd2pcm_reset(dsd2pcm_ctx *ctx); - -/** - * "translates" a stream of octets to a stream of floats - * (8:1 decimation) - * @param ctx -- pointer to abstract context (buffers) - * @param samples -- number of octets/samples to "translate" - * @param src -- pointer to first octet (input) - * @param src_stride -- src pointer increment - * @param lsbitfirst -- bitorder, 0=msb first, 1=lsbfirst - * @param dst -- pointer to first float (output) - * @param dst_stride -- dst pointer increment - */ -extern void dsd2pcm_translate(dsd2pcm_ctx *ctx, - size_t samples, - const unsigned char *src, ptrdiff_t src_stride, - int lsbitfirst, - float *dst, ptrdiff_t dst_stride); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* include guard DSD2PCM_H_INCLUDED */ - diff --git a/src/dsd2pcm/dsd2pcm.hpp b/src/dsd2pcm/dsd2pcm.hpp deleted file mode 100644 index b1b2ae1c..00000000 --- a/src/dsd2pcm/dsd2pcm.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef DSD2PCM_HXX_INCLUDED -#define DSD2PCM_HXX_INCLUDED - -#include -#include -#include "dsd2pcm.h" - -/** - * C++ PImpl Wrapper for the dsd2pcm C library - */ - -class dxd -{ - dsd2pcm_ctx *handle; -public: - dxd() : handle(dsd2pcm_init()) - { if (!handle) throw std::runtime_error("wtf?!"); } - - dxd(dxd const& x) : handle(dsd2pcm_clone(x.handle)) - { if (!handle) throw std::runtime_error("wtf?!"); } - - ~dxd() { dsd2pcm_destroy(handle); } - - friend void swap(dxd & a, dxd & b) - { std::swap(a.handle,b.handle); } - - dxd& operator=(dxd x) - { swap(*this,x); return *this; } - - void translate(size_t samples, - const unsigned char *src, ptrdiff_t src_stride, - bool lsbitfirst, - float *dst, ptrdiff_t dst_stride) - { - dsd2pcm_translate(handle,samples,src,src_stride, - lsbitfirst,dst,dst_stride); - } -}; - -#endif // DSD2PCM_HXX_INCLUDED - diff --git a/src/dsd2pcm/info.txt b/src/dsd2pcm/info.txt deleted file mode 100644 index 15ff2924..00000000 --- a/src/dsd2pcm/info.txt +++ /dev/null @@ -1,38 +0,0 @@ -You downloaded the source code for "dsd2pcm" which is a simple little -"filter" program, that takes a DSD data stream on stdin and converts -it to a PCM stream (352.8 kHz, either 16 or 24 bits) and writes it to -stdout. The code is split into three modules: - - (1) dsd2pcm - - This is where the 8:1 decimation magic happens. It's an - implementation of a symmetric 96-taps FIR lowpass filter - optimized for DSD inputs. If you feed this converter with - DSD64 you get a PCM stream at 352.8 kHz and floating point - samples. This module is independent and can be reused. - - (2) noiseshape - - A module for applying generic noise shaping filters. It's - used for the 16-bit output mode in "main" to preserve the - dynamic range. This module is independent and can be reused. - - (3) main.cpp (file contains the main function and handles I/O) - -The first two modules are pure C for maximum portability. In addition, -there are C++ wrapper headers for convenient use of these modules in -C++. The main application is a C++ application and makes use of the -C++ headers to access the functionality of the first two modules. - - -Under Linux this program is easily compiled by typing - - g++ *.c *.cpp -O3 -o dsd2pcm - -provided you have GCC installed. That's why I didn't bother writing -any makefiles. :-p - - -Cheers! -SG - diff --git a/src/dsd2pcm/main.cpp b/src/dsd2pcm/main.cpp deleted file mode 100644 index 0b58888a..00000000 --- a/src/dsd2pcm/main.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include - -#include "dsd2pcm.hpp" -#include "noiseshape.hpp" - -namespace { - -const float my_ns_coeffs[] = { -// b1 b2 a1 a2 - -1.62666423, 0.79410094, 0.61367127, 0.23311013, // section 1 - -1.44870017, 0.54196219, 0.03373857, 0.70316556 // section 2 -}; - -const int my_ns_soscount = sizeof(my_ns_coeffs)/(sizeof(my_ns_coeffs[0])*4); - -inline long myround(float x) -{ - return static_cast(x + (x>=0 ? 0.5f : -0.5f)); -} - -template -struct id { typedef T type; }; - -template -inline T clip( - typename id::type min, - T v, - typename id::type max) -{ - if (vmax) return max; - return v; -} - -inline void write_intel16(unsigned char * ptr, unsigned word) -{ - ptr[0] = word & 0xFF; - ptr[1] = (word >> 8) & 0xFF; -} - -inline void write_intel24(unsigned char * ptr, unsigned long word) -{ - ptr[0] = word & 0xFF; - ptr[1] = (word >> 8) & 0xFF; - ptr[2] = (word >> 16) & 0xFF; -} - -} // anonymous namespace - -using std::vector; -using std::cin; -using std::cout; -using std::cerr; - -int main(int argc, char *argv[]) -{ - const int block = 16384; - int channels = -1; - int lsbitfirst = -1; - int bits = -1; - if (argc==4) { - if ('1'<=argv[1][0] && argv[1][0]<='9') channels = 1 + (argv[1][0]-'1'); - if (argv[2][0]=='m' || argv[2][0]=='M') lsbitfirst=0; - if (argv[2][0]=='l' || argv[2][0]=='L') lsbitfirst=1; - if (!strcmp(argv[3],"16")) bits = 16; - if (!strcmp(argv[3],"24")) bits = 24; - } - if (channels<1 || lsbitfirst<0 || bits<0) { - cerr << "\n" - "DSD2PCM filter (raw DSD64 --> 352 kHz raw PCM)\n" - "(c) 2009 Sebastian Gesemann\n\n" - "(filter as in \"reads data from stdin and writes to stdout\")\n\n" - "Syntax: dsd2pcm \n" - "channels = 1,2,3,...,9 (number of channels in DSD stream)\n" - "bitorder = L (lsb first), M (msb first) (DSD stream option)\n" - "bitdepth = 16 or 24 (intel byte order, output option)\n\n" - "Note: At 16 bits/sample a noise shaper kicks in that can preserve\n" - "a dynamic range of 135 dB below 30 kHz.\n\n"; - return 1; - } - int bytespersample = bits/8; - vector dxds (channels); - vector ns; - if (bits==16) { - ns.resize(channels, noise_shaper(my_ns_soscount, my_ns_coeffs) ); - } - vector dsd_data (block * channels); - vector float_data (block); - vector pcm_data (block * channels * bytespersample); - char * const dsd_in = reinterpret_cast(&dsd_data[0]); - char * const pcm_out = reinterpret_cast(&pcm_data[0]); - while (cin.read(dsd_in,block * channels)) { - for (int c=0; c -#include - -#include "noiseshape.h" - -extern int noise_shape_init( - noise_shape_ctx *ctx, - int sos_count, - const float *coeffs) -{ - int i; - ctx->sos_count = sos_count; - ctx->bbaa = coeffs; - ctx->t1 = (float*) malloc(sizeof(float)*sos_count); - if (!ctx->t1) goto escape1; - ctx->t2 = (float*) malloc(sizeof(float)*sos_count); - if (!ctx->t2) goto escape2; - for (i=0; it1[i] = 0.f; - ctx->t2[i] = 0.f; - } - return 0; -escape2: - free(ctx->t1); -escape1: - return -1; -} - -extern void noise_shape_destroy( - noise_shape_ctx *ctx) -{ - free(ctx->t1); - free(ctx->t2); -} - -extern int noise_shape_clone( - const noise_shape_ctx *from, - noise_shape_ctx *to) -{ - to->sos_count = from->sos_count; - to->bbaa = from->bbaa; - to->t1 = (float*) malloc(sizeof(float)*to->sos_count); - if (!to->t1) goto error1; - to->t2 = (float*) malloc(sizeof(float)*to->sos_count); - if (!to->t2) goto error2; - memcpy(to->t1,from->t1,sizeof(float)*to->sos_count); - memcpy(to->t2,from->t2,sizeof(float)*to->sos_count); - return 0; -error2: - free(to->t1); -error1: - return -1; -} - -extern float noise_shape_get(noise_shape_ctx *ctx) -{ - int i; - float acc; - const float *c; - acc = 0.0; - c = ctx->bbaa; - for (i=0; isos_count; ++i) { - float t1i = ctx->t1[i]; - float t2i = ctx->t2[i]; - ctx->t2[i] = acc -= t1i * c[2] + t2i * c[3]; - acc += t1i * c[0] + t2i * c[1]; - c += 4; - } - return acc; -} - -extern void noise_shape_update(noise_shape_ctx *ctx, float qerror) -{ - float *p; - int i; - for (i=0; isos_count; ++i) { - ctx->t2[i] += qerror; - } - p = ctx->t1; - ctx->t1 = ctx->t2; - ctx->t2 = p; -} - diff --git a/src/dsd2pcm/noiseshape.h b/src/dsd2pcm/noiseshape.h deleted file mode 100644 index 6075f0d8..00000000 --- a/src/dsd2pcm/noiseshape.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef NOISE_SHAPE_H_INCLUDED -#define NOISE_SHAPE_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct noise_shape_ctx_s { - int sos_count; /* number of second order sections */ - const float *bbaa; /* filter coefficients, owned by user */ - float *t1, *t2; /* filter state, owned by ns library */ -} noise_shape_ctx; - -/** - * initializes a noise_shaper context - * returns an error code or 0 - */ -extern int noise_shape_init( - noise_shape_ctx *ctx, - int sos_count, - const float *coeffs); - -/** - * destroys a noise_shaper context - */ -extern void noise_shape_destroy( - noise_shape_ctx *ctx); - -/** - * initializes a noise_shaper context so that its state - * is a copy of a given context - * returns an error code or 0 - */ -extern int noise_shape_clone( - const noise_shape_ctx *from, noise_shape_ctx *to); - -/** - * computes the next "noise shaping sample". Note: This call - * alters the internal state. xxx_get and xxx_update must be - * called in an alternating manner. - */ -extern float noise_shape_get( - noise_shape_ctx *ctx); - -/** - * updates the noise shaper's state with the - * last quantization error - */ -extern void noise_shape_update( - noise_shape_ctx *ctx, float qerror); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* NOISE_SHAPE_H_INCLUDED */ - diff --git a/src/dsd2pcm/noiseshape.hpp b/src/dsd2pcm/noiseshape.hpp deleted file mode 100644 index 726272f9..00000000 --- a/src/dsd2pcm/noiseshape.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef NOISE_SHAPE_HXX_INCLUDED -#define NOISE_SHAPE_HXX_INCLUDED - -#include -#include "noiseshape.h" - -/** - * C++ wrapper for the noiseshape C library - */ - -class noise_shaper -{ - noise_shape_ctx ctx; -public: - noise_shaper(int sos_count, const float *bbaa) - { - if (noise_shape_init(&ctx,sos_count,bbaa)) - throw std::runtime_error("noise shaper initialization failed"); - } - - noise_shaper(noise_shaper const& x) - { - if (noise_shape_clone(&x.ctx,&ctx)) - throw std::runtime_error("noise shaper initialization failed"); - } - - ~noise_shaper() - { noise_shape_destroy(&ctx); } - - noise_shaper& operator=(noise_shaper const& x) - { - if (this != &x) { - noise_shape_destroy(&ctx); - if (noise_shape_clone(&x.ctx,&ctx)) - throw std::runtime_error("noise shaper initialization failed"); - } - return *this; - } - - float get() { return noise_shape_get(&ctx); } - - void update(float error) { noise_shape_update(&ctx,error); } -}; - -#endif /* NOISE_SHAPE_HXX_INCLUDED */ - diff --git a/src/output/alsa_output_plugin.c b/src/output/alsa_output_plugin.c index d8b18427..4470e05e 100644 --- a/src/output/alsa_output_plugin.c +++ b/src/output/alsa_output_plugin.c @@ -55,14 +55,6 @@ struct alsa_data { /** use memory mapped I/O? */ bool use_mmap; - /** - * Enable DSD over USB according to the dCS suggested - * standard? - * - * @see http://www.dcsltd.co.uk/page/assets/DSDoverUSB.pdf - */ - bool dsd_usb; - /** libasound's buffer_time setting (in microseconds) */ unsigned int buffer_time; @@ -136,8 +128,6 @@ alsa_configure(struct alsa_data *ad, const struct config_param *param) ad->use_mmap = config_get_block_bool(param, "use_mmap", false); - ad->dsd_usb = config_get_block_bool(param, "dsd_usb", false); - ad->buffer_time = config_get_block_unsigned(param, "buffer_time", MPD_ALSA_BUFFER_TIME_US); ad->period_time = config_get_block_unsigned(param, "period_time", 0); @@ -226,7 +216,6 @@ get_bitformat(enum sample_format sample_format) { switch (sample_format) { case SAMPLE_FORMAT_UNDEFINED: - case SAMPLE_FORMAT_DSD: return SND_PCM_FORMAT_UNKNOWN; case SAMPLE_FORMAT_S8: @@ -585,66 +574,17 @@ error: return false; } -static bool -alsa_setup_dsd(struct alsa_data *ad, struct audio_format *audio_format, - bool *shift8_r, bool *packed_r, bool *reverse_endian_r, - GError **error_r) -{ - assert(ad->dsd_usb); - assert(audio_format->format == SAMPLE_FORMAT_DSD); - - /* pass 24 bit to alsa_setup() */ - - struct audio_format usb_format = *audio_format; - usb_format.format = SAMPLE_FORMAT_S24_P32; - usb_format.sample_rate /= 2; - - const struct audio_format check = usb_format; - - if (!alsa_setup(ad, &usb_format, packed_r, reverse_endian_r, error_r)) - return false; - - /* if the device allows only 32 bit, shift all DSD-over-USB - 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 == SAMPLE_FORMAT_S32; - if (usb_format.format == SAMPLE_FORMAT_S32) - usb_format.format = SAMPLE_FORMAT_S24_P32; - - if (!audio_format_equals(&usb_format, &check)) { - /* no bit-perfect playback, which is required - for DSD over USB */ - g_set_error(error_r, alsa_output_quark(), 0, - "Failed to configure DSD-over-USB on ALSA device \"%s\"", - alsa_device(ad)); - return false; - } - - return true; -} - static bool alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format, GError **error_r) { bool shift8 = false, packed, reverse_endian; - const bool dsd_usb = ad->dsd_usb && - audio_format->format == SAMPLE_FORMAT_DSD; - const bool success = dsd_usb - ? alsa_setup_dsd(ad, audio_format, - &shift8, &packed, &reverse_endian, - error_r) - : alsa_setup(ad, audio_format, &packed, &reverse_endian, - error_r); + const bool success = alsa_setup(ad, audio_format, &packed, &reverse_endian, error_r); if (!success) return false; - pcm_export_open(&ad->export, - audio_format->format, audio_format->channels, - dsd_usb, shift8, packed, reverse_endian); + pcm_export_open(&ad->export, audio_format->format, shift8, packed, reverse_endian); return true; } diff --git a/src/output/oss_output_plugin.c b/src/output/oss_output_plugin.c index e366a453..aa9c00fc 100644 --- a/src/output/oss_output_plugin.c +++ b/src/output/oss_output_plugin.c @@ -432,7 +432,6 @@ sample_format_to_oss(enum sample_format format) switch (format) { case SAMPLE_FORMAT_UNDEFINED: case SAMPLE_FORMAT_FLOAT: - case SAMPLE_FORMAT_DSD: return AFMT_QUERY; case SAMPLE_FORMAT_S8: @@ -539,7 +538,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format, *oss_format_r = oss_format; #ifdef AFMT_S24_PACKED - pcm_export_open(export, sample_format, 0, false, false, + pcm_export_open(export, sample_format, false, oss_format == AFMT_S24_PACKED, oss_format == AFMT_S24_PACKED && G_BYTE_ORDER != G_LITTLE_ENDIAN); diff --git a/src/pcm_convert.c b/src/pcm_convert.c index 34e6c32b..67f8d5e7 100644 --- a/src/pcm_convert.c +++ b/src/pcm_convert.c @@ -35,21 +35,16 @@ void pcm_convert_init(struct pcm_convert_state *state) { memset(state, 0, sizeof(*state)); - - pcm_dsd_init(&state->dsd); } void pcm_convert_deinit(struct pcm_convert_state *state) { - pcm_dsd_deinit(&state->dsd); - avresample_free(&state->avr); } void pcm_convert_reset(struct pcm_convert_state *state) { - pcm_dsd_reset(&state->dsd); avresample_free(&state->avr); } @@ -61,29 +56,6 @@ AVFrame *pcm_convert(struct pcm_convert_state *state, AVFrame *dst; int ret; -#if 0 // FIXME - struct audio_format float_format; - if (src_format->format == SAMPLE_FORMAT_DSD) { - size_t f_size; - const float *f = pcm_dsd_to_float(&state->dsd, - src_format->channels, - false, src, src_size, - &f_size); - if (f == NULL) { - g_set_error_literal(error_r, pcm_convert_quark(), 0, - "DSD to PCM conversion failed"); - return NULL; - } - - float_format = *src_format; - float_format.format = SAMPLE_FORMAT_FLOAT; - - src_format = &float_format; - src = f; - src_size = f_size; - } -#endif - if (!state->avr) { char in_layout[128], out_layout[128]; state->avr = avresample_alloc_context(); diff --git a/src/pcm_convert.h b/src/pcm_convert.h index 9f4f1a68..01a5c8a6 100644 --- a/src/pcm_convert.h +++ b/src/pcm_convert.h @@ -20,9 +20,10 @@ #ifndef PCM_CONVERT_H #define PCM_CONVERT_H -#include "pcm_dsd.h" #include "pcm_dither.h" +#include + #include #include #include @@ -35,8 +36,6 @@ struct audio_format; * conversions. */ struct pcm_convert_state { - struct pcm_dsd dsd; - AVAudioResampleContext *avr; enum AVSampleFormat dst_format; int dst_samplerate; diff --git a/src/pcm_dsd.c b/src/pcm_dsd.c deleted file mode 100644 index 76266b4c..00000000 --- a/src/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_dsd.h b/src/pcm_dsd.h deleted file mode 100644 index 85c2455a..00000000 --- a/src/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_dsd_usb.c b/src/pcm_dsd_usb.c deleted file mode 100644 index 4b5e39f3..00000000 --- a/src/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_dsd_usb.h b/src/pcm_dsd_usb.h deleted file mode 100644 index 38935845..00000000 --- a/src/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 diff --git a/src/pcm_export.c b/src/pcm_export.c index 144ac71c..b430318e 100644 --- a/src/pcm_export.c +++ b/src/pcm_export.c @@ -19,7 +19,6 @@ #include "config.h" #include "pcm_export.h" -#include "pcm_dsd_usb.h" #include "pcm_pack.h" #include "util/byte_reverse.h" @@ -28,30 +27,20 @@ pcm_export_init(struct pcm_export_state *state) { pcm_buffer_init(&state->reverse_buffer); pcm_buffer_init(&state->pack_buffer); - pcm_buffer_init(&state->dsd_buffer); } void pcm_export_deinit(struct pcm_export_state *state) { pcm_buffer_deinit(&state->reverse_buffer); pcm_buffer_deinit(&state->pack_buffer); - pcm_buffer_deinit(&state->dsd_buffer); } void pcm_export_open(struct pcm_export_state *state, - enum sample_format sample_format, unsigned channels, - bool dsd_usb, bool shift8, bool pack, bool reverse_endian) + enum sample_format sample_format, + bool shift8, bool pack, bool reverse_endian) { assert(audio_valid_sample_format(sample_format)); - assert(!dsd_usb || audio_valid_channel_count(channels)); - - state->channels = channels; - state->dsd_usb = dsd_usb && sample_format == SAMPLE_FORMAT_DSD; - if (state->dsd_usb) - /* after the conversion to DSD-over-USB, the DSD - samples are stuffed inside fake 24 bit samples */ - sample_format = SAMPLE_FORMAT_S24_P32; state->shift8 = shift8 && sample_format == SAMPLE_FORMAT_S24_P32; state->pack24 = pack && sample_format == SAMPLE_FORMAT_S24_P32; @@ -81,13 +70,6 @@ pcm_export_frame_size(const struct pcm_export_state *state, /* packed 24 bit samples (3 bytes per sample) */ return audio_format->channels * 3; - if (state->dsd_usb) - /* 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 - bytes per sample) */ - return audio_format->channels * 4; - return audio_format_frame_size(audio_format); } @@ -95,10 +77,6 @@ const void * pcm_export(struct pcm_export_state *state, const void *data, size_t size, size_t *dest_size_r) { - if (state->dsd_usb) - data = pcm_dsd_to_usb(&state->dsd_buffer, state->channels, - data, size, &size); - if (state->pack24) { assert(size % 4 == 0); @@ -152,9 +130,5 @@ pcm_export_source_size(const struct pcm_export_state *state, size_t size) /* 32 bit to 24 bit conversion (4 to 3 bytes) */ size = (size / 3) * 4; - if (state->dsd_usb) - /* DSD over USB doubles the transport size */ - size /= 2; - return size; } diff --git a/src/pcm_export.h b/src/pcm_export.h index a7e7c3f6..096ae8a6 100644 --- a/src/pcm_export.h +++ b/src/pcm_export.h @@ -34,14 +34,6 @@ struct audio_format; * representation which are not supported by the pcm_convert library. */ struct pcm_export_state { - /** - * The buffer is used to convert DSD samples to the - * DSD-over-USB format. - * - * @see #dsd_usb - */ - struct pcm_buffer dsd_buffer; - /** * The buffer is used to pack samples, removing padding. * @@ -61,13 +53,6 @@ struct pcm_export_state { */ uint8_t channels; - /** - * Convert DSD to DSD-over-USB? Input format must be - * SAMPLE_FORMAT_DSD and output format must be - * SAMPLE_FORMAT_S24_P32. - */ - bool dsd_usb; - /** * Convert (padded) 24 bit samples to 32 bit by shifting 8 * bits to the left? @@ -106,13 +91,10 @@ pcm_export_deinit(struct pcm_export_state *state); * times to reuse the object, until pcm_export_deinit() is called. * * This function cannot fail. - * - * @param channels the number of channels; ignored unless dsd_usb is set */ -void -pcm_export_open(struct pcm_export_state *state, - enum sample_format sample_format, unsigned channels, - bool dsd_usb, bool shift8, bool pack, bool reverse_endian); +void pcm_export_open(struct pcm_export_state *state, + enum sample_format sample_format, + bool shift8, bool pack, bool reverse_endian); /** * Calculate the size of one output frame. diff --git a/src/pcm_mix.c b/src/pcm_mix.c index 6c6d1b4a..9f344f78 100644 --- a/src/pcm_mix.c +++ b/src/pcm_mix.c @@ -119,7 +119,6 @@ pcm_add_vol(void *buffer1, const void *buffer2, size_t size, { switch (format) { case SAMPLE_FORMAT_UNDEFINED: - case SAMPLE_FORMAT_DSD: /* not implemented */ return false; @@ -228,7 +227,6 @@ pcm_add(void *buffer1, const void *buffer2, size_t size, { switch (format) { case SAMPLE_FORMAT_UNDEFINED: - case SAMPLE_FORMAT_DSD: /* not implemented */ return false; diff --git a/src/pcm_volume.c b/src/pcm_volume.c index 49c86026..d6c282c9 100644 --- a/src/pcm_volume.c +++ b/src/pcm_volume.c @@ -158,7 +158,6 @@ pcm_volume(void *buffer, size_t length, const void *end = pcm_end_pointer(buffer, length); switch (format) { case SAMPLE_FORMAT_UNDEFINED: - case SAMPLE_FORMAT_DSD: /* not implemented */ return false; -- cgit v1.2.3