shithub: sox

Download patch

ref: 3cda6b3e056b68f4d46af3c7e25e226bd6b70592
parent: 89dba2b6bfd17720c5946a97da614025befe63f4
author: robs <robs>
date: Mon Mar 23 12:18:10 EDT 2009

add sloped TPDF

--- a/src/dither.c
+++ b/src/dither.c
@@ -115,16 +115,16 @@
 
 static const filter_t filters[] = {
   {44100, fir,  5, 210, lip44, Shape_lipshitz},
-  {46000, fir,  9, 270, fwe44, Shape_f_weighted},
+  {46000, fir,  9, 271, fwe44, Shape_f_weighted},
   {46000, fir,  9, 159, mew44, Shape_modified_e_weighted},
   {46000, fir,  9, 320, iew44, Shape_improved_e_weighted},
   {48000, iir,  4, 220, ges48, Shape_gesemann},
-  {44100, iir,  4, 228, ges44, Shape_gesemann},
+  {44100, iir,  4, 229, ges44, Shape_gesemann},
   {48000, fir, 16, 300, shi48, Shape_shibata},
   {44100, fir, 20, 330, shi44, Shape_shibata},
-  {37800, fir, 16, 238, shi38, Shape_shibata},
-  {48000, fir, 16, 245, shl48, Shape_low_shibata},
-  {44100, fir, 15, 246, shl44, Shape_low_shibata},
+  {37800, fir, 16, 240, shi38, Shape_shibata},
+  {48000, fir, 16, 249, shl48, Shape_low_shibata},
+  {44100, fir, 15, 247, shl44, Shape_low_shibata},
   {44100, fir, 20, 382, shh44, Shape_high_shibata},
   {    0, fir,  0,   0,  NULL, Shape_none},
 };
@@ -133,13 +133,13 @@
 
 typedef struct {
   filter_name_t filter_name;
-  sox_bool      auto_detect;
+  sox_bool      auto_detect, alt_tpdf;
   double        dummy;
 
   double        previous_errors[MAX_N * 2];
   double        previous_outputs[MAX_N * 2];
   size_t        pos, prec, num_output;
-  int32_t       history, ranqd1;
+  int32_t       history, ranqd1, r;
   double const  * coefs;
   sox_bool      dither_off;
   int           (*flow)(sox_effect_t *, const sox_sample_t *, sox_sample_t *, size_t *, size_t *);
@@ -178,13 +178,13 @@
   priv_t * p = (priv_t *)effp->priv;
   size_t len = *isamp = *osamp = min(*isamp, *osamp);
 
-  if (p->auto_detect) while (len--) {
-    p->history = ((p->history << 1) + !!(*ibuf & (-1u >> p->prec)));
-    if (p->history) {
-      int32_t r1 = RANQD1 >> p->prec, r2 = RANQD1 >> p->prec;
-      double d = ((double)*ibuf++ + r1 + r2) / (1 << (32 - p->prec));
+  while (len--) {
+    if (!p->auto_detect || (p->history = ((p->history << 1) + !!(*ibuf & (-1u >> p->prec))))) {
+      int32_t r = RANQD1 >> p->prec;
+      double d = ((double)*ibuf++ + r + (p->alt_tpdf? -p->r : (RANQD1 >> p->prec))) / (1 << (32 - p->prec));
       int i = d < 0? d - .5 : d + .5;
-      if (i < (-1 << (p->prec-1)))
+      p->r = r;
+      if (i <= (-1 << (p->prec-1)))
         ++effp->clips, *obuf = SOX_SAMPLE_MIN;
       else if (i > (int)SOX_INT_MAX(p->prec))
         ++effp->clips, *obuf = SOX_INT_MAX(p->prec) << (32 - p->prec);
@@ -202,17 +202,6 @@
     }
     ++p->num_output;
   }
-  else while (len--) {
-    int32_t r1 = RANQD1 >> p->prec, r2 = RANQD1 >> p->prec;
-    double d = ((double)*ibuf++ + r1 + r2) / (1 << (32 - p->prec));
-    int i = d < 0? d - .5 : d + .5;
-    if (i <= (-1 << (p->prec-1)))
-      ++effp->clips, *obuf = SOX_SAMPLE_MIN;
-    else if (i > (int)SOX_INT_MAX(p->prec))
-      ++effp->clips, *obuf = SOX_INT_MAX(p->prec) << (32 - p->prec);
-    else *obuf = i << (32 - p->prec);
-    ++obuf;
-  }
   return SOX_SUCCESS;
 }
 
@@ -221,8 +210,9 @@
   priv_t * p = (priv_t *)effp->priv;
   int c;
 
-  while ((c = getopt(argc, argv, "+asf:""rt")) != -1) switch (c) {
+  while ((c = getopt(argc, argv, "+aSsf:""rt")) != -1) switch (c) {
     case 'a': p->auto_detect = sox_true; break;
+    case 'S': p->alt_tpdf = sox_true; break;
     case 'r': case 't': break; /* No longer in use */
     case 's': p->filter_name = Shape_shibata; break;
     case 'f':
@@ -253,7 +243,10 @@
 
     for (f = filters; f->len && (f->name != p->filter_name || fabs(effp->in_signal.rate - f->rate) / f->rate > .05); ++f); /* 5% leeway on frequency */
     if (!f->len) {
-      lsx_warn("no `%s' filter is available for rate %g; using plain TPDF", lsx_find_enum_value(p->filter_name, filter_names)->text, effp->in_signal.rate);
+      p->alt_tpdf |= effp->in_signal.rate >= 22050;
+      lsx_warn("no `%s' filter is available for rate %g; using %s TPDF",
+          lsx_find_enum_value(p->filter_name, filter_names)->text,
+          effp->in_signal.rate, p->alt_tpdf? "sloped" : "plain");
     }
     else {
       assert(f->len <= MAX_N);
@@ -289,8 +282,10 @@
 sox_effect_handler_t const * lsx_dither_effect_fn(void)
 {
   static sox_effect_handler_t handler = {
-    "dither", "[-a] [-s|-f filter]"
+    "dither", "[-a] [-S|-s|-f filter]"
+    "\n  (none)   Use TPDF"
     "\n  -a       Automatically turn on & off dithering as needed (use with caution!)"
+    "\n  -S       Use sloped TPDF (without noise shaping)"
     "\n  -s       Shape noise (with shibata filter)"
     "\n  -f name  Set shaping filter to one of: lipshitz, f-weighted,"
     "\n           modified-e-weighted, improved-e-weighted, gesemann,"