LFGauss Gaussian function oscillator
LFGauss.ar(duration, width, iphase, loop, doneAction)
A non-band-limited gaussian function oscillator. Output ranges from minval to 1.
LFGauss implements the formula: f(x) = exp(squared(x - iphase) / (-2.0 * squared(width)))
where x is to vary in the range -1 to 1 over the period dur. minval is the initial value at -1
duration duration of one full cycle ( for freq input: dur = 1 / freq )
width relative width of the bell. Best to keep below 0.25 when used as envelope. (default: 0.1)
iphase initial offset (default: 0)
loop if loop is > 0, UGen oscillates. Otherwise it calls doneAction after one cycle (default: 1)
doneAction doneAction, which is evaluated after cycle completes (2 frees the synth, default: 0).
See UGen-doneActions for more detail.
Some plots:
s.boot ;
// a 0.1 second grain
{ LFGauss.ar(0.1, 0.12) }.plot(0.1);
// shifting left
{ LFGauss.ar(0.1, 0.12, -1, loop: 0) }.plot(0.1);
// moving further away from the center
{ LFGauss.ar(0.1, 0.12, 2) }.plot(0.2);
// several grains
{ LFGauss.ar(0.065, 0.12, 0, loop: 1) }.plot(0.3);
Some calculations:
assuming iphase = 0:
minval for a given width: minval = exp(-1.0 / (2.0 * squared(width)))
width for a given minval: width = sqrt(-1.0 / log(minval))
width at half maximum (0.5): (2 * sqrt(2 * log(2)) * width) = ca. 2.355 * width
// minval for a width of 0.1:
(exp(1 / (-2.0 * squared(0.1)))) // 2e-22
// maximum width for a beginning at -60dB:
// we want the beginning small enough to avoid clicks
sqrt(-1 / ( 2 * log(-60.dbamp))) // 0.269
// minval for width of 0.25
(exp(1 / (-2.0 * squared(0.25)))).ampdb // -70dB
// maximum is always 1:
{ LFGauss.ar(0.1, XLine.kr(1, 0.03, 1), 0, loop: 1) }.plot(1);
// a gauss curve in sclang:
(0..1000).normalize(-1, 1).collect(_.gaussCurve(1, 0, 0.1)).plot;
// rescale the function to the range 0..1
(
{
var width = XLine.kr(0.04, 1.0, 1);
var min = (exp(1.0 / (-2.0 * squared(width))));
var gauss = LFGauss.ar(0.1, width, loop: 1);
gauss.linlin(min, 1, 0, 1);
}.plot(1)
);
// range does the same implicitly
(
{
var width = XLine.kr(0.04, 1.0, 1);
LFGauss.ar(0.1, width, loop: 1).range(0, 1);
}.plot(1)
);
Sound examples:
// modulating duration
{ LFGauss.ar(XLine.kr(0.1, 0.001, 10), 0.03) * 0.2 }.play;
// modulating width, freq 60 Hz
{ LFGauss.ar(1/60, XLine.kr(0.1, 0.001, 10)) * 0.2 }.play;
// modulating both: x position is frequency, y is width factor.
// note the artefacts due to alisasing at high frequencies
{ LFGauss.ar(MouseX.kr(1/8000, 0.1, 1), MouseY.kr(0.001, 0.1, 1)) * 0.1 }.play;
// LFGauss as amplitude modulator
{ LFGauss.ar(MouseX.kr(1, 0.001, 1), 0.1) * SinOsc.ar(1000) * 0.1 }.play;
// modulate iphase
{ LFGauss.ar(0.001, 0.2, [0, MouseX.kr(-1, 1)]).sum * 0.2 }.scope;
// for very small width we are "approaching" a dirac function
{ LFGauss.ar(0.01, SampleDur.ir * MouseX.kr(10, 3000, 1)) * 0.2 }.play;
// dur and width can be modulated at audio rate
(
{ var dur = SinOsc.ar(MouseX.kr(2, 1000, 1) * [1, 1.1]).range(0.0006, 0.01);
var width = SinOsc.ar(0.5 * [1, 1.1]).range(0.01, 0.3);
LFGauss.ar(dur, width) * 0.2
}.play
);
// several frequecies and widths combined
(
{
var mod = LFGauss.ar(MouseX.kr(1, 0.07, 1), 1 * (MouseY.kr(1, 3) ** (-1..-6)));
var carr = SinOsc.ar(200 * (1.3 ** (0..5)));
(carr * mod).sum * 0.1
}.play;
)
// test spectrum
(
{
var son = LeakDC.ar(LFGauss.ar(0.005, 0.2));
BPF.ar(son * 3, MouseX.kr(60, 2000, 1), 0.05)
}.play;
)
Gabor Grain:
(
var freq = 1000;
var ncycles = 10;
var width = 0.25;
var dur = ncycles / freq;
{
var env = LFGauss.ar(dur, width, loop: 0, doneAction: 2);
var son = FSinOsc.ar(freq, 0.5pi, env);
son
}.plot(dur);
)
(
SynthDef(\gabor, { |out, i_freq = 440, i_sustain = 1, i_pan = 1, i_amp = 0.1, i_width = 0.25 |
var env = LFGauss.ar(i_sustain, i_width, loop: 0, doneAction: 2);
var son = FSinOsc.ar(i_freq, 0.5pi, env);
OffsetOut.ar(out, Pan2.ar(son, i_pan, i_amp));
}).add;
)
// modulating various parameters
(
Pdef(\x,
Pbind(
\instrument, \gabor,
\freq, Pbrown(step:0.01).linexp(0, 1, 100, 14000),
\dur, Pbrown().linexp(0, 1, 0.004, 0.02),
\legato, Pbrown(1, 3, 0.1, inf),
\pan, Pwhite() * Pbrown()
)
).play
)
// modulating width only
(
Pdef(\x,
Pbind(
\instrument, \gabor,
\freq, 1000,
\dur, 0.01,
\width, Pseg(Pseq([0.25, 0.002], inf), 10, \exp),
\legato, 2
)
).play
)
// compare with sine grain.
(
SynthDef(\gabor, { |out, i_freq = 440, i_sustain = 1, i_pan = 1, i_amp = 0.1, i_width=0.25 |
var env = EnvGen.ar(Env.sine(i_sustain * i_width), doneAction: 2);
var son = FSinOsc.ar(i_freq, 0.5pi, env);
OffsetOut.ar(out, Pan2.ar(son, i_pan, i_amp));
}).add;
)