.\" Note: to format this document for a Diablo printer say:
.\" neqn lprev.dgl | nroff -ms -e -T450-12
.\" on the laser printer at CARL, say
.\" neqn lprev.dgl | ditroff -msnew -e
.EQ
delim $$
.EN
.TL
LPREV - CONFIGURABLE TAP-DELAY/LOW-PASS REVERBERATOR 
.AU
Gareth Loy
.AI
Computer Audio Research Laboratory,
Center for Music Experiment, 
University of California, San Diego
.PP
.I lprev
implements a reverberation scheme described by
Andy Moorer [1]
.FS
"About This Reverberation Business", 
.I CMJ,
Vol. 3, #2. 
.FE
which utilizes a tap delay line to simulate early reflections,
and a section of comb filters with low-pass filters as feedback terms to
simulate the decay of high frequency information through time because of
air and wall absorption.
.PP
Various hooks are provided for modifying the effect of the reverb as described
in the manual page entry 
.I lprev(1carl).  
The purpose of this document is to
explane the signal flow within the reverberator so as to understand what
is being modified by the flags and configuration file specifications.
.PP
The first figure below shows the input stage to the reverberator.  Signal
paths are shown as bars, delay lines are shown as 'z', places where 
paths connect are jointed with '+'.  Operations on the signals are shown
by (*) multiply, and (+) add.
.SH 
SIGNAL FLOW
.LP
.DS
.nf
.ft C
                                                      signal input (Xn)
                                                            |
                                                            +------+
           -mN       -mN-1          -mN-2           -m1     |      |
          Z         Z              Z               Z        V      |
 ...zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz . . . zzzzzzzzzzzzzz...   |
       UN       UN-1           UN-2             U1          U0     |
tap    |        |              |                |           |      |
gains:(*)aN    (*)aN-1        (*)aN-2    . . . (*)a1       (*)a0   |
       |        |              |                |           |      |
       |        |              |                |           |      |
       |        |              |                |           |      |
      (+)------(+)------------(+)------- . . . (+)---------(+)     |
       |                                                           V
      (*) 1 / ( number of taps)                                 to dsig
       |
       |
       +-----------+
       |           |
       V           V
       to D1       to low pass reverb R(z)
.ft P
.DE
The input signal format is binary floating point samples (floatsams).
The input signal (Xn) is sent to a taped delay line.  Tap U0 reads the
signal out with delay time of 0,  taps U1 ... UN pull off the signal with
delays 
$Z sup { -m1 . . . -mN }$.
The configuration file specification 
.DS
.nf
.ft C
t 1.0 0.0
t 0.98 0.045
.ft P
.DE
provides for two taps, with aN terms of 1.0 and .98, and 
$Z sup { -mN }$
delays of 0.0 and 45 milliseconds, respectively, calculated from
the prevailing sampling rate.  The first specification supplies
the direct signal part.
The outputs are summed, then scaled by 
.EQ
1 over { number of taps }
.EN
and sent to D1
and to the input to the low pass reverberators: R(z).
It is possible to override the output gain scaling of the taps by
supplying a value with the -T flag which is used instead.  What is
actually done is that the value of 
.EQ
1 over { number of taps }
.EN
or the value supplied by
-T is multiplied by each of the $a sub N$ terms, and the resulting 
$a sub N$ terms
are used to scale the signal.  This avoids an extra multiply per sample.
.DS
Low pass reverb: R(z) (one shown, inputs/outputs connected in parallel)
.nf
.ft C
      V
      |
      +------------------------ .  .  . (inputs to additional combs)
      |
     (+)<--(*) g2
      |     |
      z     +>----+
      z     |     |
 -m1  z     |     |     -1
Z     z     |     z    Z
      z     |     |
      z     |     |
      z    (+)<--(*) g1
      |     |
      +>----+
      |
     (+)------------------------ .  .  . (sum of comb outputs)
      |
     (*) 1 / (number of combs summed)
      |
      V 
      D2
.ft P
.DE
The lowpass filter reverb sections are hooked in parallel, typically six
of them, each with a different delay time,
$Z sup { -mN }.$
The values of $g sub 1$ for each reverberator
determine the rolloff of the filter in the 
feedback path.  In the configuration file, the line:
.DS
.nf
.ft C
c .46 .053
.ft P
.DE
specifies one comb filter reverberator with $g sub 1$ at .46, and Z delay
of 53 milliseconds.  The values
of $g sub 2$ are set according to
.EQ
g sub { 2 sup i } ~=~ g * (1.0 ~-~ g sub { 1 sup i } ).
.EN
Thus, the term g controls the total reverberation time.  The g term defaults
to 0.9, and is altered by the value supplied to the -g flag.
A value of .87 for g provides a reverb time of about 1 second, 0.9
rings for 3.5 seconds, .99 for 10-14 seconds.
The reverberation time can be estimated as
.EQ
{ 1 ~-~ .366 } over T
.EN
where T is the reverberation time desired in seconds.
The value of $g sub 1$ specified in the configuration file determines 
the rate of rolloff, with larger values (approaching 1.0)
causing accellerated attenuation of high
frequencies over time.
.DS
.nf
.ft C
             D1         D2
	     V          V
	     |          |
	     z          z
	     z    -D1   z    -D2
	     z  :Z      z  :Z
	     z          z
	     |          |
	     V          V
	     +---(+)----+
		  |
		  V
	      to allpass
