Implementing the Gardner Reverbs in Csound

Hans Mikelson

This chapter describes the implementation of reverbs based on nested allpass filters. Reverberant sound occurs when sound waves are reflected by surfaces repeatedly until the individual reflections merge into a continuous sound. Nested allpass filters proposed by Barry Vercoe and Miller Puckette (1985) can be used to simulate the dense reflections associated with room reverberation. This chapter describes several different types of allpass filters and uses them to implement three different reverbs. The reverbs presented in this section are derived from those developed by Bill Gardner (1992).

The Allpass Filter

Adding both a feedback path and a feedforward path to a delay line as shown in figure 24.1 makes an allpass filter.

Figure 24.1 Block diagram of a simple allpass filter.

Gain is applied to the feedback path and negative gain is applied to the feedforward path. An allpass filter passes all frequencies unaltered but changes the phase of each frequency. This can be implemented in Csound as follows:

		                                                                                               
   adel1       init      0                                                                      
   aout        =         adel1-igain*ain             ; FEEDFORWARD                              
   adel1       delay     ain+igain*aout, itime       ; FEEDBACK
   

The Single Nested Allpass Filter

A single nested allpass filter is implemented by surrounding one allpass filter by a second as shown in figure 24.2.

Figure 24.2 Block diagram of a single nested allpass filter.

A simplified representation of the allpass filter presented in figure 24.2 is shown in figure 24.3. The outer delay time t1 in figure 24.3 is equal to the sum of the delay1 and delay2 times of figure 24.2.

Figure 24.3 Block diagram of a simplified single nested allpass filter.

This can be implemented in Csound as follows:

                                                                                              
   asum      =        adel2-igain2*adel1             ; Feedforward                              
   aout      =        asum-igain1*ain                ; Feedforward                              
   adel1     delay    ain+igain1*aout, itime         ; Feedback                                 
   adel2     delay    adel1+igain2*asum, itime2      ; Feedback        
   

The Double Nested Allpass Filter

A double nested allpass filter is implemented by surrounding two allpass filters in series by a third allpass filter as shown in figure 24.4.

Figure 24.4 Block diagram of double nested allpass filter.

The simplified version of this is presented in figure 24.5. In this case t1 in figure 24.5 is the sum of delay1, delay2 and delay3 of figure 24.4.

Figure 24.5 Simplified block diagram of a double nested allpass filter.

The double nested allpass filter can be implemented in Csound as follows:

		                                                                                                
   asum1     =         adel2-igain2*adel1              ; 1st In FF                              
   asum2     =         adel3-igain3*asum1              ; 2nd In FF                              
   aout      =         asum2-igain1*ain                ; Outer FF                               
   adel1     delay     ain+igain1*aout, itime1         ; Outer FB                               
   adel2     delay     adel1+igain2*asum1, itime2      ; 1st In FB                              
   adel3     delay     asum1+igain3*asum2, itime3      ; 2nd In FB

   

Small Room Reverberator

The nested allpass filters are now combined to form reverbs. The first reverb presented is for a small room. It consists of a double nested allpass filter followed by a single nested allpass filter. The input is pre-filtered at 6 kHz to reduce metallic ringing. An overall feedback path is bandpass filtered and added to the input. The feedback filter also reduces the metallic character of the reverb and reduces DC offset. Another simplified notation is presented in figure 24.6. Delays are indicated by putting the delay time above the signal path and all times in these figures are expressed in milliseconds.

Figure 24.6 Block diagram of small room reverberator.

