Reverb
The six boxes in the above diagram are each implemented as depicted below:
What is reverb?
When recording a live music performance, sound travels directly from the instruments to the microphone, but the same sound also bounces between walls and other objects before finally reaching the microphone. This reverberation (reverb for short) gives each space a distinctive acoustic profile. A room may sound cavernous, intimate, bright, dark, etc. This feel is one of the most dramatic effects you can add to a digital synthesizer. A bit of reverb transforms a flat-sounding synth waveform into a thrilling experience.
How to simulate reverb? To a mathematician, reverberation is just a rather complicated DSP filter. DSP theory tells us that any filter is completely determined by its impulse response: First, feed the filter with an impulse, which is a special signal with 1.0 for the first sample and 0.0 for all subsequent samples. Then, capture the filter's output samples. Amazingly, the samples from this response signal happen to be the convolution coefficients needed to exactly reproduce that filter. Clap your hands once in a concert hall and record the echoes, and you have a rough approximation of this method.
Let's think about the wave that emanates from a single hand clap. If you are facing a flat wall, the sound wave will travel to the wall, then bounce back a few hundred milliseconds later as a "slapback echo." If there is another wall behind you, the echoes may repeat many times, bouncing between the two walls, quieter each time. Both situations can be easily simulated using Jamdac's channel effect with a single delay buffer.
A concert hall is quite different, though. Here the sound hits the side walls at an angle, "smearing" out the wavefront on its way back to the microphone, as well as wrapping around other objects like chairs and columns. Instead of a simple repeating pulse, our clap returns to the microphone as a complex randomized "smear" of sound. Accurately generating this effect is challenging. Classic synthesizers resorted to vibrating mechanical springs or plates. Modern digital reverb algorithms rely on matrix multiplication or physical simulations. It's also possible to directly implement the filter from a recorded impulse response, if you're okay with performing billions of multiplications per second.
Jamdac's reverb algorithm
Jamdac instead follows the approach from Manfred Schroeder's 1962 paper Natural Sounding Artificial Reverberation. A masterpiece of engineering research, it combined several insights:
- Schroeder started by simulating reverb as a cluster of individual echos. From experimental measurements, he found that human listeners perceive annoying "fluttering" if the "echo density" does not achieve at least 1,000 echoes per second.
- The reverb system is built from a collection of feedback loops that generate these echoes. The feedback loops are chained together to produce as many echoes as possible from a single input impulse (hand clap).
- There are two banks of filters: the serial filters (Allpass 0, 1, 2 in Jamdac's version) and parallel filters (Allpass 3, 4, 5).
- All this repeated filtering can easily distort the original sound, producing unpleasant "coloration" such as metallic ringing. Schroeder addressed that by using allpass filters, which manipulate a signal's phase (timing) while preserving the amplitude of each frequency.
- In Schroeder's designs, the parallel banks featured comb filters instead of allpass filters. The comb filters are structured similarly but without the allpass amplifiers
1-FEEDBACK^2and-FEEDBACK. Mixing two types of filters increased the richness of the reverb. Jamdac instead reuses identical allpass units in both banks; we get away with this simplification because we're processing synthetic instruments, not the live performances that Schroeder studied. - Stereo separation ("ambiophonic reverberation" in the paper) is achieved by inverting some inputs before mixing the left/right outputs. In the diagram, the two amplifiers multiply each sample by -1. For a cheap enhancement, it's surprisingly effective.
Configuring the reverb component
Jamdac's allpass filters have just two parameters: the delay buffer length (measured in samples), and the FEEDBACK variable. These are specified using the two arrays IO_REVERB::STAGE_DELAY_SIZES[] and IO_REVERB::STAGE_FEEDBACKS[]. Each array has six elements, one for each allpass filter. Use the LOAD GLOBAL REVERB command to configure the reverb component.
CLASS IO_REVERB # SIZE 24
# UNITS: BUFFER ARRAY SIZE MEASURED IN SAMPLES
INSET STAGE_DELAY_SIZES: PAIR[SIZE 6] # [JAMDAC PLUS]
# UNITS: S6.10 FIXED POINT
INSET STAGE_FEEDBACKS: PAIR[SIZE 6] # [JAMDAC PLUS]
END CLASS
The Hybrix framework automatically configures the reverb component when your program starts, using the predefined values shown below. For typical applications, there's no need to change it:
# HYBRIX FRAMEWORK REVERB CONFIGURATION
DATA ART::REVERB
STAGE_DELAY_SIZES: [
373,
443,
283,
639,
728,
904
],
STAGE_FEEDBACKS: [
764, # 0.74600
725, # 0.70800
819, # 0.79980
896, # 0.87500
880, # 0.85938
848 # 0.82813
]
END DATA
Each instrument has a REVERB_LEVEL dynamic parameter that determines how much reverb to apply. See the next section for details.