shithub: sox

Download patch

ref: d1d432ebe0152dd93f6b083b60e5f717e60a9685
parent: 537a028ea85b2f587a4e556b4520244e26128f8b
author: robs <robs>
date: Sat Nov 25 03:01:53 EST 2006

Improvements to clipping detection and reporting.

--- a/Changelog
+++ b/Changelog
@@ -45,6 +45,8 @@
   o Remove old, optional rate change and alaw/ulaw conversion code.
     (Reuben Thomas)
   o Make sox and soxmix a single binary.  (Reuben Thomas)
+  o Consistent (and hopefully complete) clipping detection and
+    reporting.  (robs)
 
 sox-12.18.2
 -----------
--- a/TODO
+++ b/TODO
@@ -2,9 +2,6 @@
 patches to cbagwell@users.sourceforge.net, or post them on the patches
 tracker at http://sf.net/projects/sox/.
 
-  o Change all calls to ST_SAMPLE_CLIP to use counters and report
-    clipping to user.
-
   o Update all read routines to be like WAV handler and only
     return data in multiples of sample_size*channels.  This
     will prevent corrupt files from causing sox to go into
--- /dev/null
+++ b/src/README
@@ -1,0 +1,58 @@
+Clipping Counting & Reporting Implementation Status 
+
+As of 24th Nov '06, this aspect of the implementation is
+believed to be complete.
+
+1st column: effect/format name
+2nd column: could clip (in theory)
+3rd column: CLIP_COUNT reporting implemented: yes, no, or (yes) custom
+
+avg		y	y
+band		n	n
+bass		y	y
+bandpass	n	y
+bandreject	see bandpass
+chorus		y	y
+compand		y	y
+copy		n	n
+dcshift		y	c
+deemph		n	n
+earwax		?	n
+echo		y	y
+echos		y	y
+equalizer	y	y
+fade		n	n
+filter		n	n
+flanger		y	y
+highp		n	y
+highpass	see bandpass
+lowp		n	y
+lowpass		see bandpass
+mask		n	n
+mcompand	y	y
+noiseprof	n	n
+noisered	n	y
+pan		n	y
+phaser		y	y
+pick		see avg
+pitch		y	y
+polyphase	y	y
+rate		n	n
+repeat		n	n
+resample	y	y
+reverb		y	y
+reverse		n	n
+silence		n	n
+speed		y	y
+stat		n	n
+stretch		y	y
+swap		n	n
+synth		n	n
+treble		see bass
+trim		n	n
+vibro		n	n
+vol		y	c
+
+-v		y	c
+
+dat		y	y
--- a/src/avg.c
+++ b/src/avg.c
@@ -527,7 +527,7 @@
             samp = 0.0;
             for (i = 0; i < ichan; i++)
                 samp += ibuf[i] * avg->sources[i][j];
-            ST_SAMPLE_CLIP(samp);
+            ST_EFF_SAMPLE_CLIP_COUNT(samp);
             obuf[j] = samp;
         }
     }
--- a/src/biquad.c
+++ b/src/biquad.c
@@ -14,19 +14,7 @@
     double o0 = *ibuf*p->b0 +p->i1*p->b1 +p->i2*p->b2 -p->o1*p->a1 -p->o2*p->a2;
     p->i2 = p->i1, p->i1 = *ibuf++;
     p->o2 = p->o1, p->o1 = o0;
-    *obuf++ = ST_ROUND_CLIP_COUNT(o0, p->clippedCount);
-  }
-  return ST_SUCCESS;
-}
-
-
-
-int st_biquad_stop(eff_t effp) /* Stop processing, warn if overflows */
-{
-  biquad_t p = (biquad_t) effp->priv;
-  if (p->clippedCount != 0)
-  {
-    st_warn("%s: %d samples clipped", effp->name, p->clippedCount);
+    *obuf++ = ST_EFF_ROUND_CLIP_COUNT(o0);
   }
   return ST_SUCCESS;
 }
--- a/src/biquad.h
+++ b/src/biquad.h
@@ -17,14 +17,10 @@
 
   st_sample_t i1, i2;      /* Filter memory */
   double o1, o2;           /* Filter memory */
-
-  unsigned clippedCount;
 } * biquad_t;
 
 int st_biquad_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf, 
                         st_size_t *isamp, st_size_t *osamp);
