shithub: sox

Download patch

ref: 1eb8255cb0bdaff1d8f96abbfdec315c474569b5
parent: b5a13b5234c36fe40fae0db86b58d43ef94499e3
author: robs <robs>
date: Wed Oct 24 17:10:58 EDT 2007

more changes for reverb

--- a/soxeffect.7
+++ b/soxeffect.7
@@ -753,13 +753,13 @@
 To be precise, this is done when both input-rate < output-rate, and
 output-rate \(di gcd(input-rate, output-rate) \(<= 511.
 .TP
-\fBreverb [\fB-w\fR|\fB--wet-only\fR] [\fIreverberance\fR (50%) [\fIHF-damping\fR (50%)
+\fBreverb\fR [\fB-w\fR|\fB--wet-only\fR] [\fIreverberance\fR (50%) [\fIHF-damping\fR (50%)
 [\fIroom-scale\fR (100%) [\fIstereo-depth\fR (100%)
 .br
 [\fIpre-delay\fR (0ms) [\fIwet-gain\fR (0dB)]]]]]]
 .SP
 Add reverberation to the audio using the freeverb algorithm.
-Default values shown in parenthesis.
+Default values are shown in parenthesis.
 .TP
 \fBreverse\fR
 Reverse the audio completely.
--- a/soxexam.7
+++ b/soxexam.7
@@ -190,50 +190,24 @@
 .SP
 	play file.xxx flanger triangle
 .SS Reverb
-The reverb effect is often used in audience hall which are to small or contain
-too many many visitors which disturb (dampen) the reflection of sound at
-the walls.  Reverb will make the sound be perceived as if it were in
-a large hall.  You can try the reverb effect in your bathroom or garage or
-sport hall by shouting loud some words. You'll hear the words reflected from
-the walls.
+A reverberation effect is sometimes needed in concert halls that are too
+small or contain so many people that the hall's natural reverberance is
+diminished.
 .SP
-The biggest problem in using the reverb effect is the correct setting of the
-(wall) delays such that the sound is realistic and doesn't sound like music
-playing in a tin can or has overloaded feedback which destroys any illusion
-of playing in a big hall.
-To help you obtain realistic reverb effects, you should decide first how
-long the reverb should take place until it is not loud enough to be registered
-by your ears. This is be done by varying the reverb time `t'.  To simulate
-small halls, use 200ms.  To simulate large halls, use 1000ms.  Clearly,
-the walls of such a hall aren't far
-away, so you should define its setting be given every wall its delay time.
-However, if the wall is to far away for the reverb time, you won't hear the
-reverb, so the nearest wall will be best at `t/4' delay and the farthest
-at `t/2'. You can try other distances as well, but it won't sound very realistic.
-The walls shouldn't stand to close to each other and not in a multiple integer
-distance to each other ( so avoid wall like: 200 and 202, or something
-like 100 and 200 ).
+Using the effect is easy:
+.EX
+	play file.xxx reverb
+.EE
+gives the default reverberance (50%); or specify the desired reverberance
+as a percentage:
+.EX
+	play file.xxx reverb 80
+.EE
+For fine tuning, see
+.BR sox (1).
 .SP
-Since audience halls do have a lot of walls, we will start designing one
-beginning with one wall:
-.SP
-	play file.xxx reverb 1 600 180
-.SP
-One wall more:
-.SP
-	play file.xxx reverb 1 600 180 200
-.SP
-Next two walls:
-.SP
-	play file.xxx reverb 1 600 180 200 220 240
-.SP
-Now, why not a futuristic hall with six walls:
-.SP
-	play file.xxx reverb 1 600 180 200 220 240 280 300
-.SP
 If you run out of machine power or memory, then stop as many applications
-as possible (every interrupt will consume a lot of CPU time which for
-bigger halls is absolutely necessary).
+as possible.
 .SS Phaser
 The phaser effect is like the flanger effect, but it uses a reverb instead of
 an echo and does phase shifting. You'll hear the difference in the examples
--- a/src/effects.c
+++ b/src/effects.c
@@ -30,7 +30,9 @@
 #define sox_fail sox_globals.subsystem=effp->handler.name,sox_fail
 #define sox_report sox_globals.subsystem=effp->handler.name,sox_report
 
+#define DEBUG_EFFECTS_CHAIN 0
 
+
 sox_effects_globals_t sox_effects_globals =
     {sox_plot_off, 1, &sox_globals};
 
@@ -170,17 +172,21 @@
   int effstatus = SOX_SUCCESS;
   sox_size_t i, f;
   const sox_ssample_t *ibuf;
-  sox_size_t idone = effp1->olen - effp1->odone;
-  sox_size_t odone = sox_globals.bufsiz - effp->olen;
+  sox_size_t idone = effp1->oend - effp1->obeg;
+  sox_size_t obeg = sox_globals.bufsiz - effp->oend;
+#if DEBUG_EFFECTS_CHAIN
+  sox_size_t pre_idone = idone;
+  sox_size_t pre_odone = obeg;
+#endif
 
   if (effp->flows == 1)       /* Run effect on all channels at once */
-    effstatus = effp->handler.flow(effp, &effp1->obuf[effp1->odone],
-                                   &effp->obuf[effp->olen], &idone, &odone);
+    effstatus = effp->handler.flow(effp, &effp1->obuf[effp1->obeg],
+                                   &effp->obuf[effp->oend], &idone, &obeg);
   else {                 /* Run effect on each channel individually */
-    sox_ssample_t *obuf = &effp->obuf[effp->olen];
+    sox_ssample_t *obuf = &effp->obuf[effp->oend];
     sox_size_t idone_last, odone_last;
 
-    ibuf = &effp1->obuf[effp1->odone];
+    ibuf = &effp1->obuf[effp1->obeg];
     for (i = 0; i < idone; i += effp->flows)
       for (f = 0; f < effp->flows; ++f)
         chain->ibufc[f][i / effp->flows] = *ibuf++;
@@ -187,7 +193,7 @@
 
     for (f = 0; f < effp->flows; ++f) {
       sox_size_t idonec = idone / effp->flows;
-      sox_size_t odonec = odone / effp->flows;
+      sox_size_t odonec = obeg / effp->flows;
       int eff_status_c = effp->handler.flow(&chain->effects[n][f],
           chain->ibufc[f], chain->obufc[f], &idonec, &odonec);
       if (f && (idonec != idone_last || odonec != odone_last)) {
@@ -206,18 +212,21 @@
         *obuf++ = chain->obufc[f][i];
 
     idone = f * idone_last;
-    odone = f * odone_last;
+    obeg = f * odone_last;
   }
-  effp1->odone += idone;
-  if (effp1->odone == effp1->olen)
-    effp1->odone = effp1->olen = 0;
-  else if (effp1->olen - effp1->odone < effp->imin ) { /* Need to refill? */
-    memmove(effp1->obuf, &effp1->obuf[effp1->odone], (effp1->olen - effp1->odone) * sizeof(*effp1->obuf));
-    effp1->olen -= effp1->odone;
-    effp1->odone = 0;
+#if DEBUG_EFFECTS_CHAIN
+  sox_report("flow:  %5u%5u%5u%5u", pre_idone, pre_odone, idone, obeg);
+#endif
+  effp1->obeg += idone;
+  if (effp1->obeg == effp1->oend)
+    effp1->obeg = effp1->oend = 0;
+  else if (effp1->oend - effp1->obeg < effp->imin ) { /* Need to refill? */
+    memmove(effp1->obuf, &effp1->obuf[effp1->obeg], (effp1->oend - effp1->obeg) * sizeof(*effp1->obuf));
+    effp1->oend -= effp1->obeg;
+    effp1->obeg = 0;
   }
 
-  effp->olen += odone;
+  effp->oend += obeg;
 
   return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF;
 }
@@ -228,16 +237,19 @@
   sox_effect_t * effp = &chain->effects[n][0];
   int effstatus = SOX_SUCCESS;
   sox_size_t i, f;
-  sox_size_t odone = sox_globals.bufsiz - effp->olen;
+  sox_size_t obeg = sox_globals.bufsiz - effp->oend;
+#if DEBUG_EFFECTS_CHAIN
+  sox_size_t pre_odone = obeg;
+#endif
 
   if (effp->flows == 1)   /* Run effect on all channels at once */
-    effstatus = effp->handler.drain(effp, &effp->obuf[effp->olen], &odone);
+    effstatus = effp->handler.drain(effp, &effp->obuf[effp->oend], &obeg);
   else {                         /* Run effect on each channel individually */
-    sox_ssample_t *obuf = &effp->obuf[effp->olen];
+    sox_ssample_t *obuf = &effp->obuf[effp->oend];
     sox_size_t odone_last;
 
     for (f = 0; f < effp->flows; ++f) {
-      sox_size_t odonec = odone / effp->flows;
+      sox_size_t odonec = obeg / effp->flows;
       int eff_status_c = effp->handler.drain(&chain->effects[n][f], chain->obufc[f], &odonec);
       if (f && (odonec != odone_last)) {
         sox_fail("drained asymmetrically!");
@@ -252,12 +264,15 @@
     for (i = 0; i < odone_last; ++i)
       for (f = 0; f < effp->flows; ++f)
         *obuf++ = chain->obufc[f][i];
-    odone = f * odone_last;
+    obeg = f * odone_last;
   }
-  if (!odone)   /* This is the only thing that drain has and flow hasn't */
+#if DEBUG_EFFECTS_CHAIN
+  sox_report("drain: %5u%5u%5u%5u", 0, pre_odone, 0, obeg);
+#endif
+  if (!obeg)   /* This is the only thing that drain has and flow hasn't */
     effstatus = SOX_EOF;
 
-  effp->olen += odone;
+  effp->oend += obeg;
 
   return effstatus == SOX_SUCCESS? SOX_SUCCESS : SOX_EOF;
 }
@@ -272,7 +287,7 @@
 
   for (e = 0; e < chain->length; ++e) {
     chain->effects[e][0].obuf = xmalloc(sox_globals.bufsiz * sizeof(chain->effects[e][0].obuf[0]));
-    chain->effects[e][0].odone = chain->effects[e][0].olen = 0;
+    chain->effects[e][0].obeg = chain->effects[e][0].oend = 0;
     max_flows = max(max_flows, chain->effects[e][0].flows);
   }
 
@@ -285,7 +300,8 @@
 
   e = chain->length - 1;
   while (source_e < chain->length) {
-#define have_imin (e > 0 && e < chain->length && chain->effects[e - 1][0].olen - chain->effects[e - 1][0].odone >= chain->effects[e][0].imin)
+#define have_imin (e > 0 && e < chain->length && chain->effects[e - 1][0].oend - chain->effects[e - 1][0].obeg >= chain->effects[e][0].imin)
+    size_t osize = chain->effects[e][0].oend - chain->effects[e][0].obeg;
     if (e == source_e && (draining || !have_imin)) {
       if (drain_effect(chain, e) == SOX_EOF) {
         ++source_e;
@@ -296,7 +312,7 @@
       source_e = e;
       draining = sox_true;
     }
-    if (e < chain->length && chain->effects[e][0].olen > chain->effects[e][0].odone) /* False for output */
+    if (e < chain->length && chain->effects[e][0].oend - chain->effects[e][0].obeg > osize) /* False for output */
       ++e;
     else if (e == source_e)
       draining = sox_true;
--- a/src/reverb.c
+++ b/src/reverb.c
@@ -33,7 +33,7 @@
   FLOAT   store;
 } filter_t;
 
-static FLOAT comb_process(filter_t * p,
+static FLOAT comb_process(filter_t * p,  /* gcc -O2 will inline this */
     FLOAT input, FLOAT feedback, FLOAT hf_damping)
 {
   FLOAT output = *p->ptr;
@@ -43,7 +43,7 @@
   return output;
 }
 
-static FLOAT allpass_process(filter_t * p,
+static FLOAT allpass_process(filter_t * p,  /* gcc -O2 will inline this */
     FLOAT input, FLOAT feedback)
 {
   FLOAT output = *p->ptr;
@@ -52,7 +52,7 @@
   return output - input;
 }
 
-static const size_t /* Filter lengths in samples (for 44100Hz sample-rate) */
+static const size_t /* Filter delay lengths in samples (44100Hz sample-rate) */
   comb_lengths[] = {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617},
   allpass_lengths[] = {225, 341, 441, 556};
 #define stereo_adjust 12
@@ -133,7 +133,7 @@
   b = -1 / log(1 - .5); a = 100 / (1 + log(1 - .98) * b); b *= a;
   p->feedback = 1 - exp((reverberance - a) / b);
   p->hf_damping = hf_damping / 100 * .3 + .2;
-  p->gain = exp(wet_gain_dB / 20 * log(10)) * .015;
+  p->gain = exp(wet_gain_dB / 20 * log(10.)) * .015;
   p->delay = pre_delay_ms / 1000 * sample_rate_Hz + .5;
   p->num_delay_blocks = (p->delay + block_size - 1) / block_size;
   Xcalloc(p->in, 1 + p->num_delay_blocks);
--- a/src/sox.h
+++ b/src/sox.h
@@ -418,7 +418,7 @@
   struct sox_signalinfo    outinfo;      /* output signal specifications */
   sox_effect_handler_t     handler;
   sox_ssample_t            *obuf;        /* output buffer */
-  sox_size_t               odone, olen;  /* consumed, total length */
+  sox_size_t               obeg, oend;   /* consumed, total length */
   sox_size_t               imin;         /* minimum input buffer size */
   sox_size_t               clips;        /* increment if clipping occurs */
   sox_size_t               flows;        /* 1 if MCHAN, # chans otherwise */