Coding a basic reverb algorithm- Part 2: An introduction to audio programming

Rishikesh Daoo
The Seeker’s Project
7 min readMar 26, 2019

Note: This is in continuation to the previous article on coding a basic reverb that can be found here. The article assumes a basic level of understanding of Digital Signal Processing. I have tried to explain and include links for some of the pertinent terms used in this article, but studying DSP would help develop a better appreciation for the topic.

I found this course to be a great starting point for getting into DSP: https://www.coursera.org/learn/dsp

Let’s get into the topic at hand now.

The previous article broke the complete process of programming a reverb into 5 steps and discussed steps 1, 2, 3 and 5.

In this article, we discuss Step 4 — the reverb algorithm that is at the core of the reverb application.

History of Artificial Reverb

Reverberation is defined as the combined effect of multiple sound reflections within a room.

Reverb is one of the most widely used effects in music production and a lot of efforts have been put over the years into developing techniques to achieve the effect of reverberation.

An echo chamber is an example of an early technique that was widely used for creating reverberated sound. With the progress in technology and digital signal processing, people have been trying to digitally emulate the effect of a reverb and a lot of complicated artificial reverberators have been developed in the recent times that produce a natural sounding reverberation.

The subject of artificial reverberation was initiated in the early 1960s by Manfred Schroeder and Ben Logan. *

We use the reverb proposed by Manfred Schroeder for our reverb application.

Introducing the reverb

The Schroeder reverberator is an algorithmic reverberator that was published by Manfred Schroeder in one of his papers in 1962.

The paper addresses the two main defects that the artificial reverberators at that time suffered: the echo density (the number of echos per second) was too low compared to a real room and their amplitude-frequency responses were not flat.

To resolve these issues, Schroeder proposed a reverb with four comb filters in parallel connected to two all-pass filters in series, as shown below. The next section discusses why he chose this arrangement.

Schroeder reverberator

Explanation for the reverb

The explanation for the reverb is divided into 4 parts:

  1. What happens when the reverb units are placed in series or parallel
  2. What are comb filters
  3. What are all-pass filters
  4. Why the 4 comb filters and 2 all-pass filter structure

1. Network of reverb units

When reverb units are connected in parallel, their impulse responses add. The total number of pulses produced is the sum of the pulses produced by the individual units.

When placed in series (cascade), the impulse response of one unit triggers the response of the next, producing a much denser response. The number of pulses produced is the product of the number of pulses produced by the individual units.

This knowledge will be used below to explain the structure of the Schroeder reverb.

2. Comb Filter

The comb filter is the simplest echo producing arrangement with a delay line and a feedback. The gain, g < 0 so that the system is stable.

Comb Filter structure

The impulse response of this filter is an exponentially decaying sequence as seen below.

Impulse Response of a Comb Filter

This is similar to how sound gets reflected and decays in a reverberant room. So, this unit can be used to emulate the effect of a reverb. But as discussed earlier, there would be an issue of low echo density which causes flutter.

Concerning the problem of low echo density, it has been found that approximately 1000 echos per second are required for a flutter-free reverberation.

So, to achieve 1000 echos per second we could either put comb filter units in parallel or in series. But there is a problem with either of these approaches.

For a parallel arrangement: Consider that we have a comb filter with a 40 msec delay line. This would produce 25 echos per second. So, to get 1000 echos per second we would need 40 units in parallel! This is impractical.

For a series arrangement: The frequency response of a comb filter is not flat. As can be seen below, there are peaks and valleys in the frequency response that give the undesired ‘colored’ quality to the sound reverberated by this filter. To achieve the desired echo-density, we would need 4–5 units in series, which would produce a totally unacceptable sound quality.

Frequency response of a comb filter

3. All-pass Filter

Schroeder noted that a modified comb filter, with a negative feed-forward component as shown below, would result in an equal response of the reverberator for all frequencies.

All-pass filter structure

The frequency response of an all-pass filter is flat, thus, allowing for a high echo density without spectral coloration.

Logan and Schroeder found out that the mixing proportions for getting a flat frequency response are (-g) for the undelayed sound and (1 - g²) for the delayed sound, as can be seen in the figure.

Frequency Response of an All-pass filter

Hence, all-pass filters connected in series can be one of the plausible solutions to achieve a reverb.

4. Why the 4 comb filter and 2 all-pass filter structure

A reverberant room has multiple reflections of sound between its multiple walls. A feedback comb filter can simulate a pair of parallel walls, so one could choose the delay-line length in each comb filter to be the number of samples it takes for a plane wave to propagate from one wall to the opposite wall and back.

Schroeder, in his paper, gives a more psycho-acoustically motivated approach to explain the parallel filter bank. The detailed explanation can be found in his paper. In a gist, it says that one may choose the comb-filter delay-line lengths more or less arbitrarily, and then use enough of them in parallel (with mutually prime delay-line lengths) to achieve a perceptually adequate fluctuation density in the frequency-response magnitude.

The all-pass filters in series are added to increase the echo density and have enough diffusion to avoid flutter without coloration of the sound.

Parameters of the reverb

First, let’s establish the relationship between loop gain (g), delay (τ) and the resulting Reverberation Time (T)

  • What is Reverberation Time?

It is defined as the time that a reverberating sound takes to decay by 60 dB. For example, if a sounds decays from 100 dB to 40 dB in 10 seconds, then T = 10 seconds.

For a feedback loop, with gain ‘g’, the sound decays by -20 * log|1/g| decibel for each trip around the loop. And for every delay pulse, it takes τ seconds.

So, the Reverb Time will come out to —

Using this formula, we will be able to calculate the loop gain for the delay time and reverb time that is chosen. Like for example, one of the setting for the reverb can be —

Taken from here

Implementation

We implement the Schroeder reverberator in Java as a Windows desktop application. The application user interface allows the user to select an audio file and adjust the parameters of the reverb. The scope of this implementation has been restricted to WAV format audio files for reasons discussed at length in previous article.

The comb filters have been implemented using the following mathematical equation:

y[n] = x[n] + g·y[n−M]

The all-pass filters have been implemented using the following mathematical equation:

y[n] = (−g·x[n]) + x[n−M] + (g·y[n−M])

‘M’ is the number of samples of delay. This is calculated from the delay (τ) and the sampling rate as —

M = Sampling rate * τ

The complete code for this implementation can be accessed from: https://github.com/Rishikeshdaoo/Reverberator

Reverb in motion

This is a demo video of the final reverb.

I hope this series of articles helps out at least a few. Please let me know if there are any inaccuracies in the explanation or any improvements I could make. Also, please write to me if you have any topic I could write on or projects you would like to work on together.

Rishi

--

--