-
-int st_biquad_stop(eff_t effp);
 
 assert_static(sizeof(struct biquad) <= ST_MAX_EFFECT_PRIVSIZE, 
     /* else */ biquad_PRIVSIZE_too_big);
--- a/src/btrworth.c
+++ b/src/btrworth.c
@@ -111,7 +111,7 @@
     butterworth->y [1] = butterworth->y [0];
     butterworth->y [0] = out;
 
-    ST_SAMPLE_CLIP(out);
+    ST_EFF_SAMPLE_CLIP_COUNT(out);
 
     *obuf++ = out;
   }
--- a/src/chorus.c
+++ b/src/chorus.c
@@ -276,7 +276,7 @@
                         chorus->maxsamples] * chorus->decay[i];
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * chorus->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delay and input */
                 chorus->chorusbuf[chorus->counter] = d_in;
@@ -313,7 +313,7 @@
                 chorus->maxsamples] * chorus->decay[i];
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * chorus->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delay and input */
                 chorus->chorusbuf[chorus->counter] = d_in;
--- a/src/compand.c
+++ b/src/compand.c
@@ -320,7 +320,7 @@
       if (l->delay_buf_size <= 0)
       {
         checkbuf = ibuf[chan]*(outv/v)*l->outgain;
-        ST_SAMPLE_CLIP(checkbuf);
+        ST_EFF_SAMPLE_CLIP_COUNT(checkbuf);
         obuf[odone] = checkbuf;
 
         idone++;
@@ -332,7 +332,7 @@
         {
             l->delay_buf_full=1; //delay buffer is now definetly full
             checkbuf = l->delay_buf[l->delay_buf_ptr]*(outv/v)*l->outgain;
-            ST_SAMPLE_CLIP(checkbuf);
+            ST_EFF_SAMPLE_CLIP_COUNT(checkbuf);
             obuf[odone] = checkbuf;
 
             odone++;
--- a/src/dat.c
+++ b/src/dat.c
@@ -37,13 +37,6 @@
     char prevline[LINEWIDTH]; 
 } *dat_t;
 
-/* FIXME: Move this to misc.c */
-static st_sample_t roundoff(double x)
-{
-    if (x < 0.0) return(x - 0.5);
-    else return(x + 0.5);
-}
-
 int st_datstartread(ft_t ft)
 {
     char inpstr[LINEWIDTH];
@@ -136,9 +129,8 @@
           st_fail_errno(ft,ST_EOF,"Unable to read sample.");
           return (ST_EOF);
         }
-        sampval = roundoff(sampval * FLOATTOLONG);
-        ST_SAMPLE_CLIP(sampval);
-        *buf++ = sampval;
+        sampval *= FLOATTOLONG;
+        *buf++ = ST_ROUND_CLIP_COUNT(sampval, ft->clippedCount);
         done++;
       }
     }
--- a/src/echo.c
+++ b/src/echo.c
@@ -208,7 +208,7 @@
                 }
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * echo->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Store input in delay buffer */
                 echo->delay_buf[echo->counter] = d_in;
@@ -242,7 +242,7 @@
                 }
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * echo->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Store input in delay buffer */
                 echo->delay_buf[echo->counter] = d_in;
--- a/src/echos.c
+++ b/src/echos.c
@@ -198,7 +198,7 @@
                 }
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * echos->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delays and input */
                 for ( j = 0; j < echos->num_delays; j++ ) {
@@ -238,7 +238,7 @@
                 }
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * echos->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delays and input */
                 for ( j = 0; j < echos->num_delays; j++ ) {
--- a/src/equalizer.c
+++ b/src/equalizer.c
@@ -173,13 +173,7 @@
            );
     eq->y[0] = out;
 
-    if (out < ST_SAMPLE_MIN) {
-      out = ST_SAMPLE_MIN;
-    }
-    else if (out > ST_SAMPLE_MAX) {
-      out = ST_SAMPLE_MAX;
-    }
-
+    ST_EFF_SAMPLE_CLIP_COUNT(out);
     *obuf++ = out;
   }
 
--- a/src/flanger.c
+++ b/src/flanger.c
@@ -227,7 +227,7 @@
         flanger->maxsamples] * flanger->decay;
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * flanger->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delay and input */
                 flanger->flangerbuf[flanger->counter] = d_in;
