shithub: sox

Download patch

ref: d955d5fbed00c32803de4e293cd9b482509fe3c3
parent: 1c697d3f259800ec89e8b314a579d03b8832d31f
author: Ulrich Klauer <ulrich@chirlu.de>
date: Wed Sep 26 22:02:57 EDT 2012

spectrogram: allow sample counts for -d and -S

Interpret sample counts given for spectrogram's -d and -S options
correctly. Previously, they were accepted syntactically (because
lsx_parsesamples() is used for parsing the argument), but always
interpreted according to a sample rate of 100 kHz; i.e., -d 20000s meant
0.2 seconds even when the sample rate was actually 10 kHz.

Not really a bug though, because the possibility to specify samples
wasn't documented.

--- a/ChangeLog
+++ b/ChangeLog
@@ -31,7 +31,7 @@
   o 'Rate' now much faster in many cases.  (robs)
   o Allow sending spectrograms to stdout. (Ulrich Klauer)
   o Allow mixing time and sample-count arguments for the delay
-    effect. (Ulrich Klauer)
+    effect, and for spectrogram -S and -d. (Ulrich Klauer)
 
 Internal improvements:
 
--- a/src/spectrogram.c
+++ b/src/spectrogram.c
@@ -44,12 +44,13 @@
 
 typedef struct {
   /* Parameters */
-  double     pixels_per_sec, duration, start_time,  window_adjust;
+  double     pixels_per_sec, window_adjust;
   int        x_size0, y_size, Y_size, dB_range, gain, spectrum_points, perm;
   sox_bool   monochrome, light_background, high_colour, slack_overlap, no_axes;
   sox_bool   raw, alt_palette, truncate;
   win_type_t win_type;
   char const * out_name, * title, * comment;
+  char const *duration_str, *start_time_str;
   sox_bool   using_stdout; /* output image to stdout */
 
   /* Shared work area */
@@ -93,7 +94,7 @@
 static int getopts(sox_effect_t * effp, int argc, char **argv)
 {
   priv_t * p = (priv_t *)effp->priv;
-  uint64_t duration;
+  uint64_t dummy;
   char const * next;
   int c;
   lsx_getopt_t optstate;
@@ -124,15 +125,15 @@
     case 't': p->title            = optstate.arg; break;
     case 'c': p->comment          = optstate.arg; break;
     case 'o': p->out_name         = optstate.arg; break;
-    case 'S': next = lsx_parsesamples(1e5, optstate.arg, &duration, 't');
-      if (next && !*next) {p->start_time = duration * 1e-5; break;}
+    case 'S': next = lsx_parsesamples(1e5, optstate.arg, &dummy, 't');
+      if (next && !*next) {p->start_time_str = lsx_strdup(optstate.arg); break;}
       return lsx_usage(effp);
-    case 'd': next = lsx_parsesamples(1e5, optstate.arg, &duration, 't');
-      if (next && !*next) {p->duration = duration * 1e-5; break;}
+    case 'd': next = lsx_parsesamples(1e5, optstate.arg, &dummy, 't');
+      if (next && !*next) {p->duration_str = lsx_strdup(optstate.arg); break;}
       return lsx_usage(effp);
     default: lsx_fail("invalid option `-%c'", optstate.opt); return lsx_usage(effp);
   }
-  if (!!p->x_size0 + !!p->pixels_per_sec + !!p->duration > 2) {
+  if (!!p->x_size0 + !!p->pixels_per_sec + !!p->duration_str > 2) {
     lsx_fail("only two of -x, -X, -d may be given");
     return SOX_EOF;
   }
@@ -202,11 +203,22 @@
 static int start(sox_effect_t * effp)
 {
   priv_t * p = (priv_t *)effp->priv;
-  double actual, duration = p->duration, pixels_per_sec = p->pixels_per_sec;
+  double actual, duration = 0.0, start_time = 0.0,
+         pixels_per_sec = p->pixels_per_sec;
+  uint64_t d;
 
   memset(&p->WORK, 0, sizeof(*p) - field_offset(priv_t, WORK));
-  
-  p->skip = p->start_time * effp->in_signal.rate + .5;
+
+  if (p->duration_str) {
+    lsx_parsesamples(effp->in_signal.rate, p->duration_str, &d, 't');
+    duration = d / effp->in_signal.rate;
+  }
+  if (p->start_time_str) {
+    lsx_parsesamples(effp->in_signal.rate, p->start_time_str, &d, 't');
+    start_time = d / effp->in_signal.rate;
+    p->skip = d;
+  }
+
   p->x_size = p->x_size0;
   while (sox_true) {
     if (!pixels_per_sec && p->x_size && duration)
@@ -215,7 +227,7 @@
       p->x_size = min(5000, (int)(pixels_per_sec * duration + .5));
     if (!duration && effp->in_signal.length) {
       duration = effp->in_signal.length / (effp->in_signal.rate * effp->in_signal.channels);
-      duration -= p->start_time;
+      duration -= start_time;
       if (duration <= 0)
         duration = 1;
       continue;