shithub: sox

Download patch

ref: 5d6d8c3f66bb6aad2da4529879a8effbc2fe9efa
parent: 9086beebe4f86ea753d71d27216ea25f2b5fde58
author: robs <robs>
date: Sun Jan 21 04:02:42 EST 2007

filter consolidation

--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,7 @@
 	  voc.c vorbis.c vox.c wav.c wav.h wve.c xa.c
 
 effects = avg.c band.h biquad.c biquad.h biquads.c chorus.c compand.c dcshift.c\
-	  deemphas.c earwax.c echo.c echos.c fade.c FFT.c FFT.h filter.c \
+	  deemph.h earwax.c echo.c echos.c fade.c FFT.c FFT.h filter.c \
 	  flanger.c luaeff.c luaform.c lintlib.c mask.c mcompand.c noiseprof.c \
 	  noisered.c noisered.h pad.c pan.c phaser.c pitch.c polyphas.c \
 	  rabbit.c rate.c repeat.c resample.c reverb.c reverse.c silence.c \
--- a/src/biquad.h
+++ b/src/biquad.h
@@ -37,7 +37,8 @@
   filter_BPF_SPK, 
   filter_BPF_SPK_N,
   filter_AP1,
-  filter_AP2
+  filter_AP2,
+  filter_deemph
 } filter_t;
 
 
--- a/src/biquads.c
+++ b/src/biquads.c
@@ -129,6 +129,11 @@
 }
 
 
+static int deemph_getopts(eff_t effp, int n, char **argv) {
+  return st_biquad_getopts(effp, n, argv, 0, 0, 0, 1, 2, "", filter_deemph);
+}
+
+
 static int start(eff_t effp)
 {
   biquad_t p = (biquad_t) effp->priv;
@@ -284,6 +289,11 @@
       p->a1 = -2 * cos(w0);
       p->a2 = 1 - sin(w0);
       break;
+
+    case filter_deemph: {
+      #include "deemph.h" /* Has own documentation */
+      break;
+    }
   }
   return st_biquad_start(effp);
 }
@@ -300,3 +310,4 @@
 BIQUAD_EFFECT(treble,    tone,     "gain [frequency [width[s|h|q|o]]]")
 BIQUAD_EFFECT(equalizer, equalizer,"frequency width[q|o|h] gain")
 BIQUAD_EFFECT(band,      band,     "[-n] center [width[h|q|o]]")