@@ -260,7 +260,7 @@
         flanger->maxsamples] * flanger->decay;
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_out * flanger->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delay and input */
                 flanger->flangerbuf[flanger->counter] = d_in;
--- a/src/highp.c
+++ b/src/highp.c
@@ -115,7 +115,7 @@
                 d = highp->A0 * l + 
                     highp->A1 * highp->inm1 + 
                     highp->B1 * highp->outm1;
-                ST_SAMPLE_CLIP(d);
+                ST_EFF_SAMPLE_CLIP_COUNT(d);
                 highp->inm1 = l;
                 highp->outm1 = d;
                 *obuf++ = d;
--- a/src/lowp.c
+++ b/src/lowp.c
@@ -109,7 +109,7 @@
         for(done = 0; done < len; done++) {
                 l = *ibuf++;
                 d = lowp->A * l + lowp->B * lowp->outm1;
-                ST_SAMPLE_CLIP(d);
+                ST_EFF_SAMPLE_CLIP_COUNT(d);
                 lowp->outm1 = d;
                 *obuf++ = d;
         }
--- a/src/mcompand.c
+++ b/src/mcompand.c
@@ -132,7 +132,7 @@
   return (ST_SUCCESS);
 }
 
-static int lowpass_flow(butterworth_crossover_t butterworth, int nChan, st_sample_t *ibuf, st_sample_t *lowbuf, st_sample_t *highbuf,
+static int lowpass_flow(eff_t effp, butterworth_crossover_t butterworth, int nChan, st_sample_t *ibuf, st_sample_t *lowbuf, st_sample_t *highbuf,
                          int len) {
   int chan;
   double in, out;
@@ -168,7 +168,7 @@
       butterworth->xy_low[chan].y [1] = butterworth->xy_low[chan].y [0];
       butterworth->xy_low[chan].y [0] = out;
 
-      ST_SAMPLE_CLIP(out);
+      ST_EFF_SAMPLE_CLIP_COUNT(out);
 
       *lowbufptr = out;
 
@@ -185,7 +185,7 @@
       butterworth->xy_high[chan].y [1] = butterworth->xy_high[chan].y [0];
       butterworth->xy_high[chan].y [0] = out;
 
-      ST_SAMPLE_CLIP(out);
+      ST_EFF_SAMPLE_CLIP_COUNT(out);
 
       /* don't forget polarity reversal of high pass! */
 
@@ -600,7 +600,7 @@
     l = &c->bands[band];
 
     if (l->topfreq)
-      lowpass_flow(&l->filter, effp->outinfo.channels, abuf, bbuf, cbuf, len);
+      lowpass_flow(effp, &l->filter, effp->outinfo.channels, abuf, bbuf, cbuf, len);
     else {
       bbuf = abuf;
       abuf = cbuf;
@@ -611,7 +611,7 @@
     for (i=0;i<len;++i)
     {
       out = obuf[i] + abuf[i];
-      ST_SAMPLE_CLIP(out);
+      ST_EFF_SAMPLE_CLIP_COUNT(out);
       obuf[i] = out;
     }
     oldabuf = abuf;
@@ -624,7 +624,7 @@
   return ST_SUCCESS;
 }
 
-static int st_mcompand_drain_1(compand_t c, comp_band_t l, st_sample_t *obuf, int maxdrain, int band)
+static int st_mcompand_drain_1(eff_t effp, compand_t c, comp_band_t l, st_sample_t *obuf, int maxdrain, int band)
 {
   int done;
   double out;
@@ -634,7 +634,7 @@
    */
   for (done = 0;  done < maxdrain  &&  l->delay_buf_cnt > 0;  done++) {
     out = obuf[done] + l->delay_buf[l->delay_buf_ptr++];
-    ST_SAMPLE_CLIP(out);
+    ST_EFF_SAMPLE_CLIP_COUNT(out);
     obuf[done] = out;
     l->delay_buf_ptr %= c->delay_buf_size;
     l->delay_buf_cnt--;
@@ -657,7 +657,7 @@
   memset(obuf,0,*osamp * sizeof *obuf);
   for (band=0;band<c->nBands;++band) {
     l = &c->bands[band];
-    drained = st_mcompand_drain_1(c,l,obuf,*osamp,0);
+    drained = st_mcompand_drain_1(effp, c,l,obuf,*osamp,0);
     if (drained > mostdrained)
       mostdrained = drained;
   }
--- a/src/misc.c
+++ b/src/misc.c
@@ -436,16 +436,6 @@
     srand(t);
 }
 
-st_sample_t st_clip24(st_sample_t l)
-{
-    if (l >= ((st_sample_t)1 << 23))
-        return ((st_sample_t)1 << 23) - 1;
-    else if (l <= -((st_sample_t)1 << 23))
-        return -((st_sample_t)1 << 23) + 1;
-    else
-        return l;
-}
-
 /* This was very painful.  We need a sine library. */
 
 void st_sine(int *buf, st_ssize_t len, int max, int depth)
--- a/src/noisered.c
+++ b/src/noisered.c
@@ -208,7 +208,7 @@
 
 /* Do window management once we have a complete window, including mangling
  * the current window. */
-static int process_window(reddata_t data, int chan_num, int num_chans,
+static int process_window(eff_t effp, reddata_t data, int chan_num, int num_chans,
                           st_sample_t *obuf, int len) {
     int j;
     float* nextwindow;
@@ -215,7 +215,6 @@
     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,
@@ -226,13 +225,7 @@
     if (!first) {
         for (j = 0; j < use; j ++) {
             float s = chan->window[j] + chan->lastwindow[WINDOWSIZE/2 + j];
-            ST_NORMALIZED_CLIP_COUNT(s, clipped);
-            if (clipped)
-            {
-                /* Reset for future tests. */
-                clipped = 0;
-                st_warn("noisered: Output clipped to %f.\n", s);
-            }
+            ST_EFF_NORMALIZED_CLIP_COUNT(s);
             obuf[chan_num + num_chans * j] =
                 ST_FLOAT_DWORD_TO_SAMPLE(s);
         }
@@ -288,7 +281,7 @@
         if (!whole_window)
             continue;
         else {
-            process_window(data, i, tracks, obuf, oldbuf + ncopy);
+            process_window(effp, data, i, tracks, obuf, oldbuf + ncopy);
         }
     }
     
@@ -312,7 +305,7 @@
     int i;
     int tracks = effp->ininfo.channels;
     for (i = 0; i < tracks; i ++) {
-        *osamp = process_window(data, i, tracks, obuf, data->bufdata);
+        *osamp = process_window(effp, data, i, tracks, obuf, data->bufdata);
     }
     /* FIXME: This is very picky.  osamp needs to be big enough to get all
      * remaining data or it will be discarded.
--- a/src/pan.c
+++ b/src/pan.c
@@ -49,7 +49,6 @@
 
     /* local data
      */
-    int clipped;   /* number of clipped values */
 } * pan_t;
 
 /*
@@ -60,7 +59,6 @@
     pan_t pan = (pan_t) effp->priv; 
     
     pan->dir = ZERO; /* default is no change */
-    pan->clipped = 0;
     
     if (n && (!sscanf(argv[0], PAN_FLOAT_SCAN, &pan->dir) || 
               pan->dir < MONE || pan->dir > ONE))
@@ -134,7 +132,7 @@
             {
                 float f;
                 f = HALF*ibuf[0] + HALF*ibuf[1];
-                ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                ST_EFF_SAMPLE_CLIP_COUNT(f);
                 *obuf++ = f;
                 ibuf += 2;
             }
@@ -145,7 +143,7 @@
                 float f;
                 f = QUARTER*ibuf[0] + QUARTER*ibuf[1] + 
                         QUARTER*ibuf[2] + QUARTER*ibuf[3];
-                ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                ST_EFF_SAMPLE_CLIP_COUNT(f);
                 *obuf++ = f;
                 ibuf += 4;
             }
@@ -163,10 +161,10 @@
                 float f;
 
                 f = left * ibuf[0];
-                ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                ST_EFF_SAMPLE_CLIP_COUNT(f);
                 obuf[0] = f;
                 f = right * ibuf[0];
-                ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                ST_EFF_SAMPLE_CLIP_COUNT(f);
                 obuf[1] = f;
                 obuf += 2;
                 ibuf++;
@@ -189,10 +187,10 @@
                     float f;
 
                     f = cll * ibuf[0] + clr * ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[0] = f;
                     f = cr * ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[1] = f;
                     obuf += 2;
                     ibuf += 2;
@@ -212,10 +210,10 @@
                     float f;
 
                     f = cl * ibuf[0];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[0] = f;
                     f = crl * ibuf[0] + crr * ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[1] = f;
                     obuf += 2;
                     ibuf += 2;
@@ -242,10 +240,10 @@
 
                     /* pan it */
                     f = cll * ibuf0 + clr * ibuf1;
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[0] = f;
                     f = cr * ibuf1;
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[1] = f;
                     obuf += 2;
                     ibuf += 4;
@@ -268,10 +266,10 @@
                     ibuf1 = HALF*ibuf[1] + HALF*ibuf[3];
 
                     f = cl * ibuf0;
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[0] = f;
                     f = crl * ibuf0 + crr * ibuf1;
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[1] = f;
                     obuf += 2;
                     ibuf += 4;
@@ -297,10 +295,10 @@
                     float f;
 
                     f = cl * ibuf[0];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[2] = obuf[0] = f;
                     f = cr * ibuf[0];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     ibuf[3] = obuf[1] = f;
                     obuf += 4;
                     ibuf++;
@@ -322,10 +320,10 @@
                     float f;
 
                     f = cll * ibuf[0] + clr * ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[2] = obuf[0] = f;
                     f = cr * ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     ibuf[3] = obuf[1] = f;
                     obuf += 4;
                     ibuf += 2;
@@ -345,10 +343,10 @@
                     float f;
 
                     f = cl * ibuf[0];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[2] = obuf[0] =f ;
                     f = crl * ibuf[0] + crr * ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     ibuf[3] = obuf[1] = f;
                     obuf += 4;
                     ibuf += 2;
@@ -371,16 +369,16 @@
                     float f;
 
                     f = cown*ibuf[0] + cright*ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[0] = f;
                     f = cown*ibuf[1] + cright*ibuf[3];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[1] = f;
                     f = cown*ibuf[2] + cright*ibuf[0];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[2] = f;
                     f = cown*ibuf[3] + cright*ibuf[2];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[3] = f;
                     obuf += 4;
                     ibuf += 4;              
@@ -398,16 +396,16 @@
                     float f;
 
                     f = cleft*ibuf[2] + cown*ibuf[0];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[0] = f;
                     f = cleft*ibuf[0] + cown*ibuf[1];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[1] = f;
                     f = cleft*ibuf[3] + cown*ibuf[2];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[2] = f;
                     f = cleft*ibuf[1] + cown*ibuf[3];
-                    ST_SAMPLE_CLIP_COUNT(f, pan->clipped);
+                    ST_EFF_SAMPLE_CLIP_COUNT(f);
                     obuf[3] = f;
                     obuf += 4;
                     ibuf += 4;
@@ -435,11 +433,6 @@
  */
 int st_pan_stop(eff_t effp)
 {
-    pan_t pan = (pan_t) effp->priv;
-    if (pan->clipped) {
-        st_warn("PAN clipped %d values, maybe adjust volume?",
-             pan->clipped);
-    }
     return ST_SUCCESS;
 }
 
--- a/src/phaser.c
+++ b/src/phaser.c
@@ -214,7 +214,7 @@
         phaser->maxsamples] * phaser->decay * -1.0;
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_in * phaser->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delay and input */
                 phaser->phaserbuf[phaser->counter] = d_in;
@@ -247,7 +247,7 @@
         phaser->maxsamples] * phaser->decay * -1.0;
                 /* Adjust the output volume and size to 24 bit */
                 d_out = d_in * phaser->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 /* Mix decay of delay and input */
                 phaser->phaserbuf[phaser->counter] = d_in;
--- a/src/pitch.c
+++ b/src/pitch.c
@@ -130,8 +130,6 @@
 
     pitch_state_t state; /* buffer management status. */
 
-    int clipped;         /* number of clipped values (i.e. overflows) */
-
 } * pitch_t;
 
 /* // debug functions
@@ -348,8 +346,6 @@
         return ST_EOF;
     }
 
-    pitch->clipped = 0;
-
     return ST_SUCCESS;
 }
 
@@ -467,8 +463,6 @@
         return ST_EOF;
     }
 
-    pitch->clipped = 0;
-
     return ST_SUCCESS;
 }
 
@@ -525,7 +519,7 @@
                 float f;
 
                 f = pitch->acc[pitch->iacc++];
-                ST_SAMPLE_CLIP_COUNT(f, pitch->clipped);
+                ST_EFF_SAMPLE_CLIP_COUNT(f);
                 obuf[oindex++] = f;
             }
 
@@ -578,7 +572,7 @@
         float f;
 
         f = pitch->acc[pitch->iacc++];
-        ST_SAMPLE_CLIP_COUNT(f, pitch->clipped);
+        ST_EFF_SAMPLE_CLIP_COUNT(f);
         obuf[i++] = f;
     }
 
@@ -603,10 +597,6 @@
     free(pitch->tmp);
     free(pitch->acc);
     free(pitch->buf);
-
-    if (pitch->clipped)
-        st_warn("PITCH clipped %d values... adjust volume with -v option maybe?", 
-             pitch->clipped);
 
     return ST_SUCCESS;
 }
--- a/src/polyphas.c
+++ b/src/polyphas.c
@@ -615,7 +615,7 @@
     {
         float f;
         f = out_buf[k] * ISCALE; /* should clip-limit */
