shithub: sox

Download patch

ref: 0e004134fdfe3a63e7dd44e2e44f5009489fd248
parent: ab3579456b8484ef94615d30e59f6871833cd5e7
author: robs <robs>
date: Sat Dec 13 17:08:06 EST 2008

moving some things around

--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -28,16 +28,16 @@
 
 # Format with: !xargs echo|tr ' ' '\n'|sort|column|expand|sed 's/^/  /'
 set(effects_srcs
-  bend            earwax          mixer           rate            stat
-  biquad          echo            noiseprof       remix           stretch
-  biquads         echos           noisered        repeat          swap
-  chorus          fade            normalise       resample        synth
-  compand         fft4g           output          reverb          tempo
-  compandt        filter          overdrive       reverse         tremolo
-  contrast        flanger         pad             silence         trim
-  dcshift         input           pan             skeleff         vol
-  delay           loudness        phaser          speed effects_i_dsp
-  dither          mcompand        polyphas        splice
+  bend            dither          lowfir          phaser          speed
+  biquad          earwax          mcompand        polyphas        splice
+  biquads         echo            mixer           rate            stat
+  chorus          echos           noiseprof       remix           stretch
+  compand         fade            noisered        repeat          swap
+  compandt        fft4g           normalise       resample        synth
+  contrast        filter          output          reverb          tempo
+  dcshift         flanger         overdrive       reverse         tremolo
+  delay           input           pad             silence         trim
+  dft_filter      loudness        pan             skeleff         vol
 )
 set(formats_srcs
   8svx            dat             ima-fmt         s3-fmt          u3-fmt
@@ -54,11 +54,11 @@
   cvsd-fmt        htk             s2-fmt          u2-fmt
 )
 add_library(lib${PROJECT_NAME}
-  effects                 ${formats_srcs}         ${optional_srcs}
-  effects_i               getopt                  soxstdint
+  effects                 formats_i               libsox_i
+  effects_i               ${formats_srcs}         ${optional_srcs}
+  effects_i_dsp           getopt                  soxstdint
   ${effects_srcs}         getopt1                 util
   formats                 libsox                  xmalloc
-  formats_i               libsox_i
 )
 add_executable(${PROJECT_NAME} ${PROJECT_NAME}.c)
 target_link_libraries(${PROJECT_NAME} lib${PROJECT_NAME} lpc10 ${optional_libs})
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -273,7 +273,8 @@
 	polyphas.c rabbit.c rate.c rate_filters.h rate_half_fir.h \
 	rate_poly_fir0.h rate_poly_fir.h remix.c repeat.c resample.c reverb.c \
 	reverse.c silence.c skeleff.c speed.c splice.c stat.c swap.c stretch.c \
-	synth.c tempo.c tremolo.c trim.c vol.c overdrive.c effects_i_dsp.c
+	synth.c tempo.c tremolo.c trim.c vol.c overdrive.c effects_i_dsp.c \
+	dft_filter.c dft_filter.h lowfir.c
 if HAVE_PNG
     libsox_la_SOURCES += spectrogram.c
 endif
