I decided to spend the first week at iii concentrating on software setups. This included looking into recent developments in SuperCollider-based live-coding systems where I was pleasantly surprised to find Steno by Julian Rohrhuber,
a little concatenative livecoding language embedded in SuperCollider, [which] makes code for combining synth graphs very short, so that writing endless chains is like writing a single long word. A word is a program. A letter is a synth.
Without going into further details, Steno
allows to write concatenative synthesis trees of (mostly simplistic) filters and sources (“quellen”) in a short yet reasonably writable string.
I pasted an already quite complex environment using my recent implementation of the Lotka-Volterra chaotic oscillator below.
One of the niceties of this system is that it makes Julian’s most recent work on “Generic additive synthesis” very easy to implement and manipulate. A paper he wrote together with Juan Sebastián Lach Lau will soon appear in the Proceedings of the International Congress on Music and Mathematics (2015). I am sure that it will appear as a link on Julian’s publication list. Curious people may contact him for a preprint.
t = Steno.push; s.boot;
// the concatenated synthesis string, i.e. "main program"
-- {(uxxxp(([xupq])xqqqqqq))u+}q
// change synthesis parameters in the fly
g = #[2, 5, 2, 9, 8].scramble * 0.005;
t.setGlobal(\h, {|args| g.wrapAt(args[\index]) * 0.125});
t.setGlobal(\h, {|args| g.wrapAt(args[\index])});
t.setGlobal(\h, {|args| g.wrapAt(args[\index]) * 16});
t.set(\x, \a, {rrand(-1, 1.0)}, \b, {rrand(-1, 1.0)}, \c, {rrand(-1, 1.0)}, \d, {rrand(-1, 1.0)} );
t.set(\x, \a, 0.0);
t.set(\x, \b, 0.0);
t.set(\x, \c, 0.0);
t.set(\x, \d, 0.0);
( // synthesis definitions
t.fadeTime = 5;
t.operator('+', { |x, y, ctl|
x * y
}, 2);
t.filter(\x, { |in, ctl|
var influence = RMS.ar(in, 10).sum;
var a = (1.5 + (\a.kr(0, 5) * influence)).clip(1.4, 2);
var b = (1.5 + (\b.kr(0, 5) * influence)).clip(1.4, 2);
var c = (0.5 + (\c.kr(0, 5) * influence)).clip(0.5, 0.7);
var d = (1.5 + (\d.kr(0, 5) * influence)).clip(1.4, 2);
var h = \h.kr(0.01, 0.1);
(
in + (LotkaVolterra.ar(
SampleRate.ir*0.5,
a, b, c, d,
h,
xi: 0.1,
mul: Line.kr(0, 1, 10)
)) * 0.2
) * ctl[\env]
});
t.filter(\p, { |in, ctl|
(
LeakDC.ar(in)
* ({
LFNoise1.kr(LFNoise1.kr(0.5).range(1, 4)).exprange(1, 14.2).lag(0, 1)
}!2)
).tanh * ctl[\env]
});
t.filter(\u, { |in, ctl|
in + Splay.ar(
SinOsc.ar(750 * [0.5, 1, 0.125, 0.75, 0.25] * 0.99)
) * ctl[\env]
});
t.filter(\q, { |in, ctl|
in * Splay.ar(
LFPulse.ar([5, 10, 5.03], (ctl[\depth]+1).reciprocal, 0.2).lag(0.1)
) * ctl[\env]
});
t.set(\q, \mix, 0.96)
)
Steno is available from within SuperCollider through the Quarks
extension system.