-        ST_SAMPLE_CLIP(f);
+        ST_EFF_SAMPLE_CLIP_COUNT(f);
         *q++ = f;
     }
 
--- a/src/resample.c
+++ b/src/resample.c
@@ -359,7 +359,7 @@
                 // orig: *obuf++ = r->Y[i] * ISCALE;
                 Float ftemp = r->Y[i] * ISCALE;
 
-                ST_SAMPLE_CLIP(ftemp);
+                ST_EFF_SAMPLE_CLIP_COUNT(ftemp);
                 *obuf++ = ftemp;
         }
 
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -229,7 +229,7 @@
                         d_in +=
 reverb->reverbbuf[(i + reverb->maxsamples - reverb->samples[j]) % reverb->maxsamples] * reverb->decay[j];
                 d_out = d_in * reverb->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 *obuf++ = out * 256;
                 reverb->reverbbuf[i] = d_in;
                 i++;            /* XXX need a % maxsamples here ? */
@@ -261,10 +261,10 @@
                         d_in += 
 reverb->reverbbuf[(i + reverb->maxsamples - reverb->samples[j]) % reverb->maxsamples] * reverb->decay[j];
                 d_out = d_in * reverb->out_gain;
-                out = st_clip24((st_sample_t) d_out);
+                out = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_out);
                 obuf[done++] = out * 256;
                 reverb->reverbbuf[i] = d_in;
