Synthesis and transformation of sound with comb filters in Common Lisp Music
Prof. Oscar Pablo Di Liscia
a)General
The purpose of this work is to explore -through the design of an instrument for the Common Lisp Music program (Bill Schottstaedt, CCRMA, Stanford University)- some of the sound synthesis and transformation possibilities of a network of lowpass, hipass and comb filters.
Widely used in DSP to emulate reverberation (see Moorer, Dodge & Jerse and Steiglitz, op. Cit), the comb filter has a non-flat frequency response which is considered undesirable for this purpose. However, it could be a powerful and handy feature if it is desirable to produce "colored" signals, or some harmonic or cuasi-inharmonic signals from noise sources, even imitating the behavior of acoustic instruments.
b)About comb filters
The comb filter has received its name because of the particular shape of its frequency response (see Figures 1.a y 1.b). It is an IIR filter (Infinite Impulse Response), and its difference equation is as follows:
y(n) = x(n-D) + g y(n-D)
where:
x(n) is the nth sample of the input signal.
D is the delay of the filter, in samples.
g is the feedback coefficient of the filter.
y(n) is the nth sample of the output signal.
According with (Moore, op.cit., pp. 381-82), its z transform :
H(z) = H-D / (1 - gz-D)
(eq. 1.a)Allows us to evaluate its frequency response as:
| H (e j
w) | = 1 / (1 - 2g cos wD + g2)1/2(eq. 1.b)Thus, when the quantity cos wD reaches its maximal value, the denominator of equation 1.b equals to 1-g, and when cos wD reaches its minimal value the same denominator equals to 1+g. This shows that the amplitude of the frequency response of a comb filter changes over a full range of: (1 + g) / (1 - g).
To say it other way, the so-called resonance frequency, in Hertz, of a comb filter equals to: Sampling Rate / Delay (in samples), and will produce as many poles (resonant peaks) as samples has its delay, each pole being located at intervals of the resonance frequency. When the coefficient is positive, the first pole is located at 0 Hz, while when it is negative it is located at: (resonance frequency / 2)Hz.
As an example, let´s consider the case of two comb filters, both with a delay of 20 samples, having the first one a coefficient of 0.9, and the second one a coefficient of -0.9. The amount of poles will be 20, using a Sampling Rate of 44100 Hz, the resonance frequency will be: 44100/20=2205 Hz. The peak-to-valley amplitude of the frequency response of these filters will be: (1.+0.9) / (1. -0.9)= 19. (ca. 25.5 dB).
The difference between these two filters is easily seen in Figures 1.a and 1.b. Note that the first one has its first pole at 0 Hz while the second has its first pole at 1102.5 Hz. Poles are 20 for both, but only the positive part of the spectrum is plotted. A very good 3-D plot of the transfer function of one comb filter on the z plane can be seen in (Steiglitz, op. Cit., pp. 103).
Figure 1.a

Figure 1.b

