shithub: sox

Download patch

ref: d9b41147ef5125bf5fb646546caf475bc3d02f62
parent: 6b43e9afa4681b42350ea17adcf54a015afc1731
author: robs <robs>
date: Thu Jun 5 18:52:31 EDT 2008

clean-ups

--- a/src/rate.c
+++ b/src/rate.c
@@ -18,6 +18,10 @@
 /* Based upon the techniques described in `The Quest For The Perfect Resampler'
  * by Laurent De Soras; http://ldesoras.free.fr/doc/articles/resampler-en.pdf */
 
+#ifdef NDEBUG /* Enable assert always. */
+#undef NDEBUG /* Must undef above assert.h or other that might include it. */
+#endif
+
 #include "sox_i.h"
 #include "fft4g.h"
 #define  FIFO_SIZE_T int
@@ -32,9 +36,6 @@
 #define  TO_SOX     SOX_FLOAT_64BIT_TO_SAMPLE
 #define  FROM_SOX   SOX_SAMPLE_TO_FLOAT_64BIT
 #define  coef(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) coef_p[(fir_len) * ((interp_order) + 1) * (phase_num) + ((interp_order) + 1) * (fir_coef_num) + (interp_order - coef_interp_num)]
-#ifdef   NDEBUG
-#undef   NDEBUG     /* Enable assert always */
-#endif
 
 static sample_t * prepare_coefs(raw_coef_t const * coefs, int num_coefs,
     int num_phases, int interp_order, int multiplier)
@@ -69,11 +70,11 @@
 typedef struct {
   int        dft_length, num_taps;
   sample_t   * coefs;
-} half_band_t;
+} half_band_t;      /* Note: not half-band as in symmetric about Fn/2 (Fs/4) */
 
 typedef struct {    /* Data that are shared between channels and filters */
   sample_t   * poly_fir_coefs;
-  half_band_t half_band[2];    /* [0]: halve; [1]: down/up: halve/double */ 
+  half_band_t half_band[2];    /* [0]: halve; [1]: down/up: halve/double */
   sample_t   * sin_cos_table;  /* For Ooura fft */
   int        * bit_rev_table;  /* ditto */
 } rate_shared_t;
@@ -81,6 +82,7 @@
 struct stage;
 typedef void (* stage_fn_t)(struct stage * input, fifo_t * output);
 typedef struct stage {
+  rate_shared_t * shared;
   fifo_t     fifo;
   int        pre;              /* Number of past samples to store */
   int        pre_post;         /* pre + number of future samples to store */
@@ -87,11 +89,7 @@
   int        preload;          /* Number of zero samples to pre-load the fifo */
   int        which;            /* Which of the 2 half-band filters to use */
   stage_fn_t fn;
-  sample_t   out_in_ratio;
-
-  rate_shared_t * shared;
                                /* For poly_fir & spline: */
-  int       divisor;
   union {                      /* 32bit.32bit fixed point arithmetic */
     #if defined(WORDS_BIGENDIAN)
     struct {int32_t integer; uint32_t fraction;} parts;
@@ -101,6 +99,8 @@
     int64_t all;
     #define MULT32 (65536. * 65536.)
   } at, step;
+  int        divisor;          /* For step: > 1 for rational; 1 otherwise */
+  double     out_in_ratio;
 } stage_t;
 
 #define stage_occupancy(s) max(0, fifo_occupancy(&(s)->fifo) - (s)->pre_post)