-                l = st_clip24((st_sample_t) d_in);
+                l = ST_EFF_24BIT_CLIP_COUNT((st_sample_t) d_in);
                 reverb->pppl = reverb->ppl;
                 reverb->ppl = reverb->pl;
                 reverb->pl = l;
--- a/src/sox.c
+++ b/src/sox.c
@@ -848,6 +848,11 @@
 
     for (f = 0; f < input_count; f++)
     {
+        if (file_desc[f]->clippedCount != 0)
+        {
+          st_warn("%s: %u values clipped on input", file_desc[f]->filename, file_desc[f]->clippedCount);
+        }
+
         /* If problems closing input file, just warn user since
          * we are exiting anyways.
          */
@@ -1130,11 +1135,15 @@
     int e, ret = ST_SUCCESS;
 
     for(e = 1; e < neffects; e++) {
+        efftab[e].clippedCount = 0;
         if ((ret = (*efftab[e].h->start)(&efftab[e])) == ST_EOF)
             break;
         if (efftabR[e].name)
+        {
+            efftabR[e].clippedCount = 0;
             if ((ret = (*efftabR[e].h->start)(&efftabR[e])) == ST_EOF)
                 break;
+        }
     }
 
     return ret;
@@ -1563,9 +1572,18 @@
     int e;
 
     for (e = 1; e < neffects; e++) {
+        st_size_t clippedCount;
         (*efftab[e].h->stop)(&efftab[e]);
+        clippedCount = efftab[e].clippedCount;
         if (efftabR[e].name)
+        {
             (* efftabR[e].h->stop)(&efftabR[e]);
+            clippedCount += efftab[e].clippedCount;
+        }
+        if (clippedCount != 0)
+        {
+          st_warn("%s: %u values clipped, maybe adjust volume?", efftab[e].name, clippedCount);
+        }
     }
 }
 
