Reverb

Author: Kees van den Doel


This applet contains an implementation of a reverb as described by Steiglitz in his book "A Digital Signal Processing Primer with Applications to Digital Audio and Computer Music", pages 290 -- 295.

This patch uses several containing patches and would be best explained in a diagram which eventually I'll produce here.

Here's a home recording of me playing my Persian ney, dry and reverbed using this reverb patch.

The input signal is filtered through 6 parallel comb filters (delay feedback loops) with a lowpass filter in each loop. Each comb filter is characterized by a feedback coefficient, a low-pass filter coefficient g, from the lowpass transfer function H(z) = 1/(1-g/z), and a delay time. The result of summingthe 6 comb filter outputs is fed through an allpass filter, which is characterized by a delay, and a coefficient a. The allpass transfer function is H(z) = (z^-{m}+a)/(1+a*z^{-m}). The final result is mixed with the original signal.

You can reverberate a recording or a mike input (if your security allows mike input through your browser).

All parameters can be set with the sliders. Try increasing the delays to get a Taj-Mahal effect. If you boost the feedback too much the filter will become unstable (negative absorbtion). AGC will then turn things off untill you reset it. You can always get the defaults back by pressing a button. I guess it's clear *which* button...

If you have no mike the AGC will boost the noise in your soundcard and reverberate that. Latency is terrible. Download JASS and reduce the buffersizes if you have low latency JavaSound implementation like Tritonus, if you can't live with it.

Source code:

import java.io.*;
import java.net.*;
import jass.render.*;
import jass.engine.*;
import jass.generators.*;
import jass.patches.*;

/** CombReverb using Moorers reverb. See e.g.
    @book{Steiglitz96,
	title		= {A Digital Signal Processing Primer with
                          Applications to Digital Audio and Computer Music},
	author          =  {Ken Steiglitz},
	publisher	= {Addison-Wesley},
	address		= {New York},
	year		= {1996},
    pages = {290--295}}

    Defaults are for 25Khz sampling rate from Steiglitz book.
    
    @author Kees van den Doel (kvdoel@cs.ubc.ca)
*/
public class ReverbApplet extends AppletController {
    
    int bufferSize = 16; // no feedback loop can have smaller delay than this
    int bufferSizeJavaSound = 0; // use huge default latency
    float srate = 44100;
    SourcePlayer player;
    AudioIn input;
    ConstantLoopBuffer loopbuf; // another source
    String wavfile = "../data/hello.wav";
    boolean useMike = false;
    float impulseT = 1f; //second
    CombReverb reverb;
    int nReflections = 6;
    // Reverb parameters
    float[] combDelays = {.05f,.056f,.061f,.068f,.072f,.078f}; // delays in seonds
    float allpassDelay = .006f; // delay in seconds
    float a = .7071068f; // allpass parameter
    float[] R = {.4897f,.6142f,.5976f,.5893f,.581f,.5644f}; // feedback comb parameters
    float[] g = {.24f,.26f,.28f,.29f,.3f,.32f}; // low-pass comb parameters
    float dryToWet = .1f; // 1 is dry only
    double minDelay = 1.3*(bufferSize/srate); // smalles feedback delay possible

    public void setNSliders() {
        nsliders = nReflections*3 + 3;
    }

    public void setNButtons() {
        nbuttons = 3;
    }

    protected void createPatch() {
        URL wavurl = null;
        try {
            wavurl = new URL(getCodeBase(),wavfile);
        } catch(MalformedURLException e) {
            System.out.println(e+" Malformed URL: " + wavfile);
        }
        player = new SourcePlayer(bufferSize,bufferSizeJavaSound,srate);
        if(useMike) {
            input = new AudioIn(srate,bufferSize,bufferSizeJavaSound);
        } else {
            loopbuf = new ConstantLoopBuffer(srate,bufferSize,wavurl);

        }
        reverb = new CombReverb(bufferSize,srate,nReflections);
        try {
            if(useMike) {
                reverb.addSource(input);
            } else {
                reverb.addSource(loopbuf);
            }
            player.addSource(reverb);
        } catch(SinkIsFullException e) {
            System.out.println(e);
            System.exit(0);
        }
        for(int i=0;i