.ft P
.DE
This section collects the output of the tap delay line at D1 and the
output of the comb filter reverb sections at D2.  The purpose of the
two delays $Z sup { -D sub 1 }$ and $Z sup { -D sub 2 }$ is to
align the outputs from these sections so that the early reflections
from the tap delay line
sound first, and are then immediately followed by the thick
reverb from the comb filter reverb sections.  This models the sound from
actual concert halls.  This is done by the algorithm:
.EQ
D ~=~ ( Z sup { -m sub N } ~-~
( Rz sub 1 ~min~ Rz sub 2 ~min~ ... ~min~ Rz sub n ) )
.EN
.EQ
if ( D > 0 ) \{ D sub 2 ~=~ D;  D sub 1 ~=~ 0; \} 
else \{ D sub 1 ~=~ |D|;~~ D sub 2 ~=~ 0; \}
.EN
Thus, one of the delays will always be 0.
.DS
allpass: (if more than one specified, connected in series)
.nf
.ft C
                   V
                   |
	      +---<+<-----(*) gain
feed foreward:|    |       |
              |    z       |
              |    z       |
              |    z:delay |
              |    z       |
              |    z       |
              |    z       |
              |    |       |:feedback
       -gain (*)-->+>------+
                   |
                   V
    to next allpass (if any) or dsig mix
.ft P
.DE
The allpass sections receive the signal from the taps and comb filters.
There is typically only one, but more may be added by specifying configuration
file lines of the form
.DS
.nf
.ft C
a gain delay
.ft P
.DE
where gain controlls reverberation time and delay is time in seconds.
The output of the last allpass is written to the standard output in
binary floating point floatsams.
.DS
.nf
.ft C
            dsig:      allpass output:
            V          V
            |          |
            |          |
            |          |
            |          |
            V          V
 dsig_gain (*)--(+)---(*) 1 - dsig_gain
                 |
                 V
             signal output
.ft P
.DE
Finally, a portion of the straight input signal, dsig, is scaled by
dsig_gain, which is set with the -D flag, is mixed with the
output of the last allpass reverberator scaled by (1 - dsig_gain).
.SH
EXAMPLE CONFIGURATION FILE
.PP
This example, of a 19-tap, 6-comb, 1-allpass configuration,
is drawn directly from [Moorer].   This table is, in fact, the values
which lprev uses by default.  The format is as follows: lines may begin
with a single letter, either 't', 'c' or 'a' for "tap", "comb" or "allpass".
The next field is a gain associated with that unit, followed by a field
giving the delay length in seconds at the prevailing sampling rate.
.DS
.ft C
.nf
/*
 * 
 * line_format	:== <spec_char> <coeff> <length> 
 * spec_char 	:== t | c | a  (tap, comb, or allpass respectively)
 * coeff 		:== floating_pt_number (between 0 and 1.0)
 * length 	:== floating_pt_number (seconds delay length)
 */
/* tap delay line parameters */
t  1.0  0.0	/* this is the "direct signal" tap */
t  .841 0.0043	/* gain of .841 for tap 1, 4.3 ms delay */
t  .504 0.0215
t  .491 0.0225
t  .379 0.0268
t  .380 0.0270
t  .346 0.0298
t  .289 0.0458
t  .272 0.0485
t  .192 0.0572
t  .193 0.0587
t  .217 0.0595
t  .181 0.0612
t  .180 0.0707
t  .181 0.0708
t  .176 0.0726
t  .142 0.0741
t  .167 0.0753
t  .134 0.0797
/* for roughly 50KHz sampling rate */
c .24 .05 	/* G1 of .24, delay length of 50 ms */
c .26 .056 
c .28 .061 
c .29 .068 
c .20 .072 
c .32 .078 
/* comb reverb parameters */
/* use these values for roughly 25KHz sampling rate */
/*c .46 .05 */
/*c .48 .056 */
/*c .50 .061 */
/*c .52 .068 */
/*c .53 .072 */
/*c .55 .078 */
/* allpass reverb parameters */
a .7 .006  
.ft P
.DE
