shithub: sox

Download patch

ref: 2dd8e848393dff0a4be2f4b54e242995f036c7d7
parent: 1338952d0f41fb87ff45d313cdc08fb22f267ea5
author: robs <robs>
date: Sun Jun 17 17:12:01 EDT 2007

Can now run an effects chain with e.g. upsample, filter, downsample, dither.
Cleaned up speed hack so as not to affect resampling effects.

--- a/src/biquad.c
+++ b/src/biquad.c
@@ -67,10 +67,10 @@
   if (effp->global_info->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"
+      "title('SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)')\n"
       "xlabel('Frequency (Hz)')\n"
       "ylabel('Amplitude Response (dB)')\n"
-      "Fs=%u;minF=10;maxF=Fs/2;\n"
+      "Fs=%g;minF=10;maxF=Fs/2;\n"
       "axis([minF maxF -35 25])\n"
       "sweepF=logspace(log10(minF),log10(maxF),200);\n"
       "grid on\n"
@@ -87,10 +87,10 @@
   if (effp->global_info->plot == sox_plot_gnuplot) {
     printf(
       "# gnuplot file\n"
-      "set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%u)'\n"
+      "set title 'SoX effect: %s gain=%g frequency=%g %s=%g (rate=%g)'\n"
       "set xlabel 'Frequency (Hz)'\n"
       "set ylabel 'Amplitude Response (dB)'\n"
-      "Fs=%u.\n"
+      "Fs=%g\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"
--- a/src/echo.c
+++ b/src/echo.c
@@ -141,7 +141,7 @@
                 if ( echo->samples[i] > (sox_ssize_t)DELAY_BUFSIZ )
                 {
                         sox_fail("echo: delay must be less than %g seconds!",
-                                DELAY_BUFSIZ / (float) effp->ininfo.rate );
+                                DELAY_BUFSIZ / effp->ininfo.rate );
                         return (SOX_EOF);
                 }
                 if ( echo->decay[i] < 0.0 )
--- a/src/echos.c
+++ b/src/echos.c
@@ -134,7 +134,7 @@
                 if ( echos->samples[i] > (sox_ssize_t)DELAY_BUFSIZ )
                 {
                         sox_fail("echos: delay must be less than %g seconds!",
-                                DELAY_BUFSIZ / (float) effp->ininfo.rate );
+                                DELAY_BUFSIZ / effp->ininfo.rate );
                         return (SOX_EOF);
                 }
                 if ( echos->decay[i] < 0.0 )
--- a/src/hcom.c
+++ b/src/hcom.c
@@ -244,7 +244,7 @@
 {
         register struct writepriv *p = (struct writepriv *) ft->priv;
 
-        switch (ft->signal.rate) {
+        switch ((int)ft->signal.rate) {
         case 22050:
         case 22050/2:
         case 22050/3:
--- a/src/ladspa.c
+++ b/src/ladspa.c
@@ -198,8 +198,8 @@
   unsigned long i;
 
   /* Instantiate the plugin */
-  sox_debug("rate for plugin is %d", effp->ininfo.rate);
-  l_st->handle = l_st->desc->instantiate(l_st->desc, effp->ininfo.rate);
+  sox_debug("rate for plugin is %g", effp->ininfo.rate);
+  l_st->handle = l_st->desc->instantiate(l_st->desc, (unsigned long)effp->ininfo.rate);
   if (l_st->handle == NULL) {
     sox_fail("could not instantiate plugin");
     return SOX_EOF;
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -351,6 +351,8 @@
     if (effp->ininfo.rate == effp->outinfo.rate)
       return SOX_EFF_NULL;
 
+    effp->outinfo.channels = effp->ininfo.channels;
+
     rate->lcmrate = sox_lcm((sox_ssample_t)effp->ininfo.rate,
                            (sox_ssample_t)effp->outinfo.rate);
 
@@ -359,8 +361,8 @@
      * 16 bits x 16 bits = 32 bits, which we can handle.
      */
 
-    rate->inskip = rate->lcmrate / effp->ininfo.rate;
-    rate->outskip = rate->lcmrate / effp->outinfo.rate;
+    rate->inskip = rate->lcmrate / (sox_ssample_t)effp->ininfo.rate;
+    rate->outskip = rate->lcmrate / (sox_ssample_t)effp->outinfo.rate;
     rate->Factor = (double)rate->inskip / (double)rate->outskip;
     rate->inpipe = 0;
     {
@@ -374,7 +376,7 @@
     rate->total = total;
     /* l1 and l2 are now lists of the up/down factors for conversion */
 
-    sox_debug("Poly:  input rate %d, output rate %d.  %d stages.",
+    sox_debug("Poly:  input rate %g, output rate %g.  %d stages.",
             effp->ininfo.rate, effp->outinfo.rate,total);
     sox_debug("Poly:  window: %s  size: %d  cutoff: %f.",
             (rate->win_type == 0) ? ("nut") : ("ham"), rate->win_width, rate->cutoff);
--- a/src/rabbit.c
+++ b/src/rabbit.c
@@ -28,6 +28,7 @@
 /* Private data for resampling */
 typedef struct {
   int converter_type;           /* SRC converter type */
+  double out_rate;
   SRC_STATE *state;             /* SRC state struct */
   SRC_DATA *data;               /* SRC_DATA control struct */
   sox_size_t i_alloc, o_alloc;  /* Samples allocated in data->data_{in,out} */
@@ -36,35 +37,40 @@
 /*
  * Process options
  */
-static int getopts(sox_effect_t * effp, int n, char **argv)
+static int getopts(sox_effect_t * effp, int argc, char **argv)
 {
   rabbit_t r = (rabbit_t) effp->priv;
+  char dummy;     /* To check for extraneous chars. */
 
   r->converter_type = SRC_SINC_BEST_QUALITY;
 
-  if (n >= 1) {
+  if (argc) {
     if (!strcmp(argv[0], "-c0")) {
       r->converter_type = SRC_SINC_BEST_QUALITY;
-      n--; argv++;
+      argc--; argv++;
     } else if (!strcmp(argv[0], "-c1")) {
       r->converter_type = SRC_SINC_MEDIUM_QUALITY;
-      n--; argv++;
+      argc--; argv++;
     } else if (!strcmp(argv[0], "-c2")) {
       r->converter_type = SRC_SINC_FASTEST;
-      n--; argv++;
+      argc--; argv++;
     } else if (!strcmp(argv[0], "-c3")) {
       r->converter_type = SRC_ZERO_ORDER_HOLD;
-      n--; argv++;
+      argc--; argv++;
     } else if (!strcmp(argv[0], "-c4")) {
       r->converter_type = SRC_LINEAR;
-      n--; argv++;
+      argc--; argv++;
     }
   }
 
-  if (n >= 1)
-    return sox_usage(effp);
+  r->out_rate = HUGE_VAL;
+  if (argc) {
+    if (sscanf(*argv, "%lf %c", &r->out_rate, &dummy) != 1 || r->out_rate <= 0) 
+      return sox_usage(effp);
+    argc--; argv++;
+  }
 
-  return SOX_SUCCESS;
+  return argc? sox_usage(effp) : SOX_SUCCESS;
 }
 
 /*
@@ -74,23 +80,16 @@
 {
   rabbit_t r = (rabbit_t) effp->priv;
   int err = 0;
+  double out_rate = r->out_rate != HUGE_VAL? r->out_rate : effp->outinfo.rate;
 
-  /* The next line makes the "speed" effect accurate; it's needed because
-   * ininfo.rate (sox_rate_t) isn't floating point (but it's probably not worth
-   * changing sox_rate_t just because of this): */
-  double in_rate = floor(effp->ininfo.rate / effp->global_info->speed + .5)
-    * effp->global_info->speed;
-
-  if (in_rate == effp->outinfo.rate)
+  if (effp->ininfo.rate == out_rate)
     return SOX_EFF_NULL;
           
-  if (effp->ininfo.channels != effp->outinfo.channels) {
-    sox_fail("number of Input and Output channels must be equal to use rabbit effect");
-    return SOX_EOF;
-  }
+  effp->outinfo.channels = effp->ininfo.channels;
+  effp->outinfo.rate = out_rate;
 
   r->data = (SRC_DATA *)xcalloc(1, sizeof(SRC_DATA));
-  r->data->src_ratio = (double)effp->outinfo.rate / in_rate;
+  r->data->src_ratio = out_rate / effp->ininfo.rate;
   r->i_alloc = r->o_alloc = 0;
   r->state = src_new(r->converter_type, effp->ininfo.channels, &err);
   if (err) {
@@ -112,34 +111,31 @@
   SRC_DATA *d = r->data;
   unsigned int channels = effp->ininfo.channels;
   sox_size_t i;
+  sox_size_t isamples0 = d->input_frames * channels;
+  sox_size_t isamples = isamples0 + *isamp;
+  sox_size_t osamples = isamples * (d->src_ratio + 0.01) + 8;
 
-  if (isamp && *isamp > 0) {
-    sox_size_t isamples0 = d->input_frames * channels;
-    sox_size_t isamples = isamples0 + *isamp;
-    sox_size_t osamples = isamples * (d->src_ratio + 0.01) + 8;
+  if (osamples > *osamp) {
+    osamples = *osamp;
+    isamples = (osamples - 8) / (d->src_ratio + 0.01);
+  }
 
-    if (osamples > sox_bufsiz) {
-      osamples = sox_bufsiz;
-      isamples = (osamples - 8) / (d->src_ratio + 0.01);
-    }
+  if (r->i_alloc < isamples) {
+    d->data_in = xrealloc(d->data_in, isamples * sizeof(float));
+    r->i_alloc = isamples;
+  }
+  if (r->o_alloc < osamples) {
+    d->data_out = xrealloc(d->data_out, osamples * sizeof(float));
+    r->o_alloc = osamples;
+    d->output_frames = osamples / channels;
+  }
 
-    if (r->i_alloc < isamples) {
-      d->data_in = xrealloc(d->data_in, isamples * sizeof(float));
-      r->i_alloc = isamples;
-    }
-    if (r->o_alloc < osamples) {
-      d->data_out = xrealloc(d->data_out, osamples * sizeof(float));
-      r->o_alloc = osamples;
-      d->output_frames = osamples / channels;
-    }
+  for (i = 0; i < isamples - isamples0; i++)
+    d->data_in[isamples0 + i] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i], effp->clips);
+  *isamp = i;
 
-    for (i = 0; i < isamples - isamples0; i++)
-      d->data_in[isamples0 + i] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i], effp->clips);
+  d->input_frames = isamples / channels;
 
-    *isamp = isamples - isamples0;
-    d->input_frames = isamples / channels;
-  }
-
   *osamp = 0;
   while (d->input_frames > 0 || d->end_of_input != 0) {
     if (src_process(r->state, r->data) != 0) {
@@ -146,22 +142,16 @@
       sox_fail("%s", src_strerror(src_error(r->state)));
       return SOX_EOF;
     }
-    if (d->input_frames_used) {
-      d->input_frames -= d->input_frames_used;
-      if (d->input_frames)
-       memcpy(d->data_in,
-              d->data_in + d->input_frames_used * sizeof(float),
-              d->input_frames * sizeof(float));
-    }
+    d->input_frames -= d->input_frames_used;
+    if (d->input_frames)
+       memmove(d->data_in, d->data_in + d->input_frames_used * sizeof(float),
+           d->input_frames * sizeof(float));
 
-    *osamp = d->output_frames_gen * channels;
-    if (! *osamp)
-      break;
-
     for (i = 0; i < (sox_size_t)d->output_frames_gen * channels; i++)
       obuf[i] = SOX_FLOAT_32BIT_TO_SAMPLE(d->data_out[i], effp->clips);
+    *osamp += i;
 
-    if (d->end_of_input)
+    if (!d->output_frames_gen || d->end_of_input)
       break;
   }
 
@@ -174,8 +164,9 @@
 static int drain(sox_effect_t * effp, sox_ssample_t *obuf, sox_size_t *osamp)
 {
   rabbit_t r = (rabbit_t) effp->priv;
+  static sox_size_t isamp = 0;
   r->data->end_of_input = 1;
-  return flow(effp, NULL, obuf, NULL, osamp);
+  return flow(effp, NULL, obuf, &isamp, osamp);
 }
 
 /*
@@ -193,7 +184,7 @@
 const sox_effect_handler_t *sox_rabbit_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "rabbit", "[-c0|-c1|-c2|-c3|-c4]",
+    "rabbit", "[-c0|-c1|-c2|-c3|-c4] [rate]",
     SOX_EFF_RATE | SOX_EFF_MCHAN,
     getopts, start, flow, drain, stop, NULL
   };
--- a/src/resample.c
+++ b/src/resample.c
@@ -195,16 +195,12 @@
   long Xoff, gcdrate;
   int i;
 
-  /* The next line makes the "speed" effect accurate; it's needed because
-   * ininfo.rate (sox_rate_t) isn't floating point (but it's probably not worth
-   * changing sox_rate_t just because of this): */
-  double in_rate = floor(effp->ininfo.rate / effp->global_info->speed + .5)
-    * effp->global_info->speed;
-
-  if (in_rate == effp->outinfo.rate)
+  if (effp->ininfo.rate == effp->outinfo.rate)
     return SOX_EFF_NULL;
           
-  r->Factor = (double) effp->outinfo.rate / in_rate;
+  effp->outinfo.channels = effp->ininfo.channels;
+
+  r->Factor = effp->outinfo.rate / effp->ininfo.rate;
 
   gcdrate = sox_gcd((long) effp->ininfo.rate, (long) effp->outinfo.rate);
   r->a = effp->ininfo.rate / gcdrate;
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -174,7 +174,7 @@
                 if ( reverb->samples[i] > DELAY_BUFSIZ )
                 {
                         sox_fail("reverb: delay must be less than %g seconds!",
-                                DELAY_BUFSIZ / (float) effp->ininfo.rate );
+                                DELAY_BUFSIZ / effp->ininfo.rate );
                         return(SOX_EOF);
                 }
                 /* Compute a realistic decay */
--- a/src/sox.c
+++ b/src/sox.c
@@ -214,6 +214,7 @@
   f->signal.size = -1;
   f->signal.encoding = SOX_ENCODING_UNKNOWN;
   f->signal.channels = 0;
+  f->signal.rate = 0;
   f->signal.reverse_bytes = SOX_OPTION_DEFAULT;
   f->signal.reverse_nibbles = SOX_OPTION_DEFAULT;
   f->signal.reverse_bits = SOX_OPTION_DEFAULT;
@@ -836,11 +837,10 @@
       break;
 
     case 'r':
-      if (sscanf(optarg, "%i %c", &i, &dummy) != 1 || i <= 0) {
-        sox_fail("Rate value `%s' is not a positive integer", optarg);
+      if (sscanf(optarg, "%lf %c", &f->signal.rate, &dummy) != 1 || f->signal.rate <= 0) {
+        sox_fail("Rate value `%s' is not a positive number", optarg);
         exit(1);
       }
-      f->signal.rate = i;
       break;
 
     case 'v':
@@ -950,7 +950,7 @@
 
   fprintf(stderr,
     "Channels       : %u\n"
-    "Sample Rate    : %u\n",
+    "Sample Rate    : %g\n",
     f->ft->signal.channels,
     f->ft->signal.rate);
 
@@ -1244,7 +1244,7 @@
 
   for (i = 0; i < sox_neffects; ++i) {
     sox_effect_t * effp = &sox_effects[i][0];
-    sox_report("effects chain: %-10s %uHz %u channels %u bits %s",
+    sox_report("effects chain: %-10s %gHz %u channels %u bits %s",
         effp->handler.name, effp->ininfo.rate, effp->ininfo.channels, effp->ininfo.size * 8,
         (effp->handler.flags & SOX_EFF_MCHAN)? "(multi)" : "");
   }
@@ -1403,7 +1403,7 @@
   if (ofile->signal.channels == 0)
     ofile->signal.channels = combiner.channels;
 
-  combiner.rate = combiner.rate * effects_global_info.speed + .5;
+  combiner.rate = combiner.rate * effects_global_info.speed;
 
   for (i = 0; i < nuser_effects; i++)
     known_length = known_length && !(user_efftab[i].handler.flags & SOX_EFF_LENGTH);
--- a/src/sox.h
+++ b/src/sox.h
@@ -155,12 +155,14 @@
   ((d) < 0? (d) <= SOX_SAMPLE_MIN - 0.5? ++(clips), SOX_SAMPLE_MIN: (d) - 0.5 \
         : (d) >= SOX_SAMPLE_MAX + 0.5? ++(clips), SOX_SAMPLE_MAX: (d) + 0.5)
 
-/* Rvalue MACRO to clip a sox_sample_t to 24 bits,
+/* Rvalue MACRO to clip an integer to a given number of bits
  * and increment a counter if clipping occurs.
  */
-#define SOX_24BIT_CLIP_COUNT(l, clips) \
-  ((l) >= ((sox_ssample_t)1 << 23)? ++(clips), ((sox_ssample_t)1 << 23) - 1 : \
-   (l) <=-((sox_ssample_t)1 << 23)? ++(clips),-((sox_ssample_t)1 << 23) + 1 : (l))
+#define SOX_INTEGER_CLIP_COUNT(bits,i,clips) ( \
+  (i) >(1 << ((bits)-1))- 1? ++(clips),(1 << ((bits)-1))- 1 : \
+  (i) <-1 << ((bits)-1)    ? ++(clips),-1 << ((bits)-1) : (i))
+#define SOX_16BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(16,i,clips)
+#define SOX_24BIT_CLIP_COUNT(i,clips) SOX_INTEGER_CLIP_COUNT(24,i,clips)
 
 
 
@@ -174,7 +176,7 @@
 #define SOX_SSIZE_MAX 0x7fffffff
 #define SOX_SSIZE_MIN (-SOX_SSIZE_MAX - 1)
 
-typedef unsigned sox_rate_t;
+typedef double sox_rate_t;
 /* Warning, this is a MAX value used in the library.  Each format and
  * effect may have its own limitations of rate.
  */
--- a/src/stat.c
+++ b/src/stat.c
@@ -146,7 +146,7 @@
 
         if (stat->fft_offset >= stat->fft_size) {
           stat->fft_offset = 0;
-          print_power_spectrum(stat->fft_size, (double)effp->ininfo.rate, stat->re_in, stat->re_out);
+          print_power_spectrum(stat->fft_size, effp->ininfo.rate, stat->re_in, stat->re_out);
         }
 
       }
@@ -215,7 +215,7 @@
     for (x = stat->fft_offset; x < stat->fft_size; x++)
       stat->re_in[x] = 0;
       
-    print_power_spectrum(stat->fft_size, (double)effp->ininfo.rate, stat->re_in, stat->re_out);
+    print_power_spectrum(stat->fft_size, effp->ininfo.rate, stat->re_in, stat->re_out);
   }
 
   *osamp = 0;