This example shows how to create a Schroeder reverberator. Here it is a cascade of 3 Schroeder allpass sections and a parallel bank of 4 comb filters as illustrated by the figure below.
First, create the Schroeder allpass sections and comb filters and select only the comb filters.
Then, click on the
button in the right panel of the DSP filter dialog. This copies the current filter selection
in a parallel bank and unselect copied items.
After adding the allpass sections to the selection, you have created the Schroeder reverberator. You can also delete the original comb filters if you do not need it anymore.
When right clicking on a parrallel bank, a Mixer item is available in the menu displayed.
Selecting the Mixer item opens a mixer dialog box.
|
|
|---|
Each row in the mixer dialog represents one input chanel filtered
by one of the DSP filters in the parallel bank.
Here, we have 2 chanels (stereo),
4 filters and therefore 8 lines.
There is one column of entries for each output chanel.
The output signal for a given chanel is the sum of the entries of
the corresponding column multiplying the output of the row at its left.
The left figure above shows the default for which each input chanel is multiplied by
1/(number of filters) for the correponding output and by 0 for the other one.
In the right figure, the output chanels of the filter 2
(FFCF 9719, 0.715) ar mixed between chane 0 and 1 outputs.
You can download schroeder_reverb.py displayed below and Load it from the application for reproducing the Schroeder reverberator. You can edit it in order to add more filters, use feedback instead of feedforword comb filters or add lowpass filter taps for reducing high frequency reverberation.
schroeder_reverb.py
def shroeder_reverb(damping=0., audioFile=""):
# Example from
# https://ccrma.stanford.edu/~jos/pasp/Example_Schroeder_Reverberators.html
# If damping is not 0
# => add low pass filter tap to comb an allpass filters
# You can also set it independently for each all-pass/ comb later
DSPFilterOpen()
width, height=GetDSPSize()
SetDSPSize(700, 300)
DSPClear()
#Remember where to start selection for filters created later
nFilterOrg=dsp_get_num_filters()
# set a damping parameters
# => add low pass filter tap to comb an allpass filters
DSPFilterType("All Pass")
delay=[1051,337,113] # in sample
g=0.7
gain=[g,g,g]
longdelay=True
if longdelay == True:
#Nearest prime from original delay *1.8 ~> 44100/25000
#since the filters have been designed for 25 kHz sample rate
delay=[1891,607,199]
gain=[g,g,g]
nNew=len(delay)
# Creat Schroeder allpass sections for each pair (delay, gain)
for i in range(nNew):
DSPFilterAllPass( delay[i], gain[i],damping)
DSPFilterType("Comb")
delay=[4799,4999,5399,5801]
gain=[0.742,0.733,0.715,0.697]
if longdelay == True:
#Nearest prime from original delay *1.8 ~> 44100/25000
delay=[8641,8999,9719,10433]
nNew=len(delay)
#for selcting the last one when done
nFilters=dsp_get_num_filters()
# Creat Comb filters for each pair (delay, gain)
feedBack=0 # feedforward otherwise
for i in range(nNew):
DSPFilterComb(feedBack, delay[i], gain[i],damping)
#Unselect all
DSPSelectAll(0)
#Select only created comb filters
DSPSelect(nFilters, nFilters+nNew-1, 1)
# Pack selection in a parallel block
# Create a parallel bank with the current selection
label=DSPSetParallel()
#select all pass sections
DSPSelect(nFilterOrg, nFilterOrg+2, 1)
#rename the filter
DSPFilterRename(label, "Schroeder parallel combs")
if audioFile != "":
# Open an audio file and listen to the
DSPRealTime(1)
OpenSoundFile(audioFile)
# Playback for 10 sec
PlaySound(0.00000000, 10)
# wait audio stream ends
WaitSoundThread(10.5)
#You can add set a damping parameter (lowpas filter tap)"
damping=0.
#You can also add an audio file for listen"
audioFileName=""
shroeder_reverb( damping, audioFileName)
In the example below where two bandpass filters have been put in a parallel bank,
the default mixer settings are not appropriated since in that case, each filter
contributes to a different part of frequency range.
The left band whose output has been multiplied by 0.5 and therefore
has a passband attenuation of -6 dB whereas the right band whose mixer coeffictients
have been set to one does not attenuate the signal in the passband.
⚠ The impulse response of a parallel filter bank is the sum of the impulse responses of individual filters. These are complex function and there sum have a linear phase only if all filters have a linear phase and the same length (order).
Here are the functions that can be called from Python scripts.
DSPSetParallel()
# Copies the current filter selection in a parallel filter bank.
# Returns the label of the new filter bank.
###############################################################
DSPOpenParallelMixer(string filterBankLabel)
# Opens the Mixer dialog.
###############################################################
DspApplyParallelMixer(string filterBankLabel, int numChanel, in numRow,
M[0,0], M[0,1], .... , M[numRow-1,0], M[numRow-1,1])
# Set the mixer for the parallel bank filterBankLabel.
# M[i,j] is the mixing coeffictient for row i to output j.
###############################################################