TITLE:: JPverb
summary:: Algorithmic reverberator, designed to produce long and rich reverberant tails.
categories:: UGens>Reverbs
RELATED:: Overviews/DEIND, Classes/Greyhole, Classes/JPverbRaw

DESCRIPTION::
image::JPverb-logo-small.png::
An algorithmic reverb, inspired by the lush chorused sound of certain vintage Lexicon and Alesis reverberation units. Designed to sound great with synthetic sound sources, rather than sound like a realistic space.

Developed as part of the LINK::Overviews/DEIND:: project.

NOTE::Please increase server realtime memory for this to work properly::
code::
s.options.memSize_(65536 * 4);
s.reboot;
::


CLASSMETHODS::
private:: categories

METHOD:: ar

note::This UGen always generates a stereo signal.::

argument::in
input to the reverb. Either an array of two audio signals (stereo), or a mono audiosignal.

argument::t60
approximate reverberation time in seconds code::(0.1..60 sec):: (code::T60:: - the time for the reverb to decay by 60db when code::damp == 0:: ). Does not effect early reflections.

argument::damp
controls damping of high-frequencies as the reverb decays. 0 is no damping, 1 is very strong damping. Values should be between code::(0..1)::.

argument::size
scales size of delay-lines within the reverberator, producing the impression of a larger or smaller space. Values below 1 can sound metallic. Values should be between code::(0.5..5)::.

argument::earlyDiff
controls shape of early reflections. Values of 0.707 or more produce smooth exponential decay. Lower values produce a slower build-up of echoes. Values should be between code::(0..1)::.

argument::modDepth
depth code::(0..1):: of delay-line modulation. Use in combination with modFreq to set amount of chorusing within the structure.

argument::modFreq
frequency code::(0..10 Hz):: of delay-line modulation. Use in combination with modDepth to set amount of chorusing within the structure.

argument::low
multiplier code::(0..1):: for the reverberation time within the low band.

argument::mid
multiplier code::(0..1):: for the reverberation time within the mid band.

argument::high
multiplier code::(0..1):: for the reverberation time within the high band.

argument::lowcut
frequency code::(100..6000 Hz):: at which the crossover between the low and mid bands of the reverb occurs.

argument::highcut
frequency code::(1000..10000 Hz):: at which the crossover between the mid and high bands of the reverb occurs.

returns::
a UGen.

EXAMPLES::

Minimal example (headphones recommended):

code::
s.options.memSize_(65536 * 4);
s.reboot;

{
	var src = SoundIn.ar(0)!2; // stereo input
	var rev = JPverb.ar(
		src,
		\t60.kr(1,           0.05),
		\damp.kr(0,          0.05),
		\size.kr(1,          0.05),
		\earlydiff.kr(0.707, 0.05),
		\mdepth.kr(5,        0.05),
		\mfreq.kr(2,         0.05),
		\lowx.kr(1,          0.05),
		\midx.kr(1,          0.05),
		\highx.kr(1,         0.05),
		\lowband.kr(500,     0.05),
		\highband.kr(2000,   0.05)
	);

	Mix([src, rev]) * 0.1;
}.play
::

code::Ndef::-based example:

code::
(
s.options.memSize_(65536 * 2);
s.reboot;

Spec.add(\t60, [0.1, 60, \exp]);
Spec.add(\damp, [0, 1]);
Spec.add(\size, [0.5, 3]);
Spec.add(\earlydiff, [0, 1]);
Spec.add(\mdepth, [0, 50]);
Spec.add(\mfreq, [0, 10]);
Spec.add(\lowx, [0, 1]);
Spec.add(\midx, [0, 1]);
Spec.add(\highx, [0, 1]);
Spec.add(\lowband, [100, 6000, \exp]);
Spec.add(\highband, [1000, 10000, \exp]);
)