--- a/src/speed.c
+++ b/src/speed.c
@@ -47,8 +47,6 @@
 
     /* internals.
      */
-    int clipped;          /* number of clipped values to report */
-
     SPEED_FLOAT rate;     /* rate of buffer sweep */
 
     int compression;      /* integer compression of the signal. */
@@ -126,7 +124,6 @@
 int st_speed_start(eff_t effp)
 {
     speed_t speed = (speed_t) effp->priv;
-    speed->clipped = 0;
 
     if (speed->factor >= ONE)
     {
@@ -178,7 +175,7 @@
 
 /* interpolate values
  */
-static st_size_t compute(speed_t speed, st_sample_t *obuf, st_size_t olen)
+static st_size_t compute(eff_t effp, speed_t speed, st_sample_t *obuf, st_size_t olen)
 {
     st_size_t i;
 
@@ -191,7 +188,7 @@
         f = cub(speed->cbuf[0], speed->cbuf[1],
                 speed->cbuf[2], speed->cbuf[3], 
                 speed->frac);
-        ST_SAMPLE_CLIP_COUNT(f, speed->clipped);
+        ST_EFF_SAMPLE_CLIP_COUNT(f);
         obuf[i] = f;
     }
     
@@ -238,7 +235,7 @@
 
         /* compute interpolation. */
         if (speed->state==sp_compute)
-            oindex += compute(speed, obuf+oindex, len-oindex);
+            oindex += compute(effp, speed, obuf+oindex, len-oindex);
     }
 
     *isamp = iindex;
@@ -273,7 +270,7 @@
 
         /* compute interpolation. */
         if (speed->state==sp_compute)
-            oindex += compute(speed, obuf+oindex, *osamp-oindex);
+            oindex += compute(effp, speed, obuf+oindex, *osamp-oindex);
     }
 
     *osamp = oindex; /* report how much was generated. */
