Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / HelpSource / Classes / PartConv.schelp
blob8b088dd6a59ac7ceb9a3a810517528b91ff0550d
1 class:: PartConv
2 summary:: Real-time partitioned convolution
3 categories:: UGens>FFT, UGens>Convolution
4 related:: Classes/Convolution, Classes/Convolution2, Classes/Convolution2L, Classes/Convolution3
6 description::
7 Partitioned convolution. Various additional buffers must be supplied.
9 Mono impulse response only! If inputting multiple channels, you'll need independent PartConvs, one for each channel.
11 But the charm is: impulse response can be as large as you like (CPU load increases with IR size. Various tradeoffs based on fftsize choice, due to rarer but larger FFTs. This plug-in uses amortisation to spread processing and avoid spikes).
13 Normalisation factors difficult to anticipate; convolution piles up multiple copies of the input on top of itself, so can easily overload.
15 classmethods::
16 method:: ar
18 argument:: in
19 processing target.
20 argument:: fftsize
21 spectral convolution partition size (twice partition size). You must ensure that the blocksize divides the partition size and there are at least two blocks per partition (to allow for amortisation).
22 argument:: irbufnum
23 prepared buffer of spectra for each partition of the inpulse response.
24 argument:: mul
25 argument:: add
27 examples::
28 code::
29 // preparation; essentially, allocate an impulse response buffer, then follow a special buffer preparation step to set up the data the plugin needs. Different options are provided commented out for loading impulse responses from soundfiles.
31 ~fftsize=2048; // also 4096 works on my machine; 1024 too often and amortisation too pushed, 8192 more high load FFT
33 s.waitForBoot {
36 var ir, irbuffer, bufsize;
38         // // MONO ONLY
39         // pre-existing impulse response sound files
40         // (could also use any general soundfile too for cross-synthesis effects)
41         // irbuffer= Buffer.read(s, "/Volumes/data/audio/ir/ir2.wav");
42         // irbuffer= Buffer.read(s, "/Volumes/data/audio/ir/ir.wav");
43         // this is a two second long hall IR
44         // irbuffer= Buffer.read(s, "/Volumes/data/audio/ir/bighall2.wav");
47         // synthesise the honourable 'Dan Stowell' impulse response
49         ir = ([1] ++0.dup(100) ++ ((1, 0.99998 .. 0).collect{|f| f =
50         f.squared.squared; f = if(f.coin){0}{f.squared}; f =
51         if(0.5.coin){0-f}{f} } * 0.1)).normalizeSum;
52         // ir.plot;
54         irbuffer = Buffer.loadCollection(s, ir);
56         s.sync;
58         bufsize= PartConv.calcBufSize(~fftsize, irbuffer);
60         // ~numpartitions= PartConv.calcNumPartitions(~fftsize, irbuffer);
62         ~irspectrum= Buffer.alloc(s, bufsize, 1);
64         ~irspectrum.preparePartConv(irbuffer, ~fftsize);
66         s.sync;
68         irbuffer.free; // don't need time domain data anymore, just needed spectral version
69 }.fork;
77 ~target= Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
78 // ~target= Buffer.read(s, "sounds/break");
82 { var input, kernel;
84 input= PlayBuf.ar(1, ~target, loop:1);
86 Out.ar(0, PartConv.ar(input, ~fftsize, ~irspectrum.bufnum, 0.5));
87  }.play;
92 // convolve with live input
95 { var input, kernel;
97 input= SoundIn.ar(0);
99 Out.ar(0, PartConv.ar(input, ~fftsize, ~irspectrum.bufnum));
100 }.play;
104 // should get back original impulse response (once every four seconds)
107 { var input, kernel;
109 input= Impulse.ar(0.25);
111 Out.ar(0, PartConv.ar(input, ~fftsize, ~irspectrum.bufnum));
112  }.play;
117 // only free buffers once you're finished with examples
118 // if you free whilst PartConv is still running, the server won't crash, but PartConv output will go to zero abruptly
120 ~irspectrum.free;
121 ~target.free;
122 currentEnvironment.clear;