shithub: sox

Download patch

ref: dee63f713a6c9ae5d37671ee7ff20b52d50f9232
parent: 69778917e402941035a4fdb9fdfb6b2bb71bac11
author: cbagwell <cbagwell>
date: Sun Feb 19 17:35:59 EST 2006

Convert to common set of CLIP routines.

--- a/Changelog
+++ b/Changelog
@@ -8,7 +8,7 @@
 ------------
 
   o The "filter" effect could go into infinite drain mode.  Now
-    only drain 1 buffer.
+    only drain 1 buffer.  noisered as well.
   o SoX was ignoring user aborts (ctrl-c) if it occured during
     effect drain operations.  This was bad if effects had
     bugs and stuck in infinite loop.
@@ -15,6 +15,8 @@
   o Stop SoX from crashing when file type could not be auto
     determined (bug 1417776).
   o Output filenames with multiple '.' confused SoX.  (Christian Hammers)
+  o Moved to a common set of CLIP routines.  This fixed clipping
+    bugs in noisered and mcompand.
 
 sox-12.17.9
 -----------
--- a/src/avg.c
+++ b/src/avg.c
@@ -527,10 +527,7 @@
             samp = 0.0;
             for (i = 0; i < ichan; i++)
                 samp += ibuf[i] * avg->sources[i][j];
-            if (samp < ST_SAMPLE_MIN)
-                samp = ST_SAMPLE_MIN;
-            else if (samp > ST_SAMPLE_MAX)
-                samp = ST_SAMPLE_MAX;
+            ST_SAMPLE_CLIP(samp, NULL);
             obuf[j] = samp;
         }
     }
--- a/src/btrworth.c
+++ b/src/btrworth.c
@@ -81,12 +81,7 @@
     butterworth->y [1] = butterworth->y [0];
     butterworth->y [0] = out;
 
-    if (out < ST_SAMPLE_MIN) {
-      out = ST_SAMPLE_MIN;
-    }
-    else if (out > ST_SAMPLE_MAX) {
-      out = ST_SAMPLE_MAX;
-    }
+    ST_SAMPLE_CLIP(out, NULL);
 
     *obuf++ = out;
   }
--- a/src/compand.c
+++ b/src/compand.c
@@ -325,12 +325,8 @@
       if (l->delay_buf_size <= 0)
       {
         checkbuf = ibuf[chan]*(outv/v)*l->outgain;
-        if(checkbuf > ST_SAMPLE_MAX)
-         obuf[odone] = ST_SAMPLE_MAX;
-        else if(checkbuf < ST_SAMPLE_MIN)
-         obuf[odone] = ST_SAMPLE_MIN;
-        else
-         obuf[odone] = checkbuf;
+        ST_SAMPLE_CLIP(checkbuf, NULL);
+        obuf[odone] = checkbuf;
 
         idone++;
         odone++;
@@ -341,12 +337,8 @@
         {
             l->delay_buf_full=1; //delay buffer is now definetly full
             checkbuf = l->delay_buf[l->delay_buf_ptr]*(outv/v)*l->outgain;
-            if(checkbuf > ST_SAMPLE_MAX)
-             obuf[odone] = ST_SAMPLE_MAX;
-            else if(checkbuf < ST_SAMPLE_MIN)
-             obuf[odone] = ST_SAMPLE_MIN;
-            else
-             obuf[odone] = checkbuf;
+            ST_SAMPLE_CLIP(checkbuf, NULL);
+            obuf[odone] = checkbuf;
 
             odone++;
             idone++;
--- a/src/dcshift.c
+++ b/src/dcshift.c
@@ -114,26 +114,6 @@
     return ST_SUCCESS;
 }
 
-/* conversion. clipping could be smoother at high ends?
- * this could be a function on its own, with clip count and report
- * handled by eff_t and caller.
- */
-static st_sample_t clip(dcs_t dcs, const DCSHIFT_FLOAT v)
-{
-    if (v > ST_SAMPLE_MAX)
-    {
-         dcs->clipped++;
-         return ST_SAMPLE_MAX;
-    }
-    else if (v < ST_SAMPLE_MIN)
-    {
-        dcs->clipped++;
-        return ST_SAMPLE_MIN;
-    }
-    /* else */
-    return (st_sample_t) v;
-}
-
 #ifndef MIN
 #define MIN(s1,s2) ((s1)<(s2)?(s1):(s2))
 #endif
@@ -185,7 +165,8 @@
                         sample = dcshift * ST_SAMPLE_MAX + sample;
                 }
 
