shithub: sox

Download patch

ref: 444f41c6fcdf4142c6bca1c6c76df2e4603a24a8
parent: 65f0f47558b878892b5e2b8b77bc3c4f958abbe0
author: robs <robs>
date: Sun Apr 29 13:21:04 EDT 2007

Added gnuplot plotting

--- a/AUTHORS
+++ b/AUTHORS
@@ -92,7 +92,8 @@
                 Formats: M3U, PLS, FLAC, AMR-WB, 24bit support for popular
                 formats.
 		Effects: pad, bass, treble, new flanger, soft-knee companding,
-                speed via resampling, filters makeover inc. octave plots.
+                speed via resampling, filters makeover inc. gnuplot & octave
+                plotting.
                 Others: open input files via URL, file merging, play
                 multiple files with mixed format types, play with replay-gain,
                 much manual improvement and expansion, various fixes,
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,10 +22,13 @@
 
   Effects:
 
+  o --octave option changed to --plot; can now also use gnuplot to
+    plot effect transfer function.  (robs)
   o Added soft-knee companding.  (robs)
-  o Show (with --octave) compand transfer function.  (robs)
+  o Show (with --plot) compand transfer function.  (robs)
   o Allow e.g. "vol 6dB" (as well as "vol 6 dB").  (robs)
-  o Changed deemph to be a true biquad for better accuracy.  (robs)
+  o Changed deemph filter from 1st order to 2nd order for
+    better accuracy.  (robs)
   o Add option to silence effect to leave periods of silence
     in and only strip out extra silence.   (Mark Schreiber)
 
--- a/sox.1
+++ b/sox.1
@@ -480,15 +480,19 @@
 See \fBInput File Combining\fR above for a description of the different
 combining methods.
 .TP
-\fB\-\-octave\fR
-Run in a mode that can be used, in conjunction with the GNU
-Octave program, to assist with the selection and configuration
-of many of the filtering effects.  For the first given effect
-that supports the \fB\-\-octave\fR option, SoX will output Octave
-commands to plot the effect's transfer function, and then exit
-without actually processing any audio.  E.g.
+\fB\-\-plot gnuplot\fR\^|\^\fBoctave\fR\^|\^\fBoff\fR
+If not set to
+.B off
+(the default if
+.B \-\-plot
+is not given), run in a mode that can be used, in conjunction with the
+gnuplot program or the GNU Octave program, to assist with the selection
+and configuration of many of the transfer-function based effects.
+For the first given effect that supports the selected plotting program,
+SoX will output commands to plot the effect's transfer function, and
+then exit without actually processing any audio.  E.g.
 .EX
-	sox --octave input-file -n highpass 1320 > plot.m
+	sox --plot octave input-file -n highpass 1320 > plot.m
 	octave plot.m
 .EE
 .TP
@@ -495,16 +499,8 @@
 \fB\-q\fR, \fB\-\-no\-show\-progress\fR
 Run in quiet mode when SoX wouldn't otherwise do so;
 this is the opposite of the \fB\-S\fR option.
-.PP
-\fB\-\-replay\-gain track\fR
-.br
-\fB\-\-replay\-gain album\fR
-.br
-\fB\-\-replay\-gain off\fR
-.if t .sp -.5
-.if n .sp -1
 .TP
-\ 
+\fB\-\-replay\-gain track\fR\^|\^\fBalbum\fR\^|\^\fBoff\fR
 Select whether or not to apply replay-gain adjustment to input files.
 The default is
 .B track
@@ -1245,7 +1241,7 @@
 audio's frequency to phase relationship without changing its frequency
 to amplitude relationship.  The filter is described in detail in [1].
 .SP
-This effect supports the \fB\-\-octave\fR global option.
+This effect supports the \fB\-\-plot\fR global option.
 .TP
 \fBband\fR [\fB\-n\fR] \fIcenter\fR [width\fR[\fBh\fR\^|\^\fBo\fR\^|\^\fBq\fR]]
 Apply a band-pass filter.