The small room reverb shown in figure 24.6 can be implemented in Csound as follows:

		                                                                                                
           instr    2402           ; small room reverb                                          
   idur    =        p3                                                                          
   iamp    =        p4                                                                          
   iinch   =        p5                                                                          
   aout41  init     0                                                                           
   adel01  init     0                                                                           
   adel11  init     0                                                                           
   adel21  init     0                                                                           
   adel22  init     0                                                                           
   adel23  init     0                                                                           
   adel41  init     0                                                                           
   adel42  init     0                                                                           
   kdclick linseg   0, .002, iamp, idur-.004, iamp, .002, 0                                     
   ; Initialize                                                                                 
   asig0   zar      iinch                                                                       
   aflt01  butterlp asig0, 6000              ; Pre-Filter                                       
   aflt02  butterbp .5*aout41, 1600, 800     ; Feedback Filter                                  
   asum01  =        aflt01+.5*aflt02         ; Initial Mix                                      
   ; Delay 1                                                                                    
   adel11  delay    asum01, .024                                                                
   ; Double Nested Allpass                                                                      
   asum21  =        adel22-.25*adel21        ; First Inner Feedforward                          
   asum22  =        adel23-.30*asum21        ; Second Inner Feedforward                         
   aout21  =        asum22-.15*adel11        ; Outer Feedforward                                
   adel21  delay    adel11+.15*aout21, .0047 ; Outer Feedback                                   
   adel22  delay    adel21+.25*asum21, .022  ; First Inner Feedback                             
   adel23  delay    asum21+.30*asum22, .0083 ; Second Inner Feedback                            
   ; Single Nested Allpass                                                                      
   asum41  =        adel42-.3*adel41         ; Inner Feedforward                                
   aout41  =        asum41-.08*aout21        ; Outer Feedforward                                
   adel41  delay    aout21+.08*aout41, .036  ; Outer Feedback                                   
   adel42  delay    adel41+.3*asum41, .030   ; Inner Feedback                                   
   ; Output                                                                                     
   aout    =        .6*aout41+.5*aout21                                                         
           outs     aout*kdclick, -aout*kdclick                                                 
           endin                                                                                

Figure 24.7 Orchestra code for instr 2402, a small room reverb.

Medium Room Reverberator

The next reverb is for a medium room. It consists of a double nested allpass filter followed by an allpass filter, followed by a single nested allpass filter. The input is prefiltered at 6 kHz and is introduced at both the beginning and before the final nested allpass filter. Output is taken after each allpass filter section. The overall feedback is bandpass filtered at 1 kHz with a bandwidth of 500 Hz. There are four delays in this reverb. The first delay follows the first output tap. The second and third delays are before and after the second output tap and the third delay precedes the overall feedback.

Figure 24.8 Block diagram of medium room reverberator.

		                                                                                                
           instr    2403           ; Medium Room Reverb                                         
   idur    =        p3                                                                          
   iamp    =        p4                                                                          
   iinch   =        p5                                                                          
   adel71  init     0                                                                           
   adel11  init     0                                                                           
   adel12  init     0                                                                           
   adel13  init     0                                                                           
   adel31  init     0                                                                           
   adel61  init     0                                                                           
   adel62  init     0                                                                           
   kdclick linseg   0, .002, iamp, idur-.004, iamp, .002, 0                                     
   ; Initialize                                                                                 
   asig0   zar      iinch                                                                       
   aflt01  butterlp asig0, 6000              ; Pre-Filter                                       
   aflt02  butterbp .4*adel71, 1000, 500     ; Feedback Filter                                  
   asum01  =        aflt01+.5*aflt02         ; Initial Mix                                      
   ; Double Nested Allpass                                                                      
   asum11  =        adel12-.35*adel11        ; First Inner Feedforward                          
   asum12  =        adel13-.45*asum11        ; Second Inner Feedforward                         
   aout11  =        asum12-.25*asum01        ; Outer Feedforward                                
   adel11  delay    asum01+.25*aout11, .0047 ; Outer Feedback                                   
   adel12  delay    adel11+.35*asum11, .0083 ; First Inner Feedback                             
   adel13  delay    asum11+.45*asum12, .022  ; Second Inner Feedback                            
   adel21  delay    aout11, .005             ; Delay 1                                          
   ; Allpass 1                                                                                  
   asub31  =        adel31-.45*adel21        ; Feedforward                                      
   adel31  delay    adel21+.45*asub31,.030   ; Feedback                                         
   adel41  delay    asub31, .067             ; Delay 2                                          
   adel51  delay    .4*adel41, .015          ; Delay 3                                          
   aout51  =        aflt01+adel41                                                               
   ; Single Nested Allpass                                                                      
   asum61  =        adel62-.35*adel61        ; Inner Feedforward                                
   aout61  =        asum61-.25*aout51        ; Outer Feedforward                                
   adel61  delay    aout51+.25*aout61, .0292 ; Outer Feedback                                   
   adel62  delay    adel61+.35*asum61, .0098 ; Inner Feedback                                   
   ; Combine Outputs                                                                            
   aout    =        .5*aout11+.5*adel41+.5*aout61                                               
   adel71  delay    aout61, .108             ; Delay 4                                          
           outs     aout*kdclick,            ; Final Output                                     
                    -aout*kdclick                                                               
           endin                                                                            

	   