c)Application in Common Lisp Music: kombie.ins
The flow diagram of kombie.ins is shown in the following figure:
Figure 2
The general idea is very simple: a source signal on a file is read with the readin unit, then it feeds a comb filter, and finally is filtered by hipass, and lowpass (IIR, second order, Butterworth) filters. The purpose of the hipass filter is to attenuate the frequencies below the supposed "fundamental" that will be produced by the comb. As an example, consider to use this network to filter white noise, setting the comb resonance frequency at 440 Hz. This will produce peaks separated by 440 Hz, but the frequency components below this may be undesirable if we are to produce some pitched sound. It is also possible to use low resonant frequencies (say 20 Hz, for example), and to adjust the hipass filter cutoff to other frequency than the resonance to get inharmonic bands. The lowpass filter is used to provide a scaling of the high frequencies similar to the behavior of some acoustic instruments. The cutoff frequencies of the lowpass, hipass filters, and the feedback coefficient of the comb filter may be fixed or time-changing through the use of envelopes. This will allow us to produce changes and spectral transitions.
d)Parameters of kombie
(kombie start dur file-name freq
&key :aba :cba :hba :file-start :channel :amp :scoef :flp :shp :aenv :kenv :lenv :henv :balance-kenv :scale-amp)
:start note start.
:dur note duration.
:file-name input file name.
:freq Resonance frequency of the comb filter (Hz). The delay is calculated internally out of the given frequency.
:aba The base for the amplitude envelope (see the env UG in Schottstaedt, op. Cit.). Default=1.
:cba The base for the comb filter coefficient envelope (see the env UG in Schottstaedt, op. Cit.). Default=1.
:lba The base for the cutoff frequency of the lowpass filter envelope (see the env and Butterworth UGs in Schottstaedt, op. Cit.). Default=1.
:hba The base for the cutoff frequency of the hipass filter envelope (see the env and Butterworth UGs in Schottstaedt, op. Cit.). Default=1.
:file-start starting read point of the input file, in seconds. Default=0.
:channel This instrument is mono, it will read by default the first channel of an input multichannel file. If you want to read another channel you must specify it.
:amp Output gain scaler. This value will be used as a scaler of the amplitude envelope. Default= 1.
:scoef Coefficient of the comb filter. It may be positive or negative, but must be smaller than 1. and greater than -1., otherwise the filter will be unstable. This value will be used as scaler of the envelope controlling the coefficient. Default= .9.
:flp Cutoff frequency of the Butterworth lowpass filter. Must be greater than 1. And smaller than SR/2. This value will be used as scaler of the envelope controlling the lowpass filter cutoff frequency. Default= (SR/2.)-1
:shp Scaler to calculate the cutoff frequency of the hipass filter. This will equals to: (freq * shp) Hz. May be smaller than 1 The resulting value will be used as scaler of the envelope controlling the hipass filter cutoff frequency. Default=1.
:aenv A list containing pairs of X Y values to be used by the amplitude envelope of the output. Since the :amp parameter is further used as a scaler of this envelope, it is suggested to use normalized envelopes. Default= (0,1,100,1).
:kenv A list containing pairs of X Y values to be used by the comb filter coefficient envelope. Since the :scoef parameter is further used as a scaler of this envelope, it is suggested to use normalized envelopes. Default= (0,1,100,1).
:lenv A list containing pairs of X Y values to be used by the lowpass filter cutoff frequency envelope. Since the :flp parameter is further used as a scaler of this envelope, it is suggested to use normalized envelopes. Default= (0,1,100,1).
:henv A list containing pairs of X Y values to be used by the hipass filter cutoff frequency envelope. Since the value yielded by (:freq * :shp) is further used as a scaler of this envelope, it is suggested to use normalized envelopes. Default= (0,1,100,1).
:balance-kenv When set to TRUE, the lowpass and hipass filters envelopes will be calculated automatically (thus, disregarding :henv and :lenv) to start "cutting" when the comb filter coefficient is non-zero, and reaches their maximal cut frequency when the comb filter coefficient reaches its maximal value. This is handy to do transitions between an original sound and the "combed" one, because it is not desirable that the original signal be filtered by the lowpass and hipass filters while the comb filter is not active. Default= NIL.
:scale-amp When set to TRUE, the :amp value will be forced to: (1. - abs(:scoef) ). This can be useful to ensure the proper amplitude range of output, but may not be that convenient if the input has low amplitude range. Default= NIL.
e)Some application examples.
N.B: To use this instrument, load and compile first butterworth.cl, and then load and compile it.
1- balance-kenv test
Source is white noise.
(with-sound (:output "~/balance-kenv-test.snd" :srate 44100)
(kombie 0 1 "~/blanc.wav" 1000 :kenv '(0 0 33 1 66 1 100 0)
:flp 4000 :balance-kenv t :aenv '(0 0 1 1 99 1 100 0) :amp .4 )
)
|
2-flute-like pitched noise(eolic) Source is white noise. (with-sound (:output "~/komb-flu-eol.snd" :srate 44100) (kombie 0 2 "~/blanc.wav" 440 :kenv '(0 0 100 1) :cba .01 :lenv '(0 0 5 1 5 .5 50 .5 100 0) :flp 8000 :shp 4 :aenv '(0 0 10 1 90 1 100 0) :amp .5) ) |
|
3-Morphing from a flute sound to a clarinet-like sound, and back to flute: Source is a recorded flute playing an A4 (ca. 440 Hz) by 3 seconds. (with-sound (:output "~/flu-cla-morph.snd" :srate 44100) (kombie 0 3 "~/flute.wav" 880 :kenv '(0 0 33 1 66 1 100 0) :cba .1 :scoef -.95 :shp .5 :amp .1 :aenv '(0 8 33 1 66 1 100 8) :aba .1) ) |
|
4-Transition from speaking voice to pitched sound (Forte´s pitch class set 3-5 is used) (with-sound (:output ~/voice-to-pitch.snd" :srate 44100) (kombie 0 8 "~/voice.wav" c5 :kenv '(0 0 100 1) :balance-kenv t :amp .1 :cba .01 :scoef .99) (kombie 0 8 "~/voice.wav" fs5 :kenv '(0 0 100 1) :balance-kenv t :amp .1 :cba .01 :scoef .99 ) (kombie 0 8 "~/voice.wav" b5 :kenv '(0 0 100 1) :balance-kenv t :amp .1 :cba .01 :scoef .99) ) |
|
5-plucked sound (source is a burst of white noise, see Steiglitz, op. Cit., pp. 106-110) (with-sound (:output "~/kombie-pluck.snd" :srate 44100) (kombie 0 2 "~/noise-short.wav" e4 :scoef .99 :aenv '(0 1 100 0) :lba 200 :amp .75 :flp 10000 :lenv '(0 2 2 .5 20 .1 80 .1 100 0)) )
|
|
;;;;; KOMBIE.INS - Oscar Pablo Di Liscia - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (definstrument kombie ( start dur file-name ; name of soundfile to process freq ; The resonant frequency of the filter. ; The delay of the filter will be calculated out of the ; frequency given (delay = sampling-rate / frequency)
&key
(aba 1.) ; base for the amplitude envelope (cba 1.) ; base for the comb filter coefficient envelope (lba 1.) ; base for the lowpass filter envelope (hba 1.) ; base for the hipass filter envelope (file-start 0.0) ; start time point of file in seconds (amp 1.0) ; general gain control (channel ':A) ; channel to read if multi-channel soundfile (scoef .9) ; comb filter feedback coefficient scaler (flp (- (/ sampling-rate 2.) 1.)) ; cutoff freq for lowpass filter (shp 1.) ; scaler for the hipass filter cutoff freq ; MAY NOT be the resonant frequency of the comb filter, but ; a harmonic, the frequency will be: freq * shp (aenv '(0 1 100 1)) ; amplitude envelope (kenv '(0 1 100 1)) ; envelope for the comb filter coefficient (lenv '(0 1 100 1)) ; envelope for the lowpass filter (henv '(0 1 100 1)) ; envelope for the hipass filter (balance-kenv nil) ; if set to TRUE both, the HP and the LP filters ; will perform only when the coefficient of the comb is ; non zero, and their cut freqs. will be inverselly ; proportional to it. ; Warning: lenv and henv will be disregarded in this case. (scale-amp nil) ; if set to TRUE the max amp will be scaled according ; to: (1. - scoef) ) (let* ( (amp (if scale-amp (- 1. (abs scoef)) amp)) (sound-file (clm-open-input* file-name)) (start-sample (floor (* start sampling-rate))) (end-sample (floor (+ start-sample (* dur sampling-rate)))) (input-sound (make-readin :file sound-file :channel channel :start-time file-start )) (delay (/ sampling-rate freq)) (komb (make-comb :scaler scoef :size delay)) (lpf (make-butterlp flp )) (hpf (make-butterhp (* shp freq ) )) (comenv(make-env :envelope kenv :scaler scoef :base cba)) (ampenv(make-env :envelope aenv :scaler amp :base aba)) (fhp (* shp freq) ) (hpfenv(make-env :envelope henv :scaler fhp :base hba :offset .000001)) (lpfenv(make-env :envelope lenv :scaler flp :base lba :offset .000001)) (nyqst (- (/ sampling-rate 2.) 10.)) (ny_lp (- nyqst flp)) (k scoef) (kabs scoef) ) (run (loop for i from start-sample to end-sample do (setf k (env comenv) ) (setf kabs (abs k)) (setf (cmbflt-scaler komb) k) (set-butterlp lpf (if balance-kenv (- nyqst (* ny_lp kabs )) (env lpfenv) ) ) (set-butterhp hpf (if balance-kenv (* fhp kabs ) (env hpfenv) ) ) (outa i (* (env ampenv) (butterlp lpf (butterhp hpf (comb komb (readin input-sound)))))) ) ) ) )
#| A SET OF SOME VERY SIMPLE ENVELOPES |# (defvar trap1 '(0 0 33 1 66 1 100 0)) (defvar trap2 '(0 0 25 1 75 1 100 0)) (defvar trap3 '(0 0 10 1 90 1 100 0)) (defvar gate '(0 0 1 1 99 1 100 0)) (defvar triang '(0 0 50 1 100 0)) (defvar adsr1 '(0 0 5 1 5 .5 50 .5 100 0)) (defvar adsr2 '(0 0 5 1 5 .5 60 .5 100 0)) (defvar adsr3 '(0 0 5 1 5 .5 70 .5 100 0)) (defvar perc '(0 0 5 1 100 0)) (defvar fadein '(0 0 100 1)) (defvar fadeout '(0 1 100 0)) (defvar cresc1 '(0 0 90 1 100 0)) (defvar cresc2 '(0 0 80 1 100 0)) (defvar cresc3 '(0 0 70 1 100 0)) g)References -Schottstaedt, Bill: Common Lisp Music, on-line documentation (http://www-ccrma.stanford.edu) -Dodge, Ch. & Jerse, T.: Computer Music Synthesis, composition and performance, Shirmer Books, New York, 1985. -Moore, F.R.: Elements of Computer Music , Prentice Hall., New Jersey, 1990. -Moorer, A.: About this reverberation business,CMJ,vol.3, Nº2. -Steiglitz, Ken: A digital signal processing Primer, Addison Wesley, California, 1996.
|