sclang: ServerShmInterface - try to avoid multiple destructor calls
[supercollider.git] / HelpSource / Classes / Convolution2.schelp
blob765cf1b01171b48b7e382a60f368a41bbf3e8816
1 class:: Convolution2
2 summary:: Real-time fixed kernel convolver.
3 related:: Classes/Convolution, Classes/Convolution2L, Classes/Convolution3
4 categories::  UGens>FFT, UGens>Convolution
7 Description::
9 Strict convolution with fixed kernel which can be updated using a trigger
10 signal.
13 See also  link::http://www.dspguide.com/ch18.htm::  by Steven W.
14 Smith.
17 classmethods::
19 method::ar
21 argument::in
23 Processing target.
26 argument::kernel
28 Buffer index for the fixed kernel, may be modulated in
29 combination with the trigger.
32 argument::trigger
34 Update the kernel on a change from non-positive to positive
35 value.
38 argument::framesize
40 Size of FFT frame, must be a power of two. Convolution uses twice
41 this number internally, maximum value you can give this argument
42 is 2^16 = 65536. Note that it gets progressively more expensive to run for higher powers! 512, 1024,
43 2048, 4096 standard.
46 Examples::
48 code::
49 ( // allocate three buffers
50 b = Buffer.alloc(s,2048);
51 c = Buffer.alloc(s,2048);
52 d = Buffer.alloc(s,2048);
54 b.zero;
55 c.zero;
56 d.zero;
60 50.do({ |it| c.set(20*it+10, 1.0.rand); });
61 3.do({ |it| b.set(400*it+100, 1); });
62 20.do({ |it| d.set(40*it+20, 1); });
67 SynthDef( "conv-test", { arg kernel, trig=0;
68         var input;
70         input=Impulse.ar(1);
72         //must have power of two framesize
73         Out.ar(0,Convolution2.ar(input,kernel,trig,2048, 0.5));
74 }).send(s)
79 x = Synth.new("conv-test",[\kernel,b.bufnum]);
81 // changing the buffer number:
82 x.set(\kernel,c.bufnum);
83 x.set(\trig,0);
84 x.set(\trig,1); // after this trigger, the change will take effect.
85 x.set(\kernel,d.bufnum);
86 x.set(\trig,0);
87 x.set(\trig,1); // after this trigger, the change will take effect.
89 d.zero;
90 40.do({ |it| d.set(20*it+10, 1); });// changing the buffers' contents
91 x.set(\trig,0);
92 x.set(\trig,1); // after this trigger, the change will take effect.
94 x.set(\kernel,b.bufnum);
95 x.set(\trig,0);
96 x.set(\trig,1); // after this trigger, the change will take effect.
99 // next example
100 b = Buffer.read(s, Help.dir +/+ "sounds/a11wlk01.wav");
103         { var input, kernel;
105         input=AudioIn.ar(1);
107         //must have power of two framesize
108         Out.ar(0,Convolution2.ar(input,b.bufnum,0,512, 0.5));
109          }.play;
114 // another example
116 //must have power of two framesize- FFT size will be sorted by Convolution2 to be double this
117 //maximum is currently a=8192 for FFT of size 16384
118 a=2048;
119 s = Server.local;
120 //kernel buffer
121 g = Buffer.alloc(s,a,1);
125 g.set(0,1.0);
126 100.do({arg i; g.set(a.rand, (i+1).reciprocal)});
130 // random impulse response
132         {
133         var input,inputAmp,threshhold,gate;
135 input = AudioIn.ar(1);
136 inputAmp = Amplitude.kr(input);
137 threshhold = 0.02;      // noise gating threshold
138 gate = Lag.kr(inputAmp > threshhold, 0.01);
140         Out.ar(0,Convolution2.ar(input*gate,g.bufnum,0, a, 0.5));
141          }.play;
145 // one last example
147 b = Buffer.alloc(s, 512, 1);
148 b.sine1(1.0/[1,2,3,4,5,6], true, true, true);
152         { var input, kernel;
154         input=AudioIn.ar(1);
156         //must have power of two framesize
157         Out.ar(0,Convolution2.ar(input,b.bufnum,0, 512, 0.5));
158          }.play;
163 Instead of triggering the kernel update yourself, as in the first example, you can use a UGen trigger signal to do so. In the next example, we use two Convolution2 UGens in order to continuously and smoothly change the impulse response: link::Classes/RecordBuf:: is used to record a random frequency link::Classes/Saw:: oscillator every code::trigPeriod:: seconds.
164 Right after the recording (trigPeriod gets delayed by the buffer duration link::Classes/BufDur::, using the link::Classes/TDelay:: UGen) the two convolution UGens alternatingly update their kernels (using two triggers convTrigs). At the frequency of the kernel updates a crossfader link::Classes/XFade2:: moves between conv1 and conv2, using a triangle oscillator link::Classes/LFTri:: at half the trigger frequency as a panning input. The result is a constantly shifting spectral colorization of the Dust impulses:
166 code::
167 b = Buffer.alloc( s, 2048, 1, _.zeroMsg );
169         x = { arg i_kernel, density = 100, trigPeriod = 5.0, cutOff = 1000, minFreq = 200, maxFreq = 2000;
170                 var input, trigFreq, recTrig, irSig, convTrig, convTrigs, bufFrames, conv1, conv2;
172                 input           = LPF.ar( Dust2.ar( density ), cutOff );
173                 trigFreq                = trigPeriod.reciprocal;
174                 recTrig         = Impulse.kr( trigFreq );
175                 irSig           = Saw.ar( TExpRand.kr( minFreq, maxFreq, recTrig ), 0.4 );
176                 RecordBuf.ar( irSig, i_kernel, recTrig, loop: 0, trigger: recTrig );
177                 convTrig                = TDelay.kr( recTrig, BufDur.ir( i_kernel ));
178                 // split updates across two triggers. Note that [ 1, 0 ] creates
179                 // a MultiChannel expansion!
180                 convTrigs               = PulseDivider.kr( convTrig, 2, [ 1, 0 ]);
181                 bufFrames               = BufFrames.ir( i_kernel );
182                 // create the two alternatingly updated convolution ugens
183                 #conv1, conv2   = Convolution2.ar( input, i_kernel, convTrigs, bufFrames );
185                 XFade2.ar( conv1, conv2, LFTri.kr( trigFreq * 0.5, 1 )) ! 2;
186         }.play( s, [ \i_kernel, b ]);
189 x.set( \trigPeriod, 0.1 );      // fast changes
190 x.set( \trigPeriod, 10.0 );     // slow changes
191 x.free; // delete synth