--- /dev/null
+++ b/src/dft_filter.c
@@ -1,0 +1,129 @@
+/* Effect: dft filter     Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * 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"
+#include "fft4g.h"
+#include "dft_filter.h"
+#include <string.h>
+
+typedef dft_filter_filter_t filter_t;
+typedef dft_filter_priv_t priv_t;
+
+static int start(sox_effect_t * effp)
+{
+  priv_t * p = (priv_t *) effp->priv;
+
+  fifo_create(&p->input_fifo, (int)sizeof(double));
+  memset(fifo_reserve(&p->input_fifo,
+        p->filter_ptr->post_peak), 0, sizeof(double) * p->filter_ptr->post_peak);
+  fifo_create(&p->output_fifo, (int)sizeof(double));
+  return SOX_SUCCESS;
+}
+
+static void filter(priv_t * p)
+{
+  int i, num_in = max(0, fifo_occupancy(&p->input_fifo));
+  filter_t const * f = p->filter_ptr;
+  int const overlap = f->num_taps - 1;
+  double * output;
+
+  while (num_in >= f->dft_length) {
+    double const * input = fifo_read_ptr(&p->input_fifo);
+    fifo_read(&p->input_fifo, f->dft_length - overlap, NULL);
+    num_in -= f->dft_length - overlap;
+
+    output = fifo_reserve(&p->output_fifo, f->dft_length);
+    fifo_trim_by(&p->output_fifo, overlap);
+    memcpy(output, input, f->dft_length * sizeof(*output));
+
+    lsx_rdft(f->dft_length, 1, output, lsx_fft_br, lsx_fft_sc);
+    output[0] *= f->coefs[0];
+    output[1] *= f->coefs[1];
+    for (i = 2; i < f->dft_length; i += 2) {
+      double tmp = output[i];
+      output[i  ] = f->coefs[i  ] * tmp - f->coefs[i+1] * output[i+1];
+      output[i+1] = f->coefs[i+1] * tmp + f->coefs[i  ] * output[i+1];
+    }
+    lsx_rdft(f->dft_length, -1, output, lsx_fft_br, lsx_fft_sc);
+  }
+}
+
+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 i, odone = min(*osamp, (size_t)fifo_occupancy(&p->output_fifo));
+  double const * s = fifo_read(&p->output_fifo, (int)odone, NULL);
+  SOX_SAMPLE_LOCALS;
+
+  for (i = 0; i < odone; ++i)
+    *obuf++ = SOX_FLOAT_64BIT_TO_SAMPLE(*s++, effp->clips);
+  p->samples_out += odone;
+
+  if (*isamp && odone < *osamp) {
+    double * t = fifo_write(&p->input_fifo, (int)*isamp, NULL);
+    p->samples_in += (int)*isamp;
+
+    for (i = *isamp; i; --i)
+      *t++ = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf++, effp->clips);
+    filter(p);
+  }
+  else *isamp = 0;
+  *osamp = odone;
+  return SOX_SUCCESS;
+}
+
+static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
+{
+  priv_t * p = (priv_t *)effp->priv;
+  static size_t isamp = 0;
+  size_t samples_out = p->samples_in;
+  size_t remaining = samples_out - p->samples_out;
+  double * buff = lsx_calloc(1024, sizeof(*buff));
+
+  if ((int)remaining > 0) {
+    while ((size_t)fifo_occupancy(&p->output_fifo) < remaining) {
+      fifo_write(&p->input_fifo, 1024, buff);
+      p->samples_in += 1024;
+      filter(p);
+    }
+    fifo_trim_to(&p->output_fifo, (int)remaining);
+    p->samples_in = 0;
+  }
+  free(buff);
+  return flow(effp, 0, obuf, &isamp, osamp);
+}
+
+static int stop(sox_effect_t * effp)
+{
+  priv_t * p = (priv_t *) effp->priv;
+
+  fifo_delete(&p->input_fifo);
+  fifo_delete(&p->output_fifo);
+  free(p->filter_ptr->coefs);
+  memset(p->filter_ptr, 0, sizeof(*p->filter_ptr));
+  return SOX_SUCCESS;
+}
+
+sox_effect_handler_t const * sox_dft_filter_effect_fn(void)
+{
+  static sox_effect_handler_t handler = {
+    "dft_filter", NULL, SOX_EFF_DEPRECATED,
+    NULL, start, flow, drain, stop, NULL, 0
+  };
+  return &handler;
+}
--- /dev/null
+++ b/src/dft_filter.h
@@ -1,0 +1,15 @@
+#include "fft4g.h"
+#define  FIFO_SIZE_T int
+#include "fifo.h"
+
+typedef struct {
+  int        dft_length, num_taps, post_peak;
+  double   * coefs;
+} dft_filter_filter_t;
+
+typedef struct {
+  size_t     samples_in, samples_out;
+  fifo_t     input_fifo, output_fifo;
+  dft_filter_filter_t   filter, * filter_ptr;
+} dft_filter_priv_t;
+
--- a/src/effects.h
+++ b/src/effects.h
@@ -27,6 +27,7 @@
   EFFECT(dcshift)
   EFFECT(deemph)
   EFFECT(delay)
+  EFFECT(dft_filter)
   EFFECT(dither)
   EFFECT(earwax)
   EFFECT(echo)
@@ -43,6 +44,7 @@
   EFFECT(ladspa)
 #endif
   EFFECT(loudness)
+  EFFECT(lowfir)
   EFFECT(lowpass)
   EFFECT(mcompand)
   EFFECT(mixer)
--- a/src/effects_i.c
+++ b/src/effects_i.c
@@ -1,7 +1,7 @@
 /* Implements a libSoX internal interface for implementing effects.
  * All public functions & data are prefixed with lsx_ .
  *
- * (c) 2005-8 Chris Bagwell and SoX contributors
+ * Copyright (c) 2005-8 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
--- a/src/loudness.c
+++ b/src/loudness.c
@@ -16,28 +16,20 @@
  */
 
 #include "sox_i.h"
