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 */