@@ -1281,7 +1277,7 @@
 .I center
 frequency and settling around it.
 .SP
-This effect supports the \fB\-\-octave\fR global option.
+This effect supports the \fB\-\-plot\fR global option.
 .SP
 See also \fBfilter\fR for a bandpass filter with steeper shoulders.
 .TP
@@ -1299,7 +1295,7 @@
 The filters roll off at 6dB per octave (20dB per decade)
 and are described in detail in [1].
 .SP
-These effects support the \fB\-\-octave\fR global option.
+These effects support the \fB\-\-plot\fR global option.
 .SP
 See also \fBfilter\fR for a bandpass filter with steeper shoulders.
 .TP
@@ -1342,7 +1338,7 @@
 .SP
 The filters are described in detail in [1].
 .SP
-These effects support the \fB\-\-octave\fR global option.
+These effects support the \fB\-\-plot\fR global option.
 .SP
 See also \fBequalizer\fR for a peaking equalisation effect.
 .TP
@@ -1391,7 +1387,7 @@
 allows the compander to effectively operate in a `predictive' rather than a
 reactive mode.
 .SP
-This effect supports the \fB\-\-octave\fR global option (for the transfer function).
+This effect supports the \fB\-\-plot\fR global option (for the transfer function).
 .SP
 See also
 .B mcompand
@@ -1417,7 +1413,7 @@
 recordings is rectified.  The filter is defined in the
 standard document ISO 908.
 .SP
-This effect supports the \fB\-\-octave\fR global option.
+This effect supports the \fB\-\-plot\fR global option.
 .SP
 See also the \fBbass\fR and \fBtreble\fR shelving equalisation effects.
 .TP
@@ -1481,7 +1477,7 @@
 .SP
 The filter is described in detail in [1].
 .SP
-This effect supports the \fB\-\-octave\fR global option.
+This effect supports the \fB\-\-plot\fR global option.
 .SP
 See also \fBbass\fR and \fBtreble\fR for shelving equalisation effects.
 .TP
@@ -1575,7 +1571,7 @@
 roll off at 6dB per pole per octave (20dB per pole per decade).  The
 double-pole filters are described in detail in [1].
 .SP
-These effects support the \fB\-\-octave\fR global option.
+These effects support the \fB\-\-plot\fR global option.
 .SP
 See also \fBfilter\fR for filters with a steeper roll-off.
 .TP
@@ -2296,8 +2292,10 @@
 Please report any bugs found in this version of SoX to the mailing list
 (sox-users@lists.sourceforge.net).
 .SH SEE ALSO
-.BR soxexam (7),
+.BR gnuplot (1),
 .BR libsox (3),
+.BR octave (1),
+.BR soxexam (7),
 .BR wget (1)
 .SP
 The SoX web page at http://sox.sourceforge.net
--- a/src/biquad.c
+++ b/src/biquad.c
@@ -66,8 +66,9 @@
   p->a2 = p->a2/p->a0;
   p->a1 = p->a1/p->a0;
 
-  if (effp->globalinfo->octave_plot_effect) {
+  if (effp->globalinfo->plot == sox_plot_octave) {
     printf(
+      "%% GNU Octave file (may also work with MATLAB(R) )\n"
       "title('SoX effect: %s gain=%g frequency=%g %s=%g (rate=%u)')\n"
       "xlabel('Frequency (Hz)')\n"
       "ylabel('Amplitude Response (dB)')\n"
@@ -76,8 +77,30 @@
       "sweepF=logspace(log10(minF),log10(maxF),200);\n"
       "grid on\n"
       "[h,w]=freqz([%g %g %g],[1 %g %g],sweepF,Fs);\n"
-      "semilogx(w,20*log10(h),'b')\n"
+      "semilogx(w,20*log10(h))\n"
+      "disp('Hit return to continue')\n"
       "pause\n"
+      , effp->name, p->gain, p->fc, width_str[p->width_type], p->width
+      , effp->ininfo.rate, effp->ininfo.rate
+      , p->b0, p->b1, p->b2, p->a1, p->a2
+      );
+    return SOX_EOF;
+  }
+  if (effp->globalinfo->plot == sox_plot_gnuplot) {
+    printf(
+      "# gnuplot file\n"
+      "set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%u)'\n"
+      "set xlabel 'Frequency (Hz)'\n"
+      "set ylabel 'Amplitude Response (dB)'\n"
+      "Fs=%u.\n"
+      "b0=%g; b1=%g; b2=%g; a1=%g; a2=%g\n"
+      "o=2*pi/Fs\n"
+      "H(f)=sqrt((b0*b0+b1*b1+b2*b2+2.*(b0*b1+b1*b2)*cos(f*o)+2.*(b0*b2)*cos(2.*f*o))/(1.+a1*a1+a2*a2+2.*(a1+a1*a2)*cos(f*o)+2.*a2*cos(2.*f*o)))\n"
+      "set logscale x\n"
+      "set grid xtics ytics\n"
+      "set key off\n"
+      "plot [f=10:Fs/2] [-35:25] 20*log10(H(f))\n"
+      "pause -1 'Hit return to continue'\n"
       , effp->name, p->gain, p->fc, width_str[p->width_type], p->width
       , effp->ininfo.rate, effp->ininfo.rate
       , p->b0, p->b1, p->b2, p->a1, p->a2
--- a/src/compand.c
+++ b/src/compand.c
@@ -137,7 +137,7 @@
   for (i = 0; i < l->expectedChannels; ++i)
     sox_debug("Channel %i: attack = %g decay = %g", i,
         l->channels[i].attack_times[0], l->channels[i].attack_times[1]);
-  if (!sox_compandt_show(&l->transfer_fn, effp->globalinfo->octave_plot_effect))
+  if (!sox_compandt_show(&l->transfer_fn, effp->globalinfo->plot))
     return SOX_EOF;
 
   /* Convert attack and decay rates using number of samples */
--- a/src/compandt.c
+++ b/src/compandt.c
@@ -21,7 +21,7 @@
 
 #define LOG_TO_LOG10(x) ((x) * 20 / log(10.))
 
-sox_bool sox_compandt_show(sox_compandt_t * t, sox_bool plot)
+sox_bool sox_compandt_show(sox_compandt_t * t, sox_plot_t plot)
 {
   int i;
 
@@ -32,27 +32,47 @@
        LOG_TO_LOG10(t->segments[i].a),
        LOG_TO_LOG10(t->segments[i].b));
 
-  if (!plot)
-    return sox_true;
-  printf(
-    "title('SoX effect: compand')\n"
-    "xlabel('Input level (dB)')\n"
-    "ylabel('Output level (dB)')\n"
-    "%%axis([-100 0 -100 0])\n"
-    "in=linspace(-99.5,0,200);\n"
-    "grid on\n"
-    "out=[");
-  for (i = -199; i <= 0; ++i) {
-    double in = i/2.;
-    double in_lin = pow(10., in/20);
-    printf("%g ", in + 20 * log10(sox_compandt(t, in_lin)));
+  if (plot == sox_plot_octave) {
+    printf(
+      "%% GNU Octave file (may also work with MATLAB(R) )\n"
+      "title('SoX effect: compand')\n"
+      "xlabel('Input level (dB)')\n"
+      "ylabel('Output level (dB)')\n"
+      "in=linspace(-99.5,0,200);\n"
+      "grid on\n"
+      "out=[");
+    for (i = -199; i <= 0; ++i) {
+      double in = i/2.;
+      double in_lin = pow(10., in/20);
+      printf("%g ", in + 20 * log10(sox_compandt(t, in_lin)));
+    }
+    printf(
+      "];\n"
+      "%%plot(in,out) %% hmm.. doesn't work :(\n"
+      "semilogx(exp(in),out)\n"
+      "pause\n");
+    return sox_false;
   }
-  printf(
-    "];\n"
-    "%%plot(in,out,'b') %% hmm.. doesn't work :(\n"
-    "semilogx(exp(in),out,'b')\n"
-    "pause\n");
-  return sox_false;
+  if (plot == sox_plot_gnuplot) {
+    printf(
+      "# gnuplot file\n"
+      "set title 'SoX effect: compand'\n"
+      "set xlabel 'Input level (dB)'\n"
+      "set ylabel 'Output level (dB)'\n"
+      "set grid xtics ytics\n"
+      "set key off\n"
+      "plot '-' with lines\n");
+    for (i = -199; i <= 0; ++i) {
+      double in = i/2.;
+      double in_lin = pow(10., in/20);
+      printf("%g %g\n", in, in + 20 * log10(sox_compandt(t, in_lin)));
+    }
+    printf(
+      "e\n"
+      "pause -1 'Hit return to continue'\n");
+    return sox_false;
+  }
+  return sox_true;
 }
 
 static void prepare_transfer_fn(sox_compandt_t * t)
--- a/src/compandt.h
+++ b/src/compandt.h
@@ -31,7 +31,7 @@
 } sox_compandt_t;
 
 sox_bool sox_compandt_parse(sox_compandt_t * t, char * points, char * gain);
-sox_bool sox_compandt_show(sox_compandt_t * t, sox_bool plot);
+sox_bool sox_compandt_show(sox_compandt_t * t, sox_plot_t plot);
 void    sox_compandt_kill(sox_compandt_t * p);
 
 /* Place in header to allow in-lining */
--- a/src/sox.c
+++ b/src/sox.c
@@ -662,7 +662,7 @@
     {"endian"          , required_argument, NULL, 0},
     {"interactive"     ,       no_argument, NULL, 0},
     {"help-effect"     , required_argument, NULL, 0},
-    {"octave"          ,       no_argument, NULL, 0},
+    {"plot"            , required_argument, NULL, 0},
     {"replay-gain"     , required_argument, NULL, 0},
     {"version"         ,       no_argument, NULL, 0},
 
@@ -700,6 +700,12 @@
   ENUM_ITEM(ENDIAN_,swap)
   {0, 0}};
 
+static enum_item const plot_methods[] = {
+  ENUM_ITEM(sox_plot_,off)
+  ENUM_ITEM(sox_plot_,octave)
+  ENUM_ITEM(sox_plot_,gnuplot)
+  {0, 0}};
+
 static int enum_option(int option_index, enum_item const * items)
 {
   enum_item const * p = find_enum_text(optarg, items);
@@ -797,7 +803,7 @@
         break;
 
       case 7:
-        globalinfo.octave_plot_effect = sox_true;
+        globalinfo.plot = enum_option(option_index, plot_methods);
         break;
 
       case 8:
--- a/src/sox.h
+++ b/src/sox.h
@@ -185,12 +185,14 @@
   SOX_ENCODINGS            /* End of list marker */
 } sox_encoding_t;
 
-/* Global parameters */
+typedef enum {sox_plot_off, sox_plot_octave, sox_plot_gnuplot} sox_plot_t;
 
+/* Global parameters (for effects) */
+
 typedef struct  sox_globalinfo
 {
-    sox_bool octave_plot_effect;/* To help user choose effect & options */
-    double speed;         /* Gather up all speed changes here, then resample */
+  sox_plot_t plot;         /* To help the user choose effect & options */
+  double speed;            /* Gather up all speed changes here, then resample */
 } sox_globalinfo_t;
 
 typedef enum {SOX_OPTION_NO, SOX_OPTION_YES, SOX_OPTION_DEFAULT} sox_option_t;