shithub: sox

Download patch

ref: c35561001da2eccbf68c793c523db2fba1563fce
parent: e8d9e315c9ca2ec268363816a8f718fdb32913ec
author: rrt <rrt>
date: Mon Nov 13 20:52:27 EST 2006

Add equalizer effect from Pascal Giard

--- a/src/Makefile.dos
+++ b/src/Makefile.dos
@@ -19,15 +19,14 @@
 	  raw.obj sf.obj smp.obj sndrtool.obj sphere.obj sunaudio.obj \
 	  tx16w.obj voc.obj vorbis.obj vox.obj wav.obj wve.obj
 
-EOBJ	= avg.obj band.obj bandpass.obj breject.obj btrworth.obj chorus.obj \
+EOBJ	= avg.obj band.obj bandpass.obj biquad.obj breject.obj btrworth.obj chorus.obj \
 	  compand.obj copy.obj dcshift.obj deemphas.obj earwax.o \
-	  echo.obj echos.obj fade.obj FFT.obj filter.obj flanger.obj \
-	  biquad.obj tone.obj \
+	  echo.obj echos.obj equalizer.obj fade.obj FFT.obj filter.obj flanger.obj \
 	  highp.obj highpass.obj lowp.obj lowpass.obj mask.obj mcompand.obj \
 	  noiseprof.obj noisered.obj phaser.obj pitch.obj pan.obj \
 	  polyphase.obj rate.obj repeat.obj resample.obj \
 	  reverb.obj reverse.obj silence.obj speed.obj stat.obj \
-	  stretch.obj swap.obj synth.obj trim.obj vibro.obj vol.obj
+	  stretch.obj swap.obj synth.obj tone.obj trim.obj vibro.obj vol.obj
 
 LIBOBJS   = $(FOBJ) $(EOBJ) handlers.obj misc.obj stio.obj getopt.obj \
 	    getopt1.obj util.obj
--- a/src/Makefile.gcc
+++ b/src/Makefile.gcc
@@ -25,13 +25,12 @@
 	  sndrtool.o sphere.o sunaudio.o tx16w.o voc.o vorbis.o \
 	  vox.o wav.o wve.o
 
-EOBJ    = avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
-	  copy.o dcshift.o deemphas.o earwax.o echo.o echos.o fade.o FFT.o \
-	  biquad.o tone.o \
-	  filter.o flanger.o highp.o highpass.o lowp.o lowpass.o \
+EOBJ    = avg.o band.o bandpass.o biquad.o breject.o btrworth.o chorus.o compand.o \
+	  copy.o dcshift.o deemphas.o earwax.o echo.o echos.o equalizer.o \
+          fade.o FFT.o filter.o flanger.o highp.o highpass.o lowp.o lowpass.o \
 	  mask.o mcompand.o noiseprof.o noisered.o pan.o phaser.o pitch.o \
 	  polyphas.o rate.o repeat.o resample.o reverb.o reverse.o \
-	  silence.o speed.o stat.o stretch.o swap.o synth.o trim.o \
+	  silence.o speed.o stat.o stretch.o swap.o synth.o tone.o trim.o \
 	  vibro.o vol.o
 
 SOUNDLIB = libst.a
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -47,14 +47,13 @@
 	  raw.o sf.o smp.o sndrtool.o sphere.o tx16w.o voc.o vorbis.o \
 	  vox.o wav.o wve.o xa.o
 
-EOBJ	= avg.o band.o bandpass.o breject.o btrworth.o chorus.o compand.o \
-	  copy.o dcshift.o deemphas.o earwax.o echo.o echos.o \
-	  biquad.o tone.o \
-	  fade.o FFT.o filter.o flanger.o highp.o highpass.o lowp.o \
+EOBJ	= avg.o band.o bandpass.o biquad.o breject.o btrworth.o chorus.o \
+	  compand.o copy.o dcshift.o deemphas.o earwax.o echo.o echos.o \
+	  equalizer.o fade.o FFT.o filter.o flanger.o highp.o highpass.o lowp.o \
 	  lowpass.o mask.o mcompand.o noiseprof.o noisered.o pan.o \
 	  phaser.o pitch.o polyphas.o rabbit.o rate.o repeat.o resample.o \
 	  reverb.o reverse.o silence.o speed.o stat.o \
-	  stretch.o swap.o synth.o trim.o vibro.o vol.o
+	  stretch.o swap.o synth.o tone.o trim.o vibro.o vol.o
 
 
 GSMOBJ_0 =
--- /dev/null
+++ b/src/equalizer.c
@@ -1,0 +1,184 @@
+/*
+    Equalizer filter effect file for SoX
+    Copyright (C) 2006 Pascal Giard <evilynux@gmail.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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Code based on the biquad filters described in
+    
+    Cookbook formulae for audio EQ biquad filter coefficients
+    by Robert Bristow-Johnson <rbj@audioimagination.com>
+
+    Theory:
+     y[n] = (a0/b0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2]
+            - (a1/a0)*y[n-1] - (a2/a0)*y[n-2]
+
+     Where:
+       w0 = 2*M_PI*cfreq/srate
+       A = 10^(gain/40)
+       alpha = sin(w0)/( 2*Q )
+
+     For a PeakingEQ filter:
+       b0 =  1 + alpha*A
+       b1 = -2*cos(w0)
+       b2 =  1 - alpha*A
+       a0 =  1 + alpha/A
+       a1 = -2*cos(w0)
+       a2 =  1 - alpha/A
+
+     Reminder:
+       Q = sqrt(2^n)/(2^n - 1) where n is bandwidth in octave
+       n = log2(bw) where bw is bandwidth in Hz
+
+     Transfer function is:
+             (a0/b0) + (b1/a0)z^-1 + (b2/a0)z^-2
+      H(z) = -----------------------------------
+                1 + (a1/a0)z^-1 + (a2/a0)z^-2
+ */
+
+#include <math.h>
+#include "st_i.h"
+
+static st_effect_t st_equalizer_effect;
+
+/* Filter parameters */
+typedef struct filterparams {
+  float rate;  // Sample rate
+  float Q;     // Q-factor
+  float cfreq; // Central frequency (Hz)
+  float gain;  // Gain (dB)
+  double x[3]; // In where x[2] <=> x[ n - 2 ]
+  double y[3]; // Out
+  double b[3]; // From this point, equation constants...
+  double a[3];
+} *equalizer_t;
+
+int st_equalizer_getopts(eff_t effp, int n, char **argv) 
+{
+  equalizer_t eq = (equalizer_t) effp->priv;
+  int i;
+
+  if (n < 3)
+    {
+      st_fail("Usage: equalizer center-freq Q gain");
+      return (ST_EOF);
+    }
+
+  i = 0;
+  sscanf(argv[i++], "%f", &eq->cfreq);
+  sscanf(argv[i++], "%f", &eq->Q);
+  sscanf(argv[i++], "%f", &eq->gain);
+
+  // TODO: Would be nice to validate the params..
+
+  return (ST_SUCCESS);
+}
+
+// Set the filter constants
+int st_equalizer_start(eff_t effp)
+{
+  equalizer_t eq = (equalizer_t) effp->priv;
+  double w0;
+  double amp;
+  double alpha;
+
+  // Sample rate
+  eq->rate = effp->ininfo.rate;
+
+  w0 = 2*M_PI*eq->cfreq/eq->rate;
+  amp = pow( 10, eq->gain/40 );
+  alpha = sin(w0)/( 2*eq->Q );
+
+  st_report("Debug: cfreq: %fHz", eq->cfreq);
+  st_report("Debug: Q: %f", eq->Q);
+  st_report("Debug: gain: %fdB", eq->gain);
+  st_report("Debug: rate: %f", eq->rate);
+  st_report("Debug: w0: %f", w0);
+  st_report("Debug: amp: %f", amp);
+  st_report("Debug: alpha: %f", alpha);
+
+  // Initialisation
+  eq->b[0] =  1 + alpha*amp;
+  eq->b[1] = -2*cos(w0);
+  eq->b[2] =  1 - alpha*amp;
+  eq->a[0] =  1 + alpha/amp;
+  eq->a[1] = -2*cos(w0);
+  eq->a[2] =  1 - alpha/amp;
+
+  eq->x[0] = 0; // x[n]
+  eq->x[1] = 0; // x[n-1]
+  eq->x[2] = 0; // x[n-2]
+  eq->y[0] = 0; // y[n]
+  eq->y[1] = 0; // y[n-1]
+  eq->y[2] = 0; // y[n-2]
+
+  return (ST_SUCCESS);
+}
+
+int st_equalizer_flow(eff_t effp, st_sample_t *ibuf,
+                      st_sample_t *obuf, st_size_t *isamp,
+                      st_size_t *osamp)
+{
+  equalizer_t eq = (equalizer_t) effp->priv;
+  st_size_t len, done;
+  double out;
+
+  len = ((*isamp > *osamp) ? *osamp : *isamp);
+
+  for(done = 0; done < len; done++) {
+    eq->x[2] = eq->x[1];
+    eq->x[1] = eq->x[0];
+    eq->x[0] = *ibuf++;
+      
+    eq->y[2] = eq->y[1];
+    eq->y[1] = eq->y[0];
+    out = (
+           (eq->b[0]/eq->a[0])*eq->x[0] +
+           (eq->b[1]/eq->a[0])*eq->x[1] +
+           (eq->b[2]/eq->a[0])*eq->x[2] -
+           (eq->a[1]/eq->a[0])*eq->y[1] -
+           (eq->a[2]/eq->a[0])*eq->y[2]
+           );
+    eq->y[0] = out;
+
+    if (out < ST_SAMPLE_MIN) {
+      out = ST_SAMPLE_MIN;
+    }
+    else if (out > ST_SAMPLE_MAX) {
+      out = ST_SAMPLE_MAX;
+    }
+
+    *obuf++ = out;
+  }
+
+  *isamp = len;
+  *osamp = len;
+
+  return (ST_SUCCESS);
+}
+
+static st_effect_t st_equalizer_effect = {
+  "equalizer",
+  "Usage: equalizer central-freqency Q gain",
+  0,
+  st_equalizer_getopts, st_equalizer_start,
+  st_equalizer_flow, st_effect_nothing_drain,
+  st_effect_nothing
+};
+
+const st_effect_t *st_equalizer_effect_fn(void)
+{
+    return &st_equalizer_effect;
+}
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -96,6 +96,7 @@
   st_earwax_effect_fn,
   st_echo_effect_fn,
   st_echos_effect_fn,
+  st_equalizer_effect_fn,
   st_fade_effect_fn,
   st_filter_effect_fn,
   st_flanger_effect_fn,
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -246,6 +246,7 @@
 extern const st_effect_t *st_earwax_effect_fn(void);
 extern const st_effect_t *st_echo_effect_fn(void);
 extern const st_effect_t *st_echos_effect_fn(void);
+extern const st_effect_t *st_equalizer_effect_fn(void);
 extern const st_effect_t *st_fade_effect_fn(void);
 extern const st_effect_t *st_filter_effect_fn(void);
 extern const st_effect_t *st_flanger_effect_fn(void);