-                *obuf++ = clip(dcs, sample);
+                ST_SAMPLE_CLIP(sample, &dcs->clipped);
+                *obuf++ = sample;
             }
     }
     else
@@ -192,7 +173,13 @@
     {
         /* quite basic, with clipping */
         for (;len>0; len--)
-                *obuf++ = clip(dcs, dcshift * ST_SAMPLE_MAX + *ibuf++);
+        {
+                float f;
+
+                f = dcshift * ST_SAMPLE_MAX + *ibuf++;
+                ST_SAMPLE_CLIP(f, &dcs->clipped);
+                *obuf++ = f;
+        }
     }
     return ST_SUCCESS;
 }
--- a/src/filter.c
+++ b/src/filter.c
@@ -266,6 +266,9 @@
         /* fprintf(stderr,"DRAIN osamp %d\n", *osamp); */
         if (isamp_res)
                 st_warn("drain overran obuf by %d\n", isamp_res); fflush(stderr);
+        /* This is very picky. osamp better be big enough to grab
+         * all remaining samples or they will be discarded.
+         */
         return (ST_EOF);
 }
 
--- a/src/highp.c
+++ b/src/highp.c
@@ -93,10 +93,7 @@
                 d = highp->A0 * l + 
                     highp->A1 * highp->inm1 + 
                     highp->B1 * highp->outm1;
-                if (d < ST_SAMPLE_MIN)
-                    d = ST_SAMPLE_MIN;
-                else if (d > ST_SAMPLE_MAX)
-                    d = ST_SAMPLE_MAX;
+                ST_SAMPLE_CLIP(d, NULL);
                 highp->inm1 = l;
                 highp->outm1 = d;
                 *obuf++ = d;
--- a/src/lowp.c
+++ b/src/lowp.c
@@ -87,10 +87,7 @@
         for(done = 0; done < len; done++) {
                 l = *ibuf++;
                 d = lowp->A * l + lowp->B * lowp->outm1;
-                if (d < ST_SAMPLE_MIN)
-                    d = ST_SAMPLE_MIN;
-                else if (d > ST_SAMPLE_MAX)
-                    d = ST_SAMPLE_MAX;
+                ST_SAMPLE_CLIP(d, NULL);
                 lowp->outm1 = d;
                 *obuf++ = d;
         }
--- a/src/mcompand.c
+++ b/src/mcompand.c
@@ -168,12 +168,7 @@
       butterworth->xy_low[chan].y [1] = butterworth->xy_low[chan].y [0];
       butterworth->xy_low[chan].y [0] = out;
 
-      if (out < ST_SAMPLE_MIN) {
-        out = ST_SAMPLE_MIN;
-      }
-      else if (out > ST_SAMPLE_MAX) {
-        out = ST_SAMPLE_MAX;
-      }
+      ST_SAMPLE_CLIP(out, NULL);
 
       *lowbufptr = out;
 
@@ -190,12 +185,7 @@
       butterworth->xy_high[chan].y [1] = butterworth->xy_high[chan].y [0];
       butterworth->xy_high[chan].y [0] = out;
 
-      if (out < ST_SAMPLE_MIN) {
-        out = ST_SAMPLE_MIN;
-      }
-      else if (out > ST_SAMPLE_MAX) {
-        out = ST_SAMPLE_MAX;
-      }
+      ST_SAMPLE_CLIP(out, NULL);
 
       /* don't forget polarity reversal of high pass! */
 
@@ -591,6 +581,7 @@
   int len = ((*isamp > *osamp) ? *osamp : *isamp);
   int band, i;
   st_sample_t *abuf, *bbuf, *cbuf, *oldabuf;