@@ -289,9 +286,6 @@
 int st_speed_stop(eff_t effp)
 {
     speed_t speed = (speed_t) effp->priv;
-
-    if (speed->clipped) 
-        st_report("SPEED: %d values clipped...", speed->clipped);
 
     free(speed->ibuf);
     
--- a/src/st.h
+++ b/src/st.h
@@ -83,17 +83,6 @@
 #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.
- */
-#define ST_SAMPLE_CLIP(samp) \
-  do { \
-    if (samp > ST_SAMPLE_MAX) \
-      { samp = ST_SAMPLE_MAX; } \
-    else if (samp < ST_SAMPLE_MIN) \
-      { samp = ST_SAMPLE_MIN; } \
-  } while (0)
-
-/* MACRO to clip a data type that is greater then st_sample_t to
  * st_sample_t's limits and increment a counter if clipping occurs..
  */
 #define ST_SAMPLE_CLIP_COUNT(samp, clips) \
@@ -108,9 +97,16 @@
  * and increment a counter if clipping occurs.
  */
 #define ST_ROUND_CLIP_COUNT(d, clips) \
-  (d < 0? d <= ST_SAMPLE_MIN - 0.5? ++clips, ST_SAMPLE_MIN: d - 0.5 \
-        : d >= ST_SAMPLE_MAX + 0.5? ++clips, ST_SAMPLE_MAX: d + 0.5)
+  ((d) < 0? (d) <= ST_SAMPLE_MIN - 0.5? ++(clips), ST_SAMPLE_MIN: (d) - 0.5 \
+        : (d) >= ST_SAMPLE_MAX + 0.5? ++(clips), ST_SAMPLE_MAX: (d) + 0.5)
 
+/* Rvalue MACRO to clip a st_sample_t to 24 bits,
+ * and increment a counter if clipping occurs.
+ */
+#define ST_24BIT_CLIP_COUNT(l, clips) \
+  ((l) >= ((st_sample_t)1 << 23)? ++(clips), ((st_sample_t)1 << 23) - 1 : \
+   (l) <=-((st_sample_t)1 << 23)? ++(clips),-((st_sample_t)1 << 23) + 1 : (l))
+
 /* MACRO to clip a normalized floating point data between 1.0 and -1.0
  * to those limits and increment a counter when clipping occurs.
  */
@@ -122,6 +118,12 @@
       { samp = -1; clips++; } \
   } while (0)
 
