Boot the server to get started.
s.boot;
For this lesson, we will work with audio files. If you are working in the SC IDE, execute the first cell. If you are using the notebook, copy and paste the path to the lecture folder that has glassHits.aiff and this file.
~lectureFolder = thisProcess.nowExecutingPath.dirname;
~lectureFolder = "/Users/andrewdavis/Wellesley/CS203/lecture_materials/delay/code" // The path to your glass hit as a string
Load the Buffer
~glassHitBuf = Buffer.read(s, ~lectureFolder +/+ "glassHit.aiff");
Test to see if the glass plays properly.
SynthDef(\play, {
arg out = 0, bufnum;
Out.ar(out, PlayBuf.ar(2, bufnum, doneAction: 2));
}).add;
Synth(\play, [\bufnum, ~glassHitBuf]); // Execute to play
A basic feedforward comb filter can be made by taking a sound source and adding it to a delayed copy of itself. It is simply an echo of the sound. The simplest way to implement a feedforward comb filter is using DelayN. DelayN
requires an input signal, an argument for the maximum possible delay, the delay time, and a multiplicative factor to scale the delayed time.
SynthDef(\simpleDelay, {
// Outputs a stereo signal and accepts a stereo signal as input
arg out = 0, delayTime = 0.5, g_f = 0.4, in;
var sig, sigDelayed;
sig = In.ar(in, 2);
sigDelayed = DelayN.ar(sig, 1, delayTime, g_f);
Out.ar(out, sig + sigDelayed);
}).add;
~delayBus = Bus.audio(s, 2);
~delay = Synth(\simpleDelay, [\in, ~delayBus]);
Synth(\play, [\bufnum, ~glassHitBuf, \out, ~delayBus]); // Execute and listen for the echo
~delayBus.free;
~delay.free;
The example below uses multiple feedforward delays to create a more complex echo effect.
SynthDef(\multiDelay, {
// Outputs a stereo signal and accepts a stereo signal as input
arg out = 0, delayTime = 0.4, delayAmp = 0.4, in;
var sig, sigDelayed;
sig = In.ar(in, 2);
sigDelayed = 0;
10.do({
arg index;
sigDelayed = sigDelayed + DelayN.ar(sig, 1, (0.3 * (index/2)), delayAmp/(index + 1));
});
Out.ar(out, sigDelayed);
}).add;
UGens like DelayN use dynamically allocated buffers to store data to be played back later as is typical for a delay. If you plan to use a lot of DelayN's or other UGens that use such memory allocation, then I strongly recommend increasing the server's memory storage for such UGens. This is a common case for the error "exception in real time: alloc failed".
s.options.memSize_(2.pow(16));
s.reboot;
~delayMultiBus = Bus.audio(s, 2);
~delayMulti = Synth(\multiDelay, [\in, ~delayMultiBus]);
Any buffers you allocated will need to be reloaded if you reboot. Therefore, it's a good idea to set the memory size before you start working.
~glassHitBuf = Buffer.read(s, ~lectureFolder ++ "/glassHit.aiff");
Synth(\play, [\bufnum, ~glassHitBuf, \out, ~delayMultiBus]);
~delayMultiBus.free;
~delayMulti.free;
With feedback comb filtering, the input signal is recursively delayed creating an infinite echo effect. When the delay time is small, the delay can create resonant peaks in the frequency spectrum. The effect is particularly palpable on a signal with a flat frequency spectrum like white noise.
SynthDef(\noise, {
arg out = 0, amp = 0.1;
Out.ar(out, WhiteNoise.ar(amp)!2);
}).add;
~noise = Synth(\noise);
~noise.free
SynthDef(\fbComb, {
arg out = 0, delayTime = 0.2, decayTime = 1, in;
var sig, sigCombed;
sig = In.ar(in, 2);
sigCombed = CombN.ar(sig, 2, delayTime, decayTime);
Out.ar(out, sigCombed);
}).add;
Create an infinite series of echoes of a distance of 0.2 seconds for the glass hit.
~combBus = Bus.audio(s, 2);
// Extend the decay time to make it longer
~comb = Synth(\fbComb, [\in, ~combBus, \decayTime, 3]);
Synth(\play, [\bufnum, ~glassHitBuf, \out, ~combBus]);
~combBus.free;
~comb.free;
~combBus = Bus.audio(s, 2);
~noise = Synth(\noise, [\out, ~combBus]);
~comb = Synth(\fbComb, [\in, ~combBus], ~noise, \addAfter);
Bringing the delay time down amplifies the effect. The delay time controls where the harmonic resonant peaks lie.
~comb.set(\delayTime, 0.005); // Slowly bring the delay time down to 0.005
The decay time controls how strong the resonant peaks are. Bring this up slowly.
~comb.set(\decayTime, 5); // Bring slowly up to 5
Free all synths and busses.
~combBus.free;
~noise.free;
~comb.free;
The End