+  double out;
 
   if (c->band_buf_len < len) {
     if ((! (c->band_buf1 = (st_sample_t *)realloc(c->band_buf1,len*sizeof(st_sample_t)))) ||
@@ -618,21 +609,16 @@
       abuf = c->band_buf3;
     (void)st_mcompand_flow_1(c,l,bbuf,abuf,len,effp->outinfo.channels);
     for (i=0;i<len;++i)
-      obuf[i] += abuf[i];
+    {
+      out = obuf[i] + abuf[i];
+      ST_SAMPLE_CLIP(out, NULL);
+      obuf[i] = out;
+    }
     oldabuf = abuf;
     abuf = cbuf;
     cbuf = oldabuf;
   }
 
-  for (i=0;i<len;++i) {
-    if (obuf[i] < ST_SAMPLE_MIN) {
-      obuf[i] = ST_SAMPLE_MIN;
-    }
-    else if (obuf[i] > ST_SAMPLE_MAX) {
-      obuf[i] = ST_SAMPLE_MAX;
-    }
-  }
-
   *isamp = *osamp = len;
 
   return ST_SUCCESS;
@@ -641,12 +627,15 @@
 static int st_mcompand_drain_1(compand_t c, comp_band_t l, st_sample_t *obuf, int maxdrain, int band)
 {
   int done;
+  double out;
 
   /*
    * Drain out delay samples.  Note that this loop does all channels.
    */
   for (done = 0;  done < maxdrain  &&  l->delay_buf_cnt > 0;  done++) {
-    obuf[done] += l->delay_buf[l->delay_buf_ptr++];
+    out = obuf[done] + l->delay_buf[l->delay_buf_ptr++];
+    ST_SAMPLE_CLIP(out, NULL);
+    obuf[done] = out;
     l->delay_buf_ptr %= c->delay_buf_size;
     l->delay_buf_cnt--;
   }
@@ -664,7 +653,6 @@
   int band, drained, mostdrained = 0;
   compand_t c = (compand_t)effp->priv;
   comp_band_t l;
-  int i;
 
   memset(obuf,0,*osamp * sizeof *obuf);
   for (band=0;band<c->nBands;++band) {
@@ -672,15 +660,6 @@
     drained = st_mcompand_drain_1(c,l,obuf,*osamp,0);
     if (drained > mostdrained)
       mostdrained = drained;
-  }
-
-  for (i=0;i<mostdrained;++i) {
-    if (obuf[i] < ST_SAMPLE_MIN) {
-      obuf[i] = ST_SAMPLE_MIN;
-    }
-    else if (obuf[i] > ST_SAMPLE_MAX) {
-      obuf[i] = ST_SAMPLE_MAX;
-    }
   }
 
   *osamp = mostdrained;
--- a/src/noisered.c
+++ b/src/noisered.c
@@ -210,9 +210,10 @@
                           st_sample_t *obuf, int len) {
     int j;
     float* nextwindow;
-    int use = min(len, WINDOWSIZE)-(WINDOWSIZE/2);
+    int use = min(len, WINDOWSIZE)-min(len,(WINDOWSIZE/2));
     chandata_t *chan = &(data->chandata[chan_num]);
     int first = (chan->lastwindow == NULL);
+    int clipped = 0;
 
     nextwindow = (float*)calloc(WINDOWSIZE, sizeof(float));
     memcpy(nextwindow, chan->window+WINDOWSIZE/2,
@@ -223,15 +224,12 @@
     if (!first) {
         for (j = 0; j < use; j ++) {
             float s = chan->window[j] + chan->lastwindow[WINDOWSIZE/2 + j];
-            if (s < -1 || s > 1) {
-                float news;
-                if (s > 1)
-                    news = 1;
-                else
-                    news = -1;
-
-                st_warn("noisered: Output clipped from %f to %f.\n",
-                        s, news);
+            ST_NORMALIZED_CLIP(s, &clipped);
+            if (clipped)
+            {
+                /* Reset for future tests. */
+                clipped = 0;
+                st_warn("noisered: Output clipped to %f.\n", s);
             }
             obuf[chan_num + num_chans * j] =
                 ST_FLOAT_DWORD_TO_SAMPLE(s);
@@ -314,7 +312,10 @@
     for (i = 0; i < tracks; i ++) {
         *osamp = process_window(data, i, tracks, obuf, data->bufdata);
     }
-    return (ST_SUCCESS);
+    /* This is very picky.  osamp needs to be big enough to get all
+     * remaining data or it will be discarded.
+     */
+    return (ST_EOF);
 }
 
 /*
--- a/src/pan.c
+++ b/src/pan.c
@@ -93,26 +93,6 @@
 }
 
 
-/* clip value if necessary. see comments about such a function in vol.c
- * Okay, it might be quite slow to have such a function for so small
- * a task. Hopefully the function can be inlined by the compiler?
- */
-static st_sample_t clip(pan_t pan, PAN_FLOAT value)
-{
-    if (value < ST_SAMPLE_MIN) 
-    {
-        pan->clipped++;
-        return ST_SAMPLE_MIN;
-    }
-    else if (value > ST_SAMPLE_MAX) 
-    {
-        pan->clipped++;
-        return ST_SAMPLE_MAX;
-    } /* else */
-
-    return (st_sample_t) value;
-}
-
 #ifndef MIN
 #define MIN(s1,s2) ((s1)<(s2)?(s1):(s2))
 #endif
@@ -157,15 +137,24 @@
             break;
         case 2: /* average 2 */
             for (done=0; done<len; done++)
-                *obuf++ = clip(pan, HALF*ibuf[0] + HALF*ibuf[1]),
-                    ibuf += 2;
+            {
+                float f;
+                f = HALF*ibuf[0] + HALF*ibuf[1];
+                ST_SAMPLE_CLIP(f, &pan->clipped);
+                *obuf++ = f;
+                ibuf += 2;
+            }
             break;
         case 4: /* average 4 */
             for (done=0; done<len; done++)
-                *obuf++ = clip(pan, 
-                               QUARTER*ibuf[0] + QUARTER*ibuf[1] + 
-                               QUARTER*ibuf[2] + QUARTER*ibuf[3]),
-                    ibuf += 4;
+            {
+                float f;
+                f = QUARTER*ibuf[0] + QUARTER*ibuf[1] + 
+                        QUARTER*ibuf[2] + QUARTER*ibuf[3];
+                ST_SAMPLE_CLIP(f, &pan->clipped);
+                *obuf++ = f;
+                ibuf += 4;
+            }
             break;
         default:
             UNEXPECTED_CHANNELS;
@@ -177,8 +166,14 @@
         case 1: /* linear */
             for (done=0; done<len; done++)
             {
-                obuf[0] = clip(pan, left * ibuf[0]);
-                obuf[1] = clip(pan, right * ibuf[0]);
+                float f;
+
+                f = left * ibuf[0];
+                ST_SAMPLE_CLIP(f, &pan->clipped);
+                obuf[0] = f;
+                f = right * ibuf[0];
+                ST_SAMPLE_CLIP(f, &pan->clipped);
+                obuf[1] = f;
                 obuf += 2;
                 ibuf++;
             }
@@ -197,8 +192,14 @@
 
                 for (done=0; done<len; done++)
                 {
-                    obuf[0] = clip(pan, cll * ibuf[0] + clr * ibuf[1]);
-                    obuf[1] = clip(pan, cr * ibuf[1]);
+                    float f;
+
+                    f = cll * ibuf[0] + clr * ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[0] = f;
+                    f = cr * ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[1] = f;
                     obuf += 2;
                     ibuf += 2;
                 }
@@ -214,8 +215,14 @@
 
                 for (done=0; done<len; done++)
                 {
-                    obuf[0] = clip(pan, cl * ibuf[0]);
-                    obuf[1] = clip(pan, crl * ibuf[0] + crr * ibuf[1]);
+                    float f;
+
+                    f = cl * ibuf[0];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[0] = f;
+                    f = crl * ibuf[0] + crr * ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[1] = f;
                     obuf += 2;
                     ibuf += 2;
                 }
@@ -233,7 +240,7 @@
 
                 for (done=0; done<len; done++)
                 {
-                    register PAN_FLOAT ibuf0, ibuf1;
+                    register PAN_FLOAT ibuf0, ibuf1, f;
 
                     /* build stereo signal */
                     ibuf0 = HALF*ibuf[0] + HALF*ibuf[2];
@@ -240,8 +247,12 @@
                     ibuf1 = HALF*ibuf[1] + HALF*ibuf[3];
 
                     /* pan it */
-                    obuf[0] = clip(pan, cll * ibuf0 + clr * ibuf1);
-                    obuf[1] = clip(pan, cr * ibuf1);
+                    f = cll * ibuf0 + clr * ibuf1;
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[0] = f;
+                    f = cr * ibuf1;
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[1] = f;
                     obuf += 2;
                     ibuf += 4;
                 }
@@ -257,13 +268,17 @@
 
                 for (done=0; done<len; done++)
                 {
-                    register PAN_FLOAT ibuf0, ibuf1;
+                    register PAN_FLOAT ibuf0, ibuf1, f;
 
                     ibuf0 = HALF*ibuf[0] + HALF*ibuf[2];
                     ibuf1 = HALF*ibuf[1] + HALF*ibuf[3];
 
-                    obuf[0] = clip(pan, cl * ibuf0);
-                    obuf[1] = clip(pan, crl * ibuf0 + crr * ibuf1);
+                    f = cl * ibuf0;
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[0] = f;
+                    f = crl * ibuf0 + crr * ibuf1;
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[1] = f;
                     obuf += 2;
                     ibuf += 4;
                 }
@@ -285,10 +300,14 @@
 
                 for (done=0; done<len; done++)
                 {
-                    obuf[0] = clip(pan, cl * ibuf[0]);
-                    obuf[2] = obuf[0];
-                    obuf[1] = clip(pan, cr * ibuf[0]);
-                    ibuf[3] = obuf[1];
+                    float f;
+
+                    f = cl * ibuf[0];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[2] = obuf[0] = f;
+                    f = cr * ibuf[0];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    ibuf[3] = obuf[1] = f;
                     obuf += 4;
                     ibuf++;
                 }
@@ -306,10 +325,14 @@
 
                 for (done=0; done<len; done++)
                 {
-                    obuf[0] = clip(pan, cll * ibuf[0] + clr * ibuf[1]);
-                    obuf[2] = obuf[0];
-                    obuf[1] = clip(pan, cr * ibuf[1]);
-                    ibuf[3] = obuf[1];
+                    float f;
+
+                    f = cll * ibuf[0] + clr * ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[2] = obuf[0] = f;
+                    f = cr * ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    ibuf[3] = obuf[1] = f;
                     obuf += 4;
                     ibuf += 2;
                 }
@@ -325,10 +348,14 @@
 
                 for (done=0; done<len; done++)
                 {
-                    obuf[0] = clip(pan, cl * ibuf[0]);
-                    obuf[2] = obuf[0];
-                    obuf[1] = clip(pan, crl * ibuf[0] + crr * ibuf[1]);
-                    ibuf[3] = obuf[1];
+                    float f;
+
+                    f = cl * ibuf[0];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[2] = obuf[0] =f ;
+                    f = crl * ibuf[0] + crr * ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    ibuf[3] = obuf[1] = f;
                     obuf += 4;
                     ibuf += 2;
                 }
@@ -347,10 +374,20 @@
 
                 for (done=0; done<len; done++)
                 {
-                    obuf[0] = clip(pan, cown*ibuf[0] + cright*ibuf[1]);
-                    obuf[1] = clip(pan, cown*ibuf[1] + cright*ibuf[3]);
-                    obuf[2] = clip(pan, cown*ibuf[2] + cright*ibuf[0]);
-                    obuf[3] = clip(pan, cown*ibuf[3] + cright*ibuf[2]);
+                    float f;
+
+                    f = cown*ibuf[0] + cright*ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[0] = f;
+                    f = cown*ibuf[1] + cright*ibuf[3];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[1] = f;
+                    f = cown*ibuf[2] + cright*ibuf[0];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[2] = f;
+                    f = cown*ibuf[3] + cright*ibuf[2];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[3] = f;
                     obuf += 4;
                     ibuf += 4;              
                 }
@@ -364,10 +401,20 @@
 
                 for (done=0; done<len; done++)
                 {
-                    obuf[0] = clip(pan, cleft*ibuf[2] + cown*ibuf[0]);
-                    obuf[1] = clip(pan, cleft*ibuf[0] + cown*ibuf[1]);
-                    obuf[2] = clip(pan, cleft*ibuf[3] + cown*ibuf[2]);
-                    obuf[3] = clip(pan, cleft*ibuf[1] + cown*ibuf[3]);
+                    float f;
+
+                    f = cleft*ibuf[2] + cown*ibuf[0];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[0] = f;
+                    f = cleft*ibuf[0] + cown*ibuf[1];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[1] = f;
+                    f = cleft*ibuf[3] + cown*ibuf[2];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[2] = f;
+                    f = cleft*ibuf[1] + cown*ibuf[3];
+                    ST_SAMPLE_CLIP(f, &pan->clipped);
+                    obuf[3] = f;
                     obuf += 4;
                     ibuf += 4;
                 }
--- a/src/pitch.c
+++ b/src/pitch.c
@@ -275,22 +275,6 @@
         pitch->acc[i] += pitch->fade[pitch->step-i-1]*pitch->tmp[i];
 }
 
-static st_sample_t clip(pitch_t pitch, PITCH_FLOAT v)
-{
-    if (v < ST_SAMPLE_MIN)
-    {
-        pitch->clipped++;
-        return ST_SAMPLE_MIN;
-    }
-    else if (v > ST_SAMPLE_MAX)
-    {
-        pitch->clipped++;
-        return ST_SAMPLE_MAX;
-    }
-    else
-        return (st_sample_t) v;
-}
-
 /*
  * Process options
  */
@@ -542,8 +526,14 @@
             int toout = MIN(*osamp-oindex, pitch->step-pitch->iacc);
 
             for (i=0; i<toout; i++)
-                obuf[oindex++] = clip(pitch, pitch->acc[pitch->iacc++]);
+            {
+                float f;
 
+                f = pitch->acc[pitch->iacc++];
+                ST_SAMPLE_CLIP(f, &pitch->clipped);
+                obuf[oindex++] = f;
+            }
+
             if (pitch->iacc == pitch->step)
             {
                 pitch->state = pi_input;
@@ -589,7 +579,13 @@
 
     /* (pitch->state == pi_output) */
     for (i=0; i<*osamp && i<pitch->index-pitch->overlap;)
-        obuf[i++] = clip(pitch, pitch->acc[pitch->iacc++]);
+    {
+        float f;
+
+        f = pitch->acc[pitch->iacc++];
+        ST_SAMPLE_CLIP(f, &pitch->clipped);
+        obuf[i++] = f;
+    }
 
     /* report... */
     *osamp = i;
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -535,15 +535,6 @@
 
 }
 
-static st_sample_t clipfloat(Float sample)
-{
-        if (sample > ST_SAMPLE_MAX)
-        return ST_SAMPLE_MAX;
-        if (sample < ST_SAMPLE_MIN)
-        return ST_SAMPLE_MIN;
-        return sample;
-}
-
 int st_poly_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
                  st_size_t *isamp, st_size_t *osamp)
 {
@@ -621,7 +612,12 @@
                 if (out_size > oskip + *osamp) out_size = oskip + *osamp;
 
     for(q=obuf, k=oskip; k < out_size; k++)
-      *q++ = clipfloat(out_buf[k] * ISCALE); /* should clip-limit */
+    {
+        float f;
+        f = out_buf[k] * ISCALE; /* should clip-limit */
+        ST_SAMPLE_CLIP(f, NULL);
+        *q++ = f;
+    }
 
                 *osamp = q-obuf;
                 rate->inpipe -= *osamp;
--- a/src/resample.c
+++ b/src/resample.c
@@ -357,13 +357,8 @@
                 // orig: *obuf++ = r->Y[i] * ISCALE;
                 Float ftemp = r->Y[i] * ISCALE;
 
-                if (ftemp > ST_SAMPLE_MAX)
-                        *obuf = ST_SAMPLE_MAX;
-                else if (ftemp < ST_SAMPLE_MIN)
-                        *obuf = ST_SAMPLE_MIN;
-                else
-                        *obuf = ftemp;
-                obuf++;
+                ST_SAMPLE_CLIP(ftemp, NULL);
+                *obuf++ = ftemp;
         }
 
         *isamp = Nx;
--- a/src/sox.c
+++ b/src/sox.c
@@ -703,16 +703,7 @@
                     {
                         double sample;
                         sample = efftab[0].obuf[s] + ibuf[f][s];
-                        if (sample < ST_SAMPLE_MIN)
-                        {
-                            sample = ST_SAMPLE_MIN;
-                            clipped++;
-                        }
-                        else if (sample > ST_SAMPLE_MAX)
-                        {
-                            sample = ST_SAMPLE_MAX;
-                            clipped++;
-                        }
+                        ST_SAMPLE_CLIP(sample, &clipped);
                         efftab[0].obuf[s] = sample;
                     }
             }
@@ -1508,14 +1499,7 @@
         top = buf+ct;
         while (p < top) {
             y = vol * *p;
-            if (y < ST_SAMPLE_MIN) {
-                y = ST_SAMPLE_MIN;
-                clips++;
-            }
-            else if (y > ST_SAMPLE_MAX) {
-                y = ST_SAMPLE_MAX;
-                clips++;
-            }
+            ST_SAMPLE_CLIP(y, &clips);
             *p++ = y;
         }
         return clips;
--- a/src/speed.c
+++ b/src/speed.c
@@ -92,23 +92,6 @@
     return ((a * x + b) * x + c) * x + d;
 }
 
-/* clip if necessary, and report. */
-static st_sample_t clip(speed_t speed, SPEED_FLOAT v)
-{
-    if (v < ST_SAMPLE_MIN)
-    {
-        speed->clipped++;
-        return ST_SAMPLE_MIN;
-    }
-    else if (v > ST_SAMPLE_MAX)
-    {
-        speed->clipped++;
-        return ST_SAMPLE_MAX;
-    }
-    else
-        return (st_sample_t) v;
-}
-
 /* get options. */
 int st_speed_getopts(eff_t effp, int n, char **argv)
 {
@@ -206,10 +189,15 @@
     for(i = 0;
         i<olen && speed->frac < ONE;
         i++, speed->frac += speed->rate)
-        obuf[i] = clip(speed, 
-                       cub(speed->cbuf[0], speed->cbuf[1],
-                           speed->cbuf[2], speed->cbuf[3], 
-                           speed->frac));
+    {
+        float f;
+
+        f = cub(speed->cbuf[0], speed->cbuf[1],
+                speed->cbuf[2], speed->cbuf[3], 
+                speed->frac);
+        ST_SAMPLE_CLIP(f, &speed->clipped);
+        obuf[i] = f;
+    }
     
     if (speed->frac >= ONE)
     {
--- a/src/st.h
+++ b/src/st.h
@@ -56,6 +56,30 @@
 #define ST_SAMPLE_TO_FLOAT_DWORD(d) ((float)(d/(ST_SAMPLE_FLOAT_SCALE)))
 #define ST_SAMPLE_TO_FLOAT_DDWORD(d) ((double)((double)d/(ST_SAMPLE_FLOAT_SCALE)))
 
+/* MACRO to clip a data type that is greater then st_sample_t to
+ * st_sample_t's limits; optionally incrementing clips if its a
+ * non-NULL pointer of type st_size_t.
+ */
+#define ST_SAMPLE_CLIP(samp, clips) \
+  do { \
+    if (samp > ST_SAMPLE_MAX) \
+      { samp = ST_SAMPLE_MAX; if (clips) (*(st_size_t *)clips)++; } \
+    else if (samp < ST_SAMPLE_MIN) \
+      { samp = ST_SAMPLE_MIN; if (clips) (*(st_size_t *)clips)++; } \
+  } while (0)
+
+/* MACRO to clip a normalized floating point data between 1.0 and -1.0
+ * to those limits.; optionally incrementing clips if its a
+ * non-NULL pointer of type st_size_t.
+ */
+#define ST_NORMALIZED_CLIP(samp, clips) \
+  do { \
+    if (samp > 1) \
+      { samp = 1; if (clips) (*(st_size_t *)clips)++; } \
+    else if (samp < -1) \
+      { samp = -1; if (clips) (*(st_size_t *)clips)++; } \
+  } while (0)
+
 /* Maximum value size type can hold. (Minimum is 0). */
 #define ST_SIZE_MAX 0xffffffffL
 
--- a/src/stretch.c
+++ b/src/stretch.c
@@ -103,26 +103,6 @@
 }
 */
 
-/* clip amplitudes and count number of clipped values.
- */
-static st_sample_t clip(stretch_t stretch, STRETCH_FLOAT v)
-{
-    if (v < ST_SAMPLE_MIN)
-    {
-        stretch->clipped++;
-        return ST_SAMPLE_MIN;
-    }
-    else if (v > ST_SAMPLE_MAX)
-    {
-        stretch->clipped++;
-        return ST_SAMPLE_MAX;
-    }
-    else
-    {
-        return (st_sample_t) v;
-    }
-}
-
 /*
  * Process options
  */
@@ -353,8 +333,12 @@
         if (stretch->state == output_state)
         {
             while (stretch->oindex<stretch->oshift && oindex<*osamp)
-                obuf[oindex++] = 
-                    clip(stretch, stretch->obuf[stretch->oindex++]);
+            {
+                float f;
+                f = stretch->obuf[stretch->oindex++];
+                ST_SAMPLE_CLIP(f, &stretch->clipped);
+                obuf[oindex++] = f;
+            }
 
             if (stretch->oindex >= stretch->oshift && oindex<*osamp)
             {
@@ -405,7 +389,13 @@
     if (stretch->state == output_state)
     {
         for (; oindex<*osamp && stretch->oindex<stretch->index;)
-            obuf[oindex++] = clip(stretch, stretch->obuf[stretch->oindex++]);
+        {
+            float f;
+
+            f = stretch->obuf[stretch->oindex++];
+            ST_SAMPLE_CLIP(f, &stretch->clipped);
+            obuf[oindex++] = f;
+        }
     }
     
     *osamp = oindex;
--- a/src/vol.c
+++ b/src/vol.c
@@ -133,26 +133,6 @@
     return ST_SUCCESS;
 }
 
-/* conversion. clipping could be smoother at high ends?
- * this could be a function on its own, with clip count and report
- * handled by eff_t and caller.
- */
-static st_sample_t clip(vol_t vol, const VOL_FLOAT v)
-{
-    if (v > ST_SAMPLE_MAX)
-    {
-         vol->clipped++;
-         return ST_SAMPLE_MAX;
-    }
-    else if (v < ST_SAMPLE_MIN)
-    {
-        vol->clipped++;
-        return ST_SAMPLE_MIN;
-    }
-    /* else */
-    return (st_sample_t) v;
-}
-
 #ifndef MIN
 #define MIN(s1,s2) ((s1)<(s2)?(s1):(s2))
 #endif
@@ -203,7 +183,8 @@
                         sample = gain * sample;
                 }
 
-                *obuf++ = clip(vol, sample);
+                ST_SAMPLE_CLIP(sample, vol->clipped);
+               *obuf++ = sample;
             }
     }
     else
@@ -210,7 +191,11 @@
     {
         /* quite basic, with clipping */
         for (;len>0; len--)
-                *obuf++ = clip(vol, gain * *ibuf++);
+        {
+                sample = gain * *ibuf++;
+                ST_SAMPLE_CLIP(sample, vol->clipped);
+                *obuf++ = sample;
+        }
     }
     return ST_SUCCESS;
 }