---
 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

Reply via email to