@@ -223,10 +223,10 @@
 {
   double tr_bw, beta;
 
-  Fp /= Fn, Fc /= Fn;        /* Normalise to Fn (nyquist) = 1 */
+  Fp /= Fn, Fc /= Fn;        /* Normalise to Fn = 1 */
   tr_bw = .5869 * (Fc - Fp); /* Transition band-width: 6dB to stop points */
 
-  if (*num_taps == 0) {
+  if (*num_taps == 0) {        /* TODO this could be cleaner, esp. for k != 0 */
     double n160 = (.0425* att - 1.4) /  tr_bw;    /* Half order for att = 160 */
     int n = n160 * (16.556 / (att - 39.6) + .8625) + .5;  /* For att [80,160) */
     *num_taps = k? 2 * n : 2 * (n + (n & 1)) + 1; /* =1 %4 (0 phase 1/2 band) */
@@ -248,10 +248,11 @@
   return result;
 }
 
-static void half_band_filter_init(rate_shared_t * p, unsigned which, int num_taps, sample_t const h[], double Fp, double atten, int multiplier)
+static void half_band_filter_init(rate_shared_t * p, unsigned which,
+    int num_taps, sample_t const h[], double Fp, double atten, int multiplier)
 {
   half_band_t * f = &p->half_band[which];
-  int dft_length, i, M = num_taps / 2;
+  int dft_length, i;
 
   if (f->num_taps)
     return;
@@ -260,7 +261,7 @@
     f->coefs = calloc(dft_length, sizeof(*f->coefs));
     for (i = 0; i < num_taps; ++i)
       f->coefs[(i + dft_length - num_taps + 1) & (dft_length - 1)]
-          = h[abs(M - i)] / dft_length * 2 * multiplier;
+          = h[abs(num_taps / 2 - i)] / dft_length * 2 * multiplier;
   }
   else {
     double * h = design_lpf(Fp, 1., 2., atten, &num_taps, 0);
@@ -274,10 +275,11 @@
   assert(num_taps & 1);
   f->num_taps = num_taps;
   f->dft_length = dft_length;
-  sox_debug("fir_len=%i dft_length=%i Fp=%g atten=%g", num_taps, dft_length, Fp, atten);
+  sox_debug("fir_len=%i dft_length=%i Fp=%g atten=%g mult=%i",
+      num_taps, dft_length, Fp, atten, multiplier);
   if (!p->bit_rev_table) {
-    p->bit_rev_table = calloc((size_t)sqrt((double)dft_length) + 2, sizeof(*p->bit_rev_table));
-    p->sin_cos_table = calloc(dft_length / 2, sizeof(*p->sin_cos_table));
+    p->bit_rev_table = calloc(dft_br_len(dft_length),sizeof(*p->bit_rev_table));
+    p->sin_cos_table = calloc(dft_sc_len(dft_length),sizeof(*p->sin_cos_table));
   }
   rdft(dft_length, 1, f->coefs, p->bit_rev_table, p->sin_cos_table);
 }
@@ -287,7 +289,7 @@
 typedef struct {
   double     factor;
   size_t     samples_in, samples_out;
-  int        level, input_level, output_level;
+  int        level, input_stage_num, output_stage_num;
   sox_bool   upsample;
   stage_t    * stages;
 } rate_t;
@@ -334,10 +336,10 @@
   sox_debug("i/o=%g; %.9g:%i @ level %i", p->factor, factor, divisor, p->level);
 
   mult = 1 + p->upsample; /* Compensate for zero-stuffing in double_sample */
-  p->input_level = -p->upsample;
-  p->output_level = p->level;
+  p->input_stage_num = -p->upsample;
+  p->output_stage_num = p->level;
   if (quality == Quick) {
-    ++p->output_level;
+    ++p->output_stage_num;
     last_stage.fn = cubic_spline;
     last_stage.pre_post = max(3, last_stage.step.parts.integer);
     last_stage.preload = last_stage.pre = 1;
@@ -350,9 +352,9 @@
       interp_order = quality > High;
     interp_order = divisor == 1? 1 + interp_order : 0;
     last_stage.divisor = divisor;
-    p->output_level += 2;
+    p->output_stage_num += 2;
     if (p->upsample && quality == Low)
-      mult = 1, ++p->input_level, --p->output_level, --n;
+      mult = 1, ++p->input_stage_num, --p->output_stage_num, --n;
     f = &poly_firs[n];
     f1 = &f->interp[interp_order];
     if (!last_stage.shared->poly_fir_coefs) {
@@ -362,7 +364,7 @@
       assert(num_taps == f->num_coefs * phases - 1);
       last_stage.shared->poly_fir_coefs =
           prepare_coefs(coefs, f->num_coefs, phases, interp_order, mult);
-      sox_debug("fir_len=%i phases=%i coef_interp=%i multiplier=%i size=%s",
+      sox_debug("fir_len=%i phases=%i coef_interp=%i mult=%i size=%s",
           f->num_coefs, phases, interp_order, mult,
           sigfigs3((num_taps + 1) * (interp_order + 1) * sizeof(sample_t)));
       free(coefs);
@@ -373,12 +375,7 @@
     last_stage.preload = last_stage.pre_post >> 1;
     mult = 1;
   }
-  if (quality == Low) { /* dft is slower here, so use normal convolution */
-    post_stage.fn = half_sample_low;
-    post_stage.pre_post = 2 * (array_length(half_fir_coefs_low) - 1);
-    post_stage.preload = post_stage.pre = post_stage.pre_post >> 1;
-  }
-  else if (quality != Quick) {
+  if (quality > Low) {
     typedef struct {int len; sample_t const * h; double bw, a;} filter_t;
     static filter_t const filters[] = {
       {2 * array_length(half_fir_coefs_low) - 1, half_fir_coefs_low, 0,0},
@@ -396,7 +393,7 @@
         half_band_filter_init(shared, 0, 0, NULL, max(p->factor, .64), f->a, 1);
       else shared->half_band[0] = shared->half_band[1];
     }
-    else if (p->level > 0 && p->output_level > p->level) {
+    else if (p->level > 0 && p->output_stage_num > p->level) {
       double pass = f->bw * divisor / factor / 2;
       if ((1 - pass) / (1 - f->bw) > 2)
         half_band_filter_init(shared, 1, 0, NULL, max(pass, .64), f->a, 1);
@@ -404,6 +401,11 @@
     post_stage.fn = half_sample;
     post_stage.preload = shared->half_band[0].num_taps >> 1;
   }
+  else if (quality == Low && !p->upsample) {    /* dft is slower here, so */
+    post_stage.fn = half_sample_low;            /* use normal convolution */
+    post_stage.pre_post = 2 * (array_length(half_fir_coefs_low) - 1);
+    post_stage.preload = post_stage.pre = post_stage.pre_post >> 1;
+  }
   if (p->level > 0) {
     stage_t * s = & p->stages[p->level - 1];
     if (shared->half_band[1].num_taps) {
@@ -413,7 +415,7 @@
     }
     else *s = post_stage;
   }
-  for (i = p->input_level; i <= p->output_level; ++i) {
+  for (i = p->input_stage_num; i <= p->output_stage_num; ++i) {
     stage_t * s = &p->stages[i];
     if (i >= 0 && i < p->level - 1) {
       s->fn = half_sample_25;
@@ -422,17 +424,18 @@
     }
     fifo_create(&s->fifo, sizeof(sample_t));
     memset(fifo_reserve(&s->fifo, s->preload), 0, sizeof(sample_t)*s->preload);
-    if (i < p->output_level)
-      sox_debug("stage=%-3ipre_post=%-3ipre=%-3ipreload=%i", i, s->pre_post, s->pre, s->preload);
+    if (i < p->output_stage_num)
+      sox_debug("stage=%-3ipre_post=%-3ipre=%-3ipreload=%i",
+          i, s->pre_post, s->pre, s->preload);
   }
 }
 
 static void rate_process(rate_t * p)
 {
-  stage_t * stage = p->stages + p->input_level;
+  stage_t * stage = p->stages + p->input_stage_num;
   int i;
 
-  for (i = p->input_level; i < p->output_level; ++i, ++stage)
+  for (i = p->input_stage_num; i < p->output_stage_num; ++i, ++stage)
     stage->fn(stage, &(stage+1)->fifo);
 }
 
@@ -439,12 +442,12 @@
 static sample_t * rate_input(rate_t * p, sample_t const * samples, size_t n)
 {
   p->samples_in += n;
-  return fifo_write(&p->stages[p->input_level].fifo, (int)n, samples);
+  return fifo_write(&p->stages[p->input_stage_num].fifo, (int)n, samples);
 }
 
 static sample_t const * rate_output(rate_t * p, sample_t * samples, size_t * n)
 {
-  fifo_t * fifo = &p->stages[p->output_level].fifo;
+  fifo_t * fifo = &p->stages[p->output_stage_num].fifo;
   p->samples_out += *n = min(*n, (size_t)fifo_occupancy(fifo));
   return fifo_read(fifo, (int)*n, samples);
 }
@@ -451,7 +454,7 @@
 
 static void rate_flush(rate_t * p)
 {
-  fifo_t * fifo = &p->stages[p->output_level].fifo;
+  fifo_t * fifo = &p->stages[p->output_stage_num].fifo;
   size_t samples_out = p->samples_in / p->factor + .5;
   size_t remaining = samples_out - p->samples_out;
   sample_t * buff = calloc(1024, sizeof(*buff));
@@ -472,7 +475,7 @@
   rate_shared_t * shared = p->stages[0].shared;
   int i;
 
-  for (i = p->input_level; i <= p->output_level; ++i)
+  for (i = p->input_stage_num; i <= p->output_stage_num; ++i)
     fifo_delete(&p->stages[i].fifo);
   free(shared->bit_rev_table);
   free(shared->sin_cos_table);
@@ -569,10 +572,10 @@
 sox_effect_handler_t const * sox_rate_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "rate", "[-q|-l|-m|-s|-h]\n"
+    "rate", "[-q|-l|-m|-h|-v]\n"
     "     Quality        BW %    Rej dB    Typical Use\n"
     " -q  quick & dirty  n/a   ~30 @ Fs/4  playback on ancient hardware\n"
-    " -l  low            80       100      playback on old hardware\n" 
+    " -l  low            80       100      playback on old hardware\n"
     " -m  medium         99       100      audio playback\n"
     " -h  high           99       120      16-bit mastering (use with dither)\n"
     " -v  very high      99.7     150      24-bit mastering"