Ndef(\src).clear
(
Ndef(\src, {
    //SoundIn.ar([0, 1])
    Splay.ar(Impulse.ar([1, 3, 5, 7, 9]).scramble);
});

Ndef(\reverb, {
	var src = Ndef(\src).ar * \amp.kr(1);
	src = JPverb.ar(
		src,
		\t60.kr(1,           0.05),
		\damp.kr(0,          0.05),
		\size.kr(1,          0.05),
		\earlydiff.kr(0.707, 0.05),
		\mdepth.kr(5,        0.05),
		\mfreq.kr(2,         0.05),
		\lowx.kr(1,          0.05),
		\midx.kr(1,          0.05),
		\highx.kr(1,         0.05),
		\lowband.kr(500,     0.05),
		\highband.kr(2000,   0.05)
	);
});
)

Ndef(\reverb).fadeTime = 1;
Ndef(\reverb).play
Ndef(\src).play


Ndef('reverb').set('lowx', 0.84375, 'amp', 0.66015625, 'damp', 0.671875, 'size', 0.94921875, 'highband', 4450.794062356, 't60', 16, 'mdepth', 17.96875, 'mfreq', 0.0, 'highx', 0.0, 'lowband', 2450.0822520097, 'earlydiff', 0.421875, 'midx', 0.5546875);

// Dreamverb
Ndef('reverb').set('wet', 0.9921875, 'lowx', 0.84375, 'amp', 0.66015625, 'damp', 0.31443298969072, 'size', 2.7938144329897, 'highband', 1024.0219794048, 't60', 60, 'mdepth', 4.639175257732, 'highx', 0.0, 'mfreq', 0.10309278350515, 'lowband', 2450.0822520097, 'fadeTime', 1, 'earlydiff', 0.421875, 'midx', 0.70618556701031);


Ndef('reverb').set('lowx', 0.84375, 'amp', 0.66015625, 'damp', 0.671875, 'size', 0.94921875, 'highband', 4450.794062356, 't60', 60, 'mdepth', 17.96875, 'mfreq', 0.0, 'highx', 0.0, 'lowband', 2450.0822520097, 'earlydiff', 0.421875, 'midx', 0.5546875);

Ndef('reverb').set('lowx', 0.609375, 'amp', 0.38092041015625, 'damp', 0.2890625, 'size', 0.6171875, 'highband', 7233.9416273667, 't60', 4.0375572334984, 'mdepth', 0.0, 'mfreq', 2.03125, 'highx', 0.2265625, 'lowband', 681.56675509913, 'fadeTime', 1, 'earlydiff', 0.765625, 'midx', 0.515625);

Ndef('reverb').set('lowx', 0.84375, 'amp', 0.66015625, 'damp', 0.875, 'size', 0.5, 'highband', 5829.4153471361, 't60', 0.16483258382257, 'mdepth', 17.96875, 'mfreq', 0.0, 'highx', 0.0, 'lowband', 100.0, 'fadeTime', 1, 'earlydiff', 0.703125, 'midx', 0.5546875);


Ndef(\src).edit
Ndef(\reverb).edit;
::


For the Verber piece ( see http://tai-studio.org/portfolio/verber.html ), the following source was used, code::Ndef(\hole) remains unchanged::.

code::
Ndef(\src).fadeTime = 4;
Ndef(\src).quant = 2;
Ndef(\src, {
	var src = 10.collect{
		Pan2.ar([HPF, LPF, ComplexRes].choose.performKeyValuePairs(\ar,[
			\in, [Impulse, LFPulse].choose.ar(
				[4, 2, 1, 1/2, 1/3, 1/4, 1/6].choose,
				iphase: [0, 1/4, 1/8, 1/2, 1/3].choose,
				phase: [0, 1/4, 1/8, 1/2, 1/3].choose,
				width:  [0.001, 0.0001, 0.01, 0.1, 0.2].choose,
				mul:    [1, 2, 3, 4].choose.reciprocal * [1, -1].choose
			),
			\freq, [10000, 2000, 1000, 500, 250, 125, 125/2].choose,
			\decay, [0.1, 0.2, 0.4, 1].choose,
		]
		), Rand(-1, 1));
	}.sum;
	HighShelf.ar(src, \shelfFreq.kr(1000), \shelfslope.kr(1));
})
::

note::
Since code::Impulse:: and code::LFPulse:: are chosen to be used at evaluation time, the given argument names might not match to the chosen UGen's interface. Since a superfluous argument does not affect a UGen's operation, the warnings can be ignored.
::