shithub: sox

Download patch

ref: 4ec68facbb721edce891a9659426bcf956eccd3f
parent: 47a2524286f71160f89b7b7f527c176deec569a9
author: Ulrich Klauer <ulrich@chirlu.de>
date: Sun Dec 25 02:04:06 EST 2011

New downsample effect

A new effect for reducing the sample rate without any decimation
filtering. Can be useful if the signal is known to be bandlimited already,
for special tasks where aliasing is desired, or after a custom
anti-aliasing filter.

--- a/ChangeLog
+++ b/ChangeLog
@@ -45,7 +45,7 @@
   o Fix crashes in compand and mcompand effects. [3420893] (Ulrich Klauer)
   o Let the delay effect gracefully handle the special case that a delay can
     be more than the input length. [3055399] (Ulrich Klauer)
-  o New hilbert effect. (Ulrich Klauer)
+  o New hilbert and downsample effects. (Ulrich Klauer)
 
 Misc:
 
--- a/msvc10/LibSoX.vcxproj
+++ b/msvc10/LibSoX.vcxproj
@@ -165,7 +165,6 @@
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
     </ClCompile>
-    <ClCompile Include="..\src\hilbert.c" />
     <ClCompile Include="..\src\oss.c">
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@@ -207,6 +206,7 @@
     <ClCompile Include="..\src\dft_filter.c" />
     <ClCompile Include="..\src\dither.c" />
     <ClCompile Include="..\src\divide.c" />
+    <ClCompile Include="..\src\downsample.c" />
     <ClCompile Include="..\src\earwax.c" />
     <ClCompile Include="..\src\echo.c" />
     <ClCompile Include="..\src\echos.c" />
@@ -216,6 +216,7 @@
     <ClCompile Include="..\src\firfit.c" />
     <ClCompile Include="..\src\flanger.c" />
     <ClCompile Include="..\src\gain.c" />
+    <ClCompile Include="..\src\hilbert.c" />
     <ClCompile Include="..\src\input.c" />
     <ClCompile Include="..\src\ladspa.c" />
     <ClCompile Include="..\src\loudness.c" />
@@ -344,4 +345,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
--- a/msvc10/LibSoX.vcxproj.filters
+++ b/msvc10/LibSoX.vcxproj.filters
@@ -612,5 +612,8 @@
     <ClCompile Include="..\src\upsample.c">
       <Filter>Effect Sources</Filter>
     </ClCompile>
+    <ClCompile Include="..\src\downsample.c">
+      <Filter>Effect Sources</Filter>
+    </ClCompile>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
--- a/msvc9/LibSoX.vcproj
+++ b/msvc9/LibSoX.vcproj
@@ -680,6 +680,10 @@
 				>
 			</File>
 			<File
+				RelativePath="..\src\downsample.c"
+				>
+			</File>
+			<File
 				RelativePath="..\src\earwax.c"
 				>
 			</File>
--- a/sox.1
+++ b/sox.1
@@ -1979,6 +1979,17 @@
 .SP
 See also the `Dithering' section above.
 .TP
+\fBdownsample [\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.
+.SP
+No decimation filter is applied.  If the input is not a properly
+bandlimited baseband signal, aliasing will occur.  This may be
+desirable, e.g., for frequency translation.
+.SP
+For a general resampling effect with anti-aliasing, see \fBrate\fR.  See
+also \fBupsample\fR.
+.TP
 \fBearwax\fR
 Makes audio easier to listen to on headphones.
 Adds `cues' to 44\*d1kHz stereo (i.e. audio CD format) audio so that
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,7 +77,7 @@
 	rate_poly_fir.h remix.c repeat.c reverb.c reverse.c silence.c \
 	sinc.c skeleff.c speed.c speexdsp.c splice.c stat.c stats.c \
 	stretch.c swap.c synth.c tempo.c tremolo.c trim.c vad.c vol.c \
-	ignore-warning.h upsample.c hilbert.c
+	ignore-warning.h upsample.c hilbert.c downsample.c
 if HAVE_PNG
     libsox_la_SOURCES += spectrogram.c
 endif
--- /dev/null
+++ b/src/downsample.c
@@ -1,0 +1,85 @@
+/* libSoX effect: Downsample
+ *
+ * First version of this effect written 11/2011 by Ulrich Klauer.
+ *
+ * Copyright 2011 Chris Bagwell and SoX Contributors
+ *
+ * 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 {
+  unsigned int factor;
+  unsigned int carry; /* number of samples still to be discarded,
+                         carried over from last block */
+} priv_t;
+
+static int create(sox_effect_t *effp, int argc, char **argv)
+{
+  priv_t *p = (priv_t*)effp->priv;
+  p->factor = 2;
+  --argc, ++argv;
+  do { /* break-able block */
+    NUMERIC_PARAMETER(factor, 1, 16384)
+  } while (0);
+  return argc ? lsx_usage(effp) : SOX_SUCCESS;
+}
+
+static int start(sox_effect_t *effp)
+{
+  priv_t *p = (priv_t*) effp->priv;
+  effp->out_signal.rate = effp->in_signal.rate / p->factor;
+  return p->factor == 1 ? SOX_EFF_NULL : SOX_SUCCESS;
+}
+
+static int flow(sox_effect_t *effp, const sox_sample_t *ibuf,
+    sox_sample_t *obuf, size_t *isamp, size_t *osamp)
+{
+  priv_t *p = (priv_t*)effp->priv;
+  size_t ilen = *isamp, olen = *osamp;
+  size_t t;
+
+  t = min(p->carry, ilen);
+  p->carry -= t;
+  ibuf += t; ilen -= t;
+
+  /* NB: either p->carry (usually) or ilen is now zero; hence, a
+     non-zero value of ilen implies p->carry == 0, and there is no
+     need to test for this in the following while and if. */
+
+  while (ilen >= p->factor && olen) {
+    *obuf++ = *ibuf;
+    ibuf += p->factor;
+    olen--; ilen -= p->factor;
+  }
+
+  if (ilen && olen) {
+    *obuf++ = *ibuf;
+    p->carry = p->factor - ilen;
+    olen--; ilen = 0;
+  }
+
+  *isamp -= ilen, *osamp -= olen;
+  return SOX_SUCCESS;
+}
+
+sox_effect_handler_t const *lsx_downsample_effect_fn(void)
+{
+  static sox_effect_handler_t handler = {"downsample", "[factor (2)]",
+    SOX_EFF_RATE | SOX_EFF_MODIFY,
+    create, start, flow, NULL, NULL, NULL, sizeof(priv_t)};
+  return &handler;
+}
--- a/src/effects.h
+++ b/src/effects.h
@@ -33,6 +33,7 @@
   EFFECT(dft_filter) /* abstract */
   EFFECT(dither)
   EFFECT(divide)
+  EFFECT(downsample)
   EFFECT(earwax)
   EFFECT(echo)
   EFFECT(echos)