--- msvc10/LibSoX.vcxproj | 1 + msvc10/LibSoX.vcxproj.filters | 3 + sox.1 | 4 ++ src/Makefile.am | 2 +- src/dop.c | 158 ++++++++++++++++++++++++++++++++++++++++++ src/effects.h | 1 + 6 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/dop.c
diff --git a/msvc10/LibSoX.vcxproj b/msvc10/LibSoX.vcxproj index 4a475cf..5136eb8 100644 --- a/msvc10/LibSoX.vcxproj +++ b/msvc10/LibSoX.vcxproj @@ -207,6 +207,7 @@ <ClCompile Include="..\src\dft_filter.c" /> <ClCompile Include="..\src\dither.c" /> <ClCompile Include="..\src\divide.c" /> + <ClCompile Include="..\src\dop.c" /> <ClCompile Include="..\src\downsample.c" /> <ClCompile Include="..\src\earwax.c" /> <ClCompile Include="..\src\echo.c" /> diff --git a/msvc10/LibSoX.vcxproj.filters b/msvc10/LibSoX.vcxproj.filters index 01bda8c..030e10f 100644 --- a/msvc10/LibSoX.vcxproj.filters +++ b/msvc10/LibSoX.vcxproj.filters @@ -213,6 +213,9 @@ <ClCompile Include="..\src\divide.c"> <Filter>Effect Sources</Filter> </ClCompile> + <ClCompile Include="..\src\dop.c"> + <Filter>Effect Sources</Filter> + </ClCompile> <ClCompile Include="..\src\earwax.c"> <Filter>Effect Sources</Filter> </ClCompile> diff --git a/sox.1 b/sox.1 index 98a84a1..f26a061 100644 --- a/sox.1 +++ b/sox.1 @@ -2021,6 +2021,10 @@ affects the audio. .SP See also the `Dithering' section above. .TP +\fBdop\fR +DSD over PCM. 1-bit DSD data is packed into 24-bit samples for +transport over non-DSD-aware links. +.TP \fBdownsample\fR [\fIfactor\fR(2)] Downsample the signal by an integer factor: Only the first out of each \fIfactor\fR samples is retained, the others are discarded. diff --git a/src/Makefile.am b/src/Makefile.am index ca7bae7..4450061 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -69,7 +69,7 @@ libsox_la_SOURCES = adpcms.c adpcms.h aiff.c aiff.h cvsd.c cvsd.h cvsdfilt.h \ libsox_la_SOURCES += \ band.h bend.c biquad.c biquad.h biquads.c chorus.c compand.c \ compandt.c compandt.h contrast.c dcshift.c delay.c dft_filter.c \ - dft_filter.h dither.c dither.h divide.c downsample.c earwax.c \ + dft_filter.h dither.c dither.h divide.c dop.c downsample.c earwax.c \ echo.c echos.c effects.c effects.h effects_i.c effects_i_dsp.c \ fade.c fft4g.c fft4g.h fifo.h fir.c firfit.c flanger.c gain.c \ hilbert.c input.c ladspa.h ladspa.c loudness.c mcompand.c \ diff --git a/src/dop.c b/src/dop.c new file mode 100644 index 0000000..e06fa9e --- /dev/null +++ b/src/dop.c @@ -0,0 +1,158 @@ +/* DSD over PCM + * Copyright (c) 2015 Mans Rullgard <m...@mansr.com> + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library 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 Lesser + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sox_i.h" + +typedef struct dop { + sox_sample_t *buf; + unsigned marker; + unsigned pos; +} dop_t; + +#define DOP_MARKER 0x05 + +static int dop_start(sox_effect_t *eff) +{ + dop_t *p = eff->priv; + + if (eff->in_signal.precision != 1) { + lsx_fail("1-bit input required"); + return SOX_EOF; + } + + if (eff->in_signal.rate != 16 * eff->out_signal.rate) { + lsx_fail("incorrect output rate, should be %.1fk", + eff->in_signal.rate / 16 / 1000); + return SOX_EOF; + } + + eff->out_signal.precision = 24; + + p->buf = lsx_calloc(eff->out_signal.channels, sizeof(*p->buf)); + p->marker = DOP_MARKER; + + return SOX_SUCCESS; +} + +static unsigned dop_load_bits(const sox_sample_t *ibuf, unsigned step, + unsigned pos, unsigned num) +{ + unsigned shift = 23 - pos; + unsigned buf = 0; + + while (num--) { + unsigned bit = *ibuf > 0 ? 1 : 0; + buf |= bit << shift; + ibuf += step; + shift--; + } + + return buf; +} + +static int dop_flow(sox_effect_t *eff, const sox_sample_t *ibuf, + sox_sample_t *obuf, size_t *isamp, size_t *osamp) +{ + dop_t *p = eff->priv; + unsigned channels = eff->in_signal.channels; + const sox_sample_t *in = ibuf; + sox_sample_t *out = obuf; + size_t ilen = *isamp / channels; + size_t olen = *osamp / channels; + unsigned i; + + if (p->pos) { + size_t n = min(16 - p->pos, ilen); + for (i = 0; i < channels; i++) + p->buf[i] |= dop_load_bits(in + i, channels, p->pos, n); + in += n * channels; + ilen -= n; + p->pos += n; + if (p->pos == 16) { + for (i = 0; i < channels; i++) + *out++ = p->buf[i] | p->marker << 24; + olen--; + p->marker ^= 0xff; + p->pos = 0; + } + } + + while (olen && ilen >= 16) { + for (i = 0; i < channels; i++) + *out++ = dop_load_bits(in + i, channels, 0, 16) | p->marker << 24; + olen--; + in += 16 * channels; + ilen -= 16; + p->marker ^= 0xff; + } + + if (olen && ilen < 16) { + size_t n = min(16 - p->pos, ilen); + for (i = 0; i < channels; i++) + p->buf[i] |= dop_load_bits(in, channels, p->pos, n); + in += n * channels; + ilen -= n; + p->pos += n; + if (p->pos == 16) { + for (i = 0; i < channels; i++) + *out++ = p->buf[i] | p->marker << 24; + olen--; + p->marker ^= 0xff; + p->pos = 0; + } + } + + *isamp = in - ibuf; + *osamp = out - obuf; + + return SOX_SUCCESS; +} + +static int dop_drain(sox_effect_t *eff, sox_sample_t *obuf, size_t *osamp) +{ + dop_t *p = eff->priv; + unsigned i; + + if (p->pos) { + for (i = 0; i < eff->in_signal.channels; i++) + *obuf++ = p->buf[i] | p->marker << 24; + *osamp = i; + } else { + *osamp = 0; + } + + return SOX_SUCCESS; +} + +static int dop_stop(sox_effect_t *eff) +{ + dop_t *p = eff->priv; + free(p->buf); + return SOX_SUCCESS; +} + +const sox_effect_handler_t *lsx_dop_effect_fn(void) +{ + static sox_effect_handler_t handler = { + "dop", NULL, + SOX_EFF_MCHAN | SOX_EFF_PREC | SOX_EFF_RATE, + NULL, dop_start, dop_flow, dop_drain, dop_stop, NULL, + sizeof(dop_t), + }; + return &handler; +} diff --git a/src/effects.h b/src/effects.h index e8987de..9e6ba10 100644 --- a/src/effects.h +++ b/src/effects.h @@ -32,6 +32,7 @@ EFFECT(dft_filter) /* abstract */ EFFECT(dither) EFFECT(divide) + EFFECT(dop) EFFECT(downsample) EFFECT(earwax) EFFECT(echo) -- 2.5.2 ------------------------------------------------------------------------------ Monitor Your Dynamic Infrastructure at Any Scale With Datadog! Get real-time metrics from all of your servers, apps and tools in one place. SourceForge users - Click here to start your Free Trial of Datadog now! http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140 _______________________________________________ SoX-devel mailing list SoX-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sox-devel