+/* MACROs for effects where standard clip counting and reporting is used. */
+#define ST_EFF_SAMPLE_CLIP_COUNT(s) ST_SAMPLE_CLIP_COUNT(s, effp->clippedCount)
+#define ST_EFF_24BIT_CLIP_COUNT(s) ST_24BIT_CLIP_COUNT(s, effp->clippedCount)
+#define ST_EFF_ROUND_CLIP_COUNT(s) ST_ROUND_CLIP_COUNT(s, effp->clippedCount)
+#define ST_EFF_NORMALIZED_CLIP_COUNT(s) ST_NORMALIZED_CLIP_COUNT(s, effp->clippedCount)
+
 /* Maximum value size type can hold. (Minimum is 0). */
 #define ST_SIZE_MAX 0xffffffffL
 
@@ -227,6 +229,7 @@
     char            mode;                 /* read or write mode */
     /* Total samples per channel of file.  Zero if unknown. */
     st_size_t       length;    
+    st_size_t       clippedCount;         /* increment if clipping occurs */
     char            *filename;            /* file name */
     char            *filetype;            /* type of file */
     char            *comment;             /* comment string */
@@ -319,6 +322,7 @@
     const st_effect_t *h;           /* effects driver */
     st_sample_t     *obuf;          /* output buffer */
     st_size_t       odone, olen;    /* consumed, total length */
+    st_size_t       clippedCount;   /* increment if clipping occurs */
     /* The following is a portable trick to align this variable on
      * an 8-byte bounder.  Once this is done, the buffer alloced
      * after it should be align on an 8-byte boundery as well.
--- a/src/st_i.h
+++ b/src/st_i.h
@@ -38,7 +38,6 @@
 #endif
 
 /* declared in misc.c */
-st_sample_t st_clip24(st_sample_t) REGPARM(1);
 void st_sine(int *buf, st_ssize_t len, int max, int depth);
 void st_triangle(int *buf, st_ssize_t len, int max, int depth);
 
--- a/src/stretch.c
+++ b/src/stretch.c
@@ -68,7 +68,6 @@
     /* internal stuff 
      */
     stretch_status_t state; /* automaton status */
-    int clipped;            /* number of clipped values. */
 
     int size;               /* buffer size */
     int index;              /* next available element */
@@ -206,7 +205,6 @@
     }
 
     stretch->state = input_state;
-    stretch->clipped = 0;
 
     stretch->size = (int)(effp->outinfo.rate * ONETHOUSANDS * stretch->window);
     /* start in the middle of an input to avoid initial fading... */
@@ -337,7 +335,7 @@
             {
                 float f;
                 f = stretch->obuf[stretch->oindex++];
-                ST_SAMPLE_CLIP_COUNT(f, stretch->clipped);
+                ST_EFF_SAMPLE_CLIP_COUNT(f);
                 obuf[oindex++] = f;
             }
 
@@ -392,7 +390,7 @@
         float f;
 
         f = stretch->obuf[stretch->oindex++];
-        ST_SAMPLE_CLIP_COUNT(f, stretch->clipped);
+        ST_EFF_SAMPLE_CLIP_COUNT(f);
         obuf[oindex++] = f;
     }
     
@@ -416,9 +414,6 @@
     free(stretch->ibuf);
     free(stretch->obuf);
     free(stretch->fbuf);
-
-    if (stretch->clipped)
-        st_warn("STRETCH clipped %d values...", stretch->clipped);
 
     return ST_SUCCESS;
 }
--- a/src/tone.c
+++ b/src/tone.c
@@ -156,7 +156,7 @@
   st_biquad_shelf_start,
   st_biquad_flow,
   st_effect_nothing_drain,
-  st_biquad_stop
+  st_effect_nothing
 };
 
 
@@ -176,7 +176,7 @@
   st_biquad_shelf_start,
   st_biquad_flow,
   st_effect_nothing_drain,
-  st_biquad_stop
+  st_effect_nothing
 };