/* Comb filters */ // fixed comb using internal feedback loop // LocalIn, LocalOut ( ~comb = CtkSynthDef(\comb, {arg dur, buffer, playbuffer, amp, freq, gain; var env, sig, tap, feedin, delaytime; env = EnvGen.kr( Env([0, amp, amp, 0], [0.05, dur - 0.1, 0.05]), doneAction: 2); // feedback input feedin = LocalIn.ar(1); // make delay time the wanted period delaytime = freq.reciprocal; // read signal form buffer sig = PlayBuf.ar(1, playbuffer); // record both input signal and feedback into delay line RecordBuf.ar(sig + (feedin * gain), buffer); // tap delay line // the feedback loop will have a delay of 1 control period. Adjust for it here. tap = Tap.ar(buffer, 1, delaytime - ControlRate.ir.reciprocal); // send signal out the feedback loop LocalOut.ar(tap); // send signal to output Out.ar(0, tap * env); }); ) // variable comb length using CombC UGen: // CombC.ar(in, maxdelaytime, delaytime, decaytime, mul, add) // CombC takes a decaytime (where the above example used a gain coefficient). // To convert between a decaytime to -60dB and a gain value, you can use the following formula: // // decayTime60 = (-60.dbamp.log2 * delaytime) / gain.log2) // // or: // // (0.001.log2 * 0.001) / 0.995.log2; // => 0.024011768338953 ( ~combvar = CtkSynthDef(\combvar, {arg dur, buffer, playbuffer, amp, freq1, freq2, gain1, gain2, skiptime; var env, sig, comb, maxdeltime, decaytime, delaytime, gain; env = EnvGen.kr( Env([0, amp, amp, 0], [0.05, dur - 0.1, 0.05]), doneAction: 2); // change delay time form freq1 to freq2 using exponential curve delaytime = XLine.kr(freq1.reciprocal, freq2.reciprocal, dur); // calculate the maxdelaytime for CombC maxdeltime = freq1.reciprocal.max(freq2.reciprocal); gain = Line.kr(gain1, gain2, dur); // turn gain vals into ringtimes // here we calculate the exponential decay time to -60 dB decaytime = (-60.dbamp.log2 * delaytime) / gain.log2; // play signal from buffer, can skip into it by skiptime seconds sig = PlayBuf.ar(1, playbuffer, startPos: skiptime * BufSampleRate.kr(playbuffer)); // use CombC for variable delay comb = CombC.ar(sig, maxdeltime, delaytime, decaytime); Out.ar(0, comb * env); }) ) // create new CtkScore ~score = CtkScore.new; // create buffers and add them to the score ~buf_1 = CtkBuffer(size: 32768).addTo(~score); ~buf_2 = CtkBuffer.playbuf("~/Snd/ferry.aiff".standardizePath).addTo(~score); // add notes to the score ~comb.new(0.0, 10).dur_(10).buffer_(~buf_1).playbuffer_(~buf_2).amp_(0.5).freq_(400).gain_(0.995).addTo(~score); ~combvar.new(11.0, 10).dur_(10).buffer_(~buf_1).playbuffer_(~buf_2).amp_(0.5).freq1_(1000).freq2_(500).gain1_(0.5).gain2_(0.995).skiptime_(0).addTo(~score); // we need to set the control period to 1 for this example o = ServerOptions.new.numOutputBusChannels_(1).blockSize_(1); // write sound file out ~score.write("~/Desktop/comb.aiff".standardizePath, options: o); Player.new("~/Desktop/comb.aiff".standardizePath).gui;