Figure 24.9 Orchestra code for instr 2403, a medium room reverberator.

Large Room Reverberator

The final reverb considered is for a large room. The major elements are two allpass filters in series, followed by a single nested allpass filter and finally a double nested allpass filter. Outputs are taken after the first two allpass filters, after the single nested allpass filter and after the double nested allpass filter. Delays are introduced before and after the first two output taps. The input is again prefiltered and the overall feedback is scaled and bandpass filtered.

Figure 24.10 Block diagram of large room reverberator.

		                                                                                                
           instr    2404           ; Large Room Reverb                                          
   idur    =        p3                                                                          
   iamp    =        p4                                                                          
   iinch   =        p5                                                                          
   aout91  init     0                                                                           
   adel01  init     0                                                                           
   adel11  init     0                                                                           
   adel51  init     0                                                                           
   adel52  init     0                                                                           
   adel91  init     0                                                                           
   adel92  init     0                                                                           
   adel93  init     0                                                                           
   kdclick linseg   0, .002, iamp, idur-.004, iamp, .002, 0                                     
   ; Initialize                                                                                 
   asig0   zar      iinch                                                                       
   aflt01  butterlp asig0, 4000              ; Pre-Filter                                       
   aflt02  butterbp .5*aout91, 1000, 500     ; Feedback Filter                                  
   asum01  =        aflt01+.5*aflt02         ; Initial Mix                                      
   ; Allpass 1                                                                                  
   asub01  =        adel01-.3*asum01         ; Feedforward                                      
   adel01  delay    asum01+.3*asub01,.008    ; Feedback                                         
   ; Allpass 2                                                                                  
   asub11  =        adel11-.3*asub01         ; Feedforward                                      
   adel11  delay    asub01+.3*asub11,.012    ; Feedback                                         
   adel21  delay    asub11, .004             ; Delay 1                                          
   adel41  delay    adel21, .017             ; Delay 2                                          
   ; Single Nested Allpass                                                                      
   asum51  =        adel52-.25*adel51        ; Inner Feedforward                                
   aout51  =        asum51-.5*adel41         ; Outer Feedforward                                
   adel51  delay    adel41+.5*aout51, .025   ; Outer Feedback                                   
   adel52  delay    adel51+.25*asum51, .062  ; Inner Feedback                                   
   adel61  delay    aout51, .031             ; Delay 3                                          
   adel81  delay    adel61, .003             ; Delay 4                                          
   ; Double Nested Allpass                                                                      
   asum91  =        adel92-.25*adel91        ; First Inner Feedforward                          
   asum92  =        adel93-.25*asum91        ; Second Inner Feedforward                         
   aout91  =        asum92-.5*adel81         ; Outer Feedforward                                
   adel91  delay    adel81+.5*aout91, .120   ; Outer Feedback                                   
   adel92  delay    adel91+.25*asum91, .076  ; First Inner Feedback                             
   adel93  delay    asum91+.25*asum92, .030  ; Second Inner Feedback                            
   ; Combine outputs                                                                            
   aout    =        .8*aout91+.8*adel61+1.5*adel21                                              
           outs     aout*kdclick,            ; Final Output                                     
                    -aout*kdclick                                                               
           endin                                                                                
           

Figure 24.11 Orchestra code for instr 2404, a large room reverb

Conclusion

The nested allpass filters presented here suggest other configurations of allpass filters. For instance, a third allpass filter could be inserted into the double nested allpass filter for three allpass filters in series. An additional level of nesting could be applied to the nested allpass filters. Many other configurations of nesting could be the subject of future experimentation and many other reverb configurations could be implemented as a result. The final Csound orchestra and score accompanying this chapter, instr 2405.orc features a flexible system for experimenting with various reverb configurations.

References

Vercoe, B. and M. Puckette. 1985. Synthetic Spaces — Artificial Acoustic Ambiance from Active Boundary Computation. unpublished NSF proposal . Boston, MA. Music and Cognition Office at MIT Media Lab.

Gardner, W. G. 1992. The Virtual Acoustic Room. Master's thesis, MIT Media Lab.