class:: StereoConvolution2L
summary:: Stereo real-time convolver with linear interpolation
categories:: UGens>FFT, UGens>Convolution
related:: Classes/Convolution, Classes/Convolution2L

description::
Strict convolution with fixed kernel which can be updated using a trigger signal. There is a linear crossfade between the buffers upon change.

Like link::Classes/Convolution2L::, but convolves with two buffers and outputs a stereo signal. This saves one FFT transformation per period, as compared to using two copies of link::Classes/Convolution2L::.

Useful applications could include stereo reverberation or HRTF convolution.

See Steven W Smith, The Scientist and Engineer's Guide to Digital Signal Processing, chapter 18: link::http://www.dspguide.com/ch18.htm::

classmethods::
method:: ar

argument:: in
processing target.
argument:: kernelL
buffer index for the fixed kernel of the left channel, may be modulated in combination with the trigger.
argument:: kernelR
buffer index for the fixed kernel of the right channel, may be modulated in combination with the trigger.
argument:: trigger
update the kernel on a change from <= 0 to > 0.
argument:: framesize
size of FFT frame, must be a power of two (512, 1024, 2048, 4096 are standard choices).
Convolution uses twice this number internally.
Note that the convolution gets progressively more expensive to run for higher powers!
The maximum value you can use is 2^16=16384.
(This upper limit is half of "SC_FFT_MAXSIZE" defined in the SC source code.)
Larger convolutions than this can be done using link::Classes/PartConv::.
argument:: crossfade
The number of periods over which a crossfade is made. The default is 1. This must be an integer.
argument:: mul
argument:: add

examples::
code::
(
//allocate three buffers
b = Buffer.alloc(s, 2048);
c = Buffer.alloc(s, 2048);
d = Buffer.alloc(s, 2048);

b.zero;
c.zero;
d.zero;
)

(
50.do({ |it| c.set(20 * it + 10, 1.0.rand); });
3.do({ |it| b.set(400 * it + 100, 1); });
20.do({ |it| d.set(40 * it + 20, 1); });
)


(
SynthDef(\conv_test, { |out, kernel1, kernel2, t_trig = 0|
	var input, result, framesize;
	framesize = 2048; // must be a power of two
	input = Impulse.ar(1);
	result = StereoConvolution2L.ar(input, kernel1, kernel2, t_trig, framesize, 1, 0.5);
	Out.ar(out, result);
}).add
)


x = Synth(\conv_test, [\kernel1, b, \kernel2, c]);

// changing the buffer number:
x.set(\kernel1, d);
x.set(\t_trig, 1); // after this trigger, the change will take effect.
x.set(\kernel2, d);
x.set(\t_trig, 1); // after this trigger, the change will take effect.

d.zero;
40.do({ |it| d.set(20 * it + 10, 1); }); // changing the buffers' contents
x.set(\t_trig, 1); // after this trigger, the change will take effect.

x.set(\kernel1, b);
x.set(\t_trig, 1); // after this trigger, the change will take effect.

x.free;
::