-#include "fft4g.h"
-#define  FIFO_SIZE_T int
-#include "fifo.h"
+#include "dft_filter.h"
 #include <string.h>
 
 typedef struct {
-  int        dft_length, num_taps;
-  double   * coefs;
-} filter_t;
-
-typedef struct {
+  dft_filter_priv_t base;
   double     delta, start;
   int        n;
-  size_t     samples_in, samples_out;
-  fifo_t     input_fifo, output_fifo;
-  filter_t   filter, * filter_ptr;
 } priv_t;
 
 static int create(sox_effect_t * effp, int argc, char **argv)
 {
   priv_t * p = (priv_t *)effp->priv;
-  p->filter_ptr = &p->filter;
+  dft_filter_priv_t * b = &p->base;
+  b->filter_ptr = &b->filter;
   p->delta = -10;
   p->start = 65;
   p->n = 1023;
@@ -104,119 +96,36 @@
 static int start(sox_effect_t * effp)
 {
   priv_t * p = (priv_t *) effp->priv;
-  int i, half = p->n / 2, dft_length = lsx_set_dft_length(p->n);
-  double * h;
+  dft_filter_filter_t * f = p->base.filter_ptr;
 
   if (p->delta == 0)
     return SOX_EFF_NULL;
 
-  if (!p->filter_ptr->num_taps) {
-    h = make_filter(p->n, p->start, p->delta, effp->in_signal.rate);
-    p->filter_ptr->coefs = lsx_calloc(dft_length, sizeof(*p->filter_ptr->coefs));
+  if (!f->num_taps) {
+    double * h = make_filter(p->n, p->start, p->delta, effp->in_signal.rate);
+    int i, dft_length = lsx_set_dft_length(p->n);
+    f->coefs = lsx_calloc(dft_length, sizeof(*f->coefs));
     for (i = 0; i < p->n; ++i)
-      p->filter_ptr->coefs[(i + dft_length - p->n + 1) & (dft_length - 1)]
+      f->coefs[(i + dft_length - p->n + 1) & (dft_length - 1)]
           = h[i] / dft_length * 2;
     free(h);
-    p->filter_ptr->num_taps = p->n;
-    p->filter_ptr->dft_length = dft_length;
-    lsx_safe_rdft(dft_length, 1, p->filter_ptr->coefs);
+    f->num_taps = p->n;
+    f->post_peak = f->num_taps / 2;
+    f->dft_length = dft_length;
+    lsx_safe_rdft(dft_length, 1, f->coefs);
   }
-  fifo_create(&p->input_fifo, (int)sizeof(double));
-  memset(fifo_reserve(&p->input_fifo, half), 0, sizeof(double) * half);
-  fifo_create(&p->output_fifo, (int)sizeof(double));
-  return SOX_SUCCESS;
+  return sox_dft_filter_effect_fn()->start(effp);
 }
 
-static void filter(priv_t * p)
-{
-  int i, num_in = max(0, fifo_occupancy(&p->input_fifo));
-  filter_t const * f = p->filter_ptr;
-  int const overlap = f->num_taps - 1;
-  double * output;
-
-  while (num_in >= f->dft_length) {
-    double const * input = fifo_read_ptr(&p->input_fifo);
-    fifo_read(&p->input_fifo, f->dft_length - overlap, NULL);
-    num_in -= f->dft_length - overlap;
-
-    output = fifo_reserve(&p->output_fifo, f->dft_length);
-    fifo_trim_by(&p->output_fifo, overlap);
-    memcpy(output, input, f->dft_length * sizeof(*output));
-
-    lsx_rdft(f->dft_length, 1, output, lsx_fft_br, lsx_fft_sc);
-    output[0] *= f->coefs[0];
-    output[1] *= f->coefs[1];
-    for (i = 2; i < f->dft_length; i += 2) {
-      double tmp = output[i];
-      output[i  ] = f->coefs[i  ] * tmp - f->coefs[i+1] * output[i+1];
-      output[i+1] = f->coefs[i+1] * tmp + f->coefs[i  ] * output[i+1];
-    }
-    lsx_rdft(f->dft_length, -1, output, lsx_fft_br, lsx_fft_sc);
-  }
-}
-
-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 i, odone = min(*osamp, (size_t)fifo_occupancy(&p->output_fifo));
-  double const * s = fifo_read(&p->output_fifo, (int)odone, NULL);
-  SOX_SAMPLE_LOCALS;
-
-  for (i = 0; i < odone; ++i)
-    *obuf++ = SOX_FLOAT_64BIT_TO_SAMPLE(*s++, effp->clips);
-  p->samples_out += odone;
-
-  if (*isamp && odone < *osamp) {
-    double * t = fifo_write(&p->input_fifo, (int)*isamp, NULL);
-    p->samples_in += (int)*isamp;
-
-    for (i = *isamp; i; --i)
-      *t++ = SOX_SAMPLE_TO_FLOAT_64BIT(*ibuf++, effp->clips);
-    filter(p);
-  }
-  else *isamp = 0;
-  *osamp = odone;
-  return SOX_SUCCESS;
-}
-
-static int drain(sox_effect_t * effp, sox_sample_t * obuf, size_t * osamp)
-{
-  priv_t * p = (priv_t *)effp->priv;
-  static size_t isamp = 0;
-  size_t samples_out = p->samples_in;
-  size_t remaining = samples_out - p->samples_out;
-  double * buff = lsx_calloc(1024, sizeof(*buff));
-
-  if ((int)remaining > 0) {
-    while ((size_t)fifo_occupancy(&p->output_fifo) < remaining) {
-      fifo_write(&p->input_fifo, 1024, buff);
-      p->samples_in += 1024;
-      filter(p);
-    }
-    fifo_trim_to(&p->output_fifo, (int)remaining);
-    p->samples_in = 0;
-  }
-  free(buff);
-  return flow(effp, 0, obuf, &isamp, osamp);
-}
-
-static int stop(sox_effect_t * effp)
-{
-  priv_t * p = (priv_t *) effp->priv;
-
-  fifo_delete(&p->input_fifo);
-  fifo_delete(&p->output_fifo);
-  free(p->filter_ptr->coefs);
-  memset(p->filter_ptr, 0, sizeof(*p->filter_ptr));
-  return SOX_SUCCESS;
-}
-
 sox_effect_handler_t const * sox_loudness_effect_fn(void)
 {
-  static sox_effect_handler_t handler = {
-    "loudness", "[gain [ref]]", 0,
-    create, start, flow, drain, stop, NULL, sizeof(priv_t)
-  };
+  static sox_effect_handler_t handler;
+  handler = *sox_dft_filter_effect_fn();
+  handler.name = "loudness";
+  handler.usage = "[gain [ref]]";
+  handler.flags &= ~SOX_EFF_DEPRECATED;
+  handler.getopts = create;
+  handler.start = start;
+  handler.priv_size = sizeof(priv_t);
   return &handler;
 }
--- /dev/null
+++ b/src/lowfir.c
@@ -1,0 +1,78 @@
+/* Effect: lowfir filter     Copyright (c) 2008 robs@users.sourceforge.net
+ *
+ * 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"
+#include "dft_filter.h"
+#include <string.h>
+
+typedef struct {
+  dft_filter_priv_t base;
+  double Fp, Fc, Fn, att, phase;
+  int allow_aliasing, num_taps, k;
+} priv_t;
+
+static int create(sox_effect_t * effp, int argc, char **argv)
+{
+  priv_t * p = (priv_t *)effp->priv;
+  dft_filter_priv_t * b = &p->base;
+  dft_filter_filter_t * f = &b->filter;
+  double * h;
+  int i;
+  b->filter_ptr = &b->filter;
+  do {                    /* break-able block */
+    NUMERIC_PARAMETER(Fp, 0, 100);
+    NUMERIC_PARAMETER(Fc, 0, 100);
+    NUMERIC_PARAMETER(Fn, 0, 100);
+    NUMERIC_PARAMETER(allow_aliasing, 0, 1);
+    NUMERIC_PARAMETER(att, 80, 200);
+    NUMERIC_PARAMETER(num_taps, 0, 65536);
+    NUMERIC_PARAMETER(k, 0, 512);
+    NUMERIC_PARAMETER(phase, 0, 100);
+  } while (0);
+
+  if (p->phase != 0 && p->phase != 50 && p->phase != 100)
+    p->att *= 34./33; /* negate degradation with intermediate phase */
+  h = lsx_design_lpf(
+      p->Fp, p->Fc, p->Fn, p->allow_aliasing, p->att, &p->num_taps, p->k);
+  f->num_taps = p->num_taps;
+
+  if (p->phase != 50)
+    lsx_fir_to_phase(&h, &f->num_taps, &f->post_peak, p->phase);
+  else f->post_peak = f->num_taps / 2;
+  lsx_debug("%i %i %g%%",
+      f->num_taps, f->post_peak, 100 - 100. * f->post_peak / (f->num_taps - 1));
+
+  f->dft_length = lsx_set_dft_length(f->num_taps);
+  f->coefs = lsx_calloc(f->dft_length, sizeof(*f->coefs));
+  for (i = 0; i < f->num_taps; ++i)
+    f->coefs[(i + f->dft_length - f->num_taps + 1) & (f->dft_length - 1)] = h[i] / f->dft_length * 2;
+  free(h);
+  lsx_safe_rdft(f->dft_length, 1, f->coefs);
+  return argc? lsx_usage(effp) : SOX_SUCCESS;
+}
+
+sox_effect_handler_t const * sox_lowfir_effect_fn(void)
+{
+  static sox_effect_handler_t handler;
+  handler = *sox_dft_filter_effect_fn();
+  handler.name = "lowfir";
+  handler.usage = "[options]";
+  handler.flags &= ~SOX_EFF_DEPRECATED;
+  handler.getopts = create;
+  handler.priv_size = sizeof(priv_t);
+  return &handler;
+}