+BIQUAD_EFFECT(deemph,    deemph,   "takes no options")
--- /dev/null
+++ b/src/deemph.h
@@ -1,0 +1,109 @@
+/*
+ * July 5, 1991
+ *
+ * Deemphases Filter
+ *
+ * Fixed deemphasis filter for processing pre-emphasized audio cd samples
+ * 09/02/98 (c) Heiko Eissfeldt
+ * License: LGPL (Lesser Gnu Public License)
+ *
+ * This implements the inverse filter of the optional pre-emphasis stage as
+ * defined by ISO 908 (describing the audio cd format).
+ *
+ * Background:
+ * In the early days of audio cds, there were recording problems
+ * with noise (for example in classical recordings). The high dynamics
+ * of audio cds exposed these recording errors a lot.
+ *
+ * The commonly used solution at that time was to 'pre-emphasize' the
+ * trebles to have a better signal-noise-ratio. That is trebles were
+ * amplified before recording, so that they would give a stronger
+ * signal compared to the underlying (tape)noise.
+ *
+ * For that purpose the audio signal was prefiltered with the following
+ * frequency response (simple first order filter):
+ *
+ * V (in dB)
+ * ^
+ * |
+ * |                         _________________
+ * |                        /
+ * |                       / |
+ * |     20 dB / decade ->/  |
+ * |                     /   |
+ * |____________________/_ _ |_ _ _ _ _ _ _ _ _ _ _ _ _ lg f
+ * |0 dB                |    |
+ * |                    |    |
+ * |                    |    |
+ *                 3.1KHz    ca. 10KHz
+ *
+ * So the recorded audio signal has amplified trebles compared to the
+ * original.
+ * HiFi cd players do correct this by applying an inverse filter
+ * automatically, the cd-rom drives or cd burners used by digital
+ * sampling programs (like cdda2wav) however do not.
+ *
+ * So, this is what this effect does.
+ *
+ * Here is the gnuplot file for the frequency response
+   of the deemphasis. The error is below +-0.1dB
+
+-------- Start of gnuplot file ---------------------
+# first define the ideal filter. We use the tenfold sampling frequency.
+T=1./441000.
+OmegaU=1./15E-6
+OmegaL=15./50.*OmegaU
+V0=OmegaL/OmegaU
+H0=V0-1.
+B=V0*tan(OmegaU*T/2.)
+# the coefficients follow
+a1=(B - 1.)/(B + 1.)
+b0=(1.0 + (1.0 - a1) * H0/2.)
+b1=(a1 + (a1 - 1.0) * H0/2.)
+# helper variables
+D=b1/b0
+o=2*pi*T
+H2(f)=b0*sqrt((1+2*cos(f*o)*D+D*D)/(1+2*cos(f*o)*a1+a1*a1))
+#
+# now approximate the ideal curve with a fitted one for sampling
+frequency
+# of 44100 Hz. Fitting parameters are
+# amplification at high frequencies V02
+# and tau of the upper edge frequency OmegaU2 = 2 *pi * f(upper)
+T2=1./44100.
+V02=0.3365
+OmegaU2=1./19E-6
+B2=V02*tan(OmegaU2*T2/2.)
+# the coefficients follow
+a12=(B2 - 1.)/(B2 + 1.)
+b02=(1.0 + (1.0 - a12) * (V02-1.)/2.)
+b12=(a12 + (a12 - 1.0) * (V02-1.)/2.)
+# helper variables
+D2=b12/b02
+o2=2*pi*T2
+H(f)=b02*sqrt((1+2*cos(f*o2)*D2+D2*D2)/(1+2*cos(f*o2)*a12+a12*a12))
+# plot best, real, ideal, level with halved attenuation,
+#      level at full attentuation, 10fold magnified error
+set logscale x
+set grid xtics ytics mxtics mytics
+plot [f=1000:20000] [-12:2] 20*log10(H(f)),20*log10(H2(f)),
+20*log10(OmegaL/(2*
+pi*f)), 0.5*20*log10(V0), 20*log10(V0), 200*log10(H(f)/H2(f))
+pause -1 "Hit return to continue"
+-------- End of gnuplot file ---------------------
+*/
+
+
+/* filter coefficients */
+p->a1 = -0.62786881719628784282;
+p->b0 =  0.45995451989513153057;
+p->b1 = -0.08782333709141937339;
+
+
+/* The sample-rate must be 44100 as this has been harded coded into the
+ * pre-calculated filter coefficients.
+ */
+if (effp->ininfo.rate != 44100) {
+  st_fail("Sample rate must be 44100 (audio-CD)");
+  return ST_EOF;
+}
--- a/src/deemphas.c
+++ /dev/null
@@ -1,210 +1,0 @@
-/*
- * July 5, 1991
- *
- * Deemphases Filter
- *
- * Fixed deemphasis filter for processing pre-emphasized audio cd samples
- * 09/02/98 (c) Heiko Eissfeldt
- * License: LGPL (Lesser Gnu Public License)
- *
- * This implements the inverse filter of the optional pre-emphasis stage as
- * defined by ISO 908 (describing the audio cd format).
- *
- * Background:
- * In the early days of audio cds, there were recording problems
- * with noise (for example in classical recordings). The high dynamics
- * of audio cds exposed these recording errors a lot.
- *
- * The commonly used solution at that time was to 'pre-emphasize' the
- * trebles to have a better signal-noise-ratio. That is trebles were
- * amplified before recording, so that they would give a stronger
- * signal compared to the underlying (tape)noise.
- *
- * For that purpose the audio signal was prefiltered with the following
- * frequency response (simple first order filter):
- *
- * V (in dB)
- * ^
- * |
- * |                         _________________
- * |                        /
- * |                       / |
- * |     20 dB / decade ->/  |
- * |                     /   |
- * |____________________/_ _ |_ _ _ _ _ _ _ _ _ _ _ _ _ lg f
- * |0 dB                |    |
- * |                    |    |
- * |                    |    |
- *                 3.1KHz    ca. 10KHz
- *
- * So the recorded audio signal has amplified trebles compared to the
- * original.
- * HiFi cd players do correct this by applying an inverse filter
- * automatically, the cd-rom drives or cd burners used by digital
- * sampling programs (like cdda2wav) however do not.
- *
- * So, this is what this effect does.
- *
- * Here is the gnuplot file for the frequency response
-   of the deemphasis. The error is below +-0.1dB
-
--------- Start of gnuplot file ---------------------
-# first define the ideal filter. We use the tenfold sampling frequency.
-T=1./441000.
-OmegaU=1./15E-6
-OmegaL=15./50.*OmegaU
-V0=OmegaL/OmegaU
-H0=V0-1.
-B=V0*tan(OmegaU*T/2.)
-# the coefficients follow
-a1=(B - 1.)/(B + 1.)
-b0=(1.0 + (1.0 - a1) * H0/2.)
-b1=(a1 + (a1 - 1.0) * H0/2.)
-# helper variables
-D=b1/b0
-o=2*pi*T
-H2(f)=b0*sqrt((1+2*cos(f*o)*D+D*D)/(1+2*cos(f*o)*a1+a1*a1))
-#
-# now approximate the ideal curve with a fitted one for sampling
-frequency
-# of 44100 Hz. Fitting parameters are
-# amplification at high frequencies V02
-# and tau of the upper edge frequency OmegaU2 = 2 *pi * f(upper)
-T2=1./44100.
-V02=0.3365
-OmegaU2=1./19E-6
-B2=V02*tan(OmegaU2*T2/2.)
-# the coefficients follow
-a12=(B2 - 1.)/(B2 + 1.)
-b02=(1.0 + (1.0 - a12) * (V02-1.)/2.)
-b12=(a12 + (a12 - 1.0) * (V02-1.)/2.)
-# helper variables
-D2=b12/b02
-o2=2*pi*T2
-H(f)=b02*sqrt((1+2*cos(f*o2)*D2+D2*D2)/(1+2*cos(f*o2)*a12+a12*a12))
-# plot best, real, ideal, level with halved attenuation,
-#      level at full attentuation, 10fold magnified error
-set logscale x
-set grid xtics ytics mxtics mytics
-plot [f=1000:20000] [-12:2] 20*log10(H(f)),20*log10(H2(f)),
-20*log10(OmegaL/(2*
-pi*f)), 0.5*20*log10(V0), 20*log10(V0), 200*log10(H(f)/H2(f))
-pause -1 "Hit return to continue"
--------- End of gnuplot file ---------------------
-
- */
-
-/*
- * adapted from Sound Tools skeleton effect file.
- */
-
-#include <math.h>
-#include "st_i.h"
-
-static st_effect_t st_deemph_effect ;
-
-/* Private data for deemph file */
-typedef struct deemphstuff {
-     st_sample_t lastin;
-     double      lastout;
-} *deemph_t;
-
-assert_static(sizeof(struct deemphstuff) <= ST_MAX_EFFECT_PRIVSIZE, 
-    /* else */ deemph_PRIVSIZE_too_big);
-
-/* filter coefficients */
-#define a1      -0.62786881719628784282
-#define b0      0.45995451989513153057
-#define b1      -0.08782333709141937339
-
-/*
- * Prepare processing.
- * Do all initializations.
- */
-static int st_deemph_start(eff_t effp)
-{
-     /* check the input format */
-
-     /* This used to check the input file sample encoding method and size
-      * but these are irrelevant as effects always work with the ST internal
-      * long-integer format regardless of the input format.
-      *   The only parameter that is important for the deemph effect is
-      * sampling rate as this has been harded coded into the pre-calculated
-      * filter coefficients.
-      */
-     if (effp->ininfo.rate != 44100)
-     {
-          st_fail("The deemphasis effect works only with audio-CD-like samples.\nThe input format however has %d Hz sample rate.",
-            effp->ininfo.rate);
-          return (ST_EOF);
-     }
-     else
-     {
-          deemph_t deemph = (deemph_t) effp->priv;
-
-          deemph->lastin = 0;
-          deemph->lastout = 0.0;
-     }
-     if (effp->globalinfo->octave_plot_effect)
-     {
-       printf(
-         "title('SoX effect: %s (rate=%u)')\n"
-         "xlabel('Frequency (Hz)')\n"
-         "ylabel('Amplitude Response (dB)')\n"
-         "Fs=%u;minF=10;maxF=Fs/2;\n"
-         "axis([minF maxF -25 25])\n"
-         "sweepF=logspace(log10(minF),log10(maxF),200);\n"
-         "grid on\n"
-         "[h,w]=freqz([%f %f],[1 %f],sweepF,Fs);\n"
-         "semilogx(w,20*log10(h),'b')\n"
-         "pause\n"
-         , effp->name
-         , effp->ininfo.rate, effp->ininfo.rate
-         , b0, b1, a1
-         );
-       return ST_EOF;
-     }
-     return (ST_SUCCESS);
-}
-
-/*
- * Processed signed long samples from ibuf to obuf.
- * Return number of samples processed.
- */
-
-static int st_deemph_flow(eff_t effp, const st_sample_t *ibuf, st_sample_t *obuf, 
-                   st_size_t *isamp, st_size_t *osamp)
-{
-     deemph_t deemph = (deemph_t) effp->priv;
-     int len, done;
-
-     len = ((*isamp > *osamp) ? *osamp : *isamp);
-     for(done = len; done; done--) {
-          deemph->lastout = *ibuf * b0 +
-                         deemph->lastin * b1 -
-                         deemph->lastout * a1;
-          deemph->lastin = *ibuf++;
-          *obuf++ = deemph->lastout > 0.0 ?
-                    deemph->lastout + 0.5 :
-                    deemph->lastout - 0.5;
-     }
-     *isamp = *osamp = len;
-     return (ST_SUCCESS);
-}
-
-static st_effect_t st_deemph_effect = {
-  "deemph",
-  "Usage: Deemphasis filtering effect takes no options",
-  0,
-  st_effect_nothing_getopts,
-  st_deemph_start,
-  st_deemph_flow,
-  st_effect_nothing_drain,
-  st_effect_nothing,
-  st_effect_nothing
-};
-
-const st_effect_t *st_deemph_effect_fn(void)
-{
-    return &st_deemph_effect;
-}