Drones, drones, drones

posted by on 2014.07.05, under Supercollider
05:

Who doesn’t like ambient drones? Ok, I guess some people might not like them.
Here’s a little code in SuperCollider to generate a kind of feedbacky ambient atmosphere. It does look involved, but it isn’t. The main thing is using Wavetable synthesis : what the method .sine1Msg does is to fill the buffer b with a sinewave (of 512 sample “period”), and its harmonics, whose number and amplitudes are specified in the array parameter of the method. Then we can “play” the wavetable with Osc.ar, which is a wavetable oscillator. Moreover, for added noisyness and ambience, I have added a bitcrusher with randomly varying samplerate and bit depth, and also a sample player playing the buffer c, which is not too loud, and just contributes to textures. You could modify it easily to load multiple samples, and choose between them. The last part involves a nice trick I learned here : basically, you stack a certain number of short time delays, and use a feedback line to simulate a reverberation effect. In particular, if the feedback parameter is 1, you get an “infinite reverb”. Very cool. Be careful not to keep feeding input in this situation, otherwise you will get the usual feedback headache! 😀

s.boot;

(
b = Buffer.alloc(s,512,1,{|z|z.sine1Msg(1.0/[1,3,5,7,9,11,13,15,17])});
c = Buffer.read(s, "/pathtothesample");

fork{
    s.sync;
~sound = {
    var sig;
    var local;
    var f = [30,60,15]*Lag.kr(TChoose.kr(Impulse.kr(0.05),[0.75, 0.5, 1]), 8);
    sig = Mix(COsc.ar(b.bufnum,f + SinOsc.ar(f*25, 0, LFTri.kr(0.01).range(0, 10)), [0.1, 0.1001, 0.2], 0.2))*0.1;
sig = sig;
sig = LeakDC.ar(Ringz.ar(sig, TChoose.kr(Impulse.kr(0.1),[88, 97, 99, 100].midicps), LFTri.kr([0.05, 0.051]).range(0.2, 0.5)));
sig = sig + Decimator.ar(sig, 48000*LFNoise0.kr(1).range(0.25, 1), TChoose.kr(Impulse.kr(4), [8, 12, 16, 24]), 0.4);
    sig = LPF.ar(sig, 3000*LFTri.kr(0.01).range(0.1, 1));
    sig = sig + (Splay.ar(Array.fill(4, {PlayBuf.ar(2, c, rrand(-0.8, 0.8), loop: 2)*0.01}), 0.5));
    sig = CombC.ar(sig, 1.0, [0.1, 0.2], LFTri.kr(0.05).range(5, 9));
       
    local = sig + LocalIn.ar(2);
    15.do({
            local = AllpassN.ar(local, 0.06, Rand(0.001, 0.06), 3)
          });
    LocalOut.ar(local*0.4);
       
    Out.ar(0, Limiter.ar(LPF.ar(local, 4000), 0.8)*EnvGen.kr(Env([0, 1, 1, 0],[3, 100, 10])));
}.play;
}
)

s.quit;

You can listen to the result here

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

Tides on the Sea of Tranquillity

posted by on 2014.03.04, under Supercollider
04:

A quick post, since it is a while I’m not updating this.
Here’s a short track, “Tides on the Sea of Tranquillity”, built around one of my favourite UGens in SuperCollider: GrainBuf. GrainBuf is a buffer granulizer which is very flexible.
The idea for the track is quite simple: there are four granulizers, which get activated at a certain point, whose parameters are controlled by the loops in the Task. In particular, the position parameter for each of them is “lagged”, so that at each change it will start from the middle of the buffer, and reach the new value in a given time. Also, the spread, pitch, and pan are jittered, to give a spacey feeling. The other important part is that the rate for the grains are controlled via the .midiratio method, which allows to vary the pitch according to a temperate scale, hence giving some harmonic consistency. To end, everything is passed to a feedback delay line with a simple compressor.
One technical point: make sure you load buffers which are mono in GrainBuf, otherwise it will fail silently! Some times ago it took me ages to figure this out (I know, the documentation says so…).
Enjoy. 😉

s.boot;

(
fork({

//Define SynthDefs for the granulizers and delay

SynthDef(\granular, {arg out = 0, buff, pos = 0, spread = 0.05, dur = 0.40, p = 0.5, t_trig = 0, rate= 1, t = 300, a = 0.1, l = 1, pa = 0, att = 6, f = 100;
    var trigger = Impulse.ar(t);
    var sp = TRand.ar((-1)*spread, spread, trigger);
    var pan = TRand.ar((-1)*p, p, trigger);
    var sig = GrainBuf.ar(1, trigger, dur, buff, rate + LFNoise0.ar(f).range(-0.01, 0.01), Lag.kr(pos, l) + sp, pan:pan);
    var env = EnvGen.kr(Env.linen(att, 4, 8), gate: t_trig, doneAction:0);
    Out.ar(out, Pan2.ar(sig*env*a, pa));
}).add;

SynthDef(\del, {arg out = 0, in, feed = 0.93;
    var sig = In.ar(in, 2) + LocalIn.ar(2);
    var delL = DelayL.ar(sig[0], 2.0, 0.2);
    var delR = DelayL.ar(sig[1], 2.0, 0.5);
    LocalOut.ar([delL, delR]*feed);
    Out.ar(out, Compander.ar(sig, sig, 0.5, 1, 0.5, 0.01, 0.3));
}).add;


// Load samples in mono buffers and create a audio bus for delay
~path = PathName(thisProcess.nowExecutingPath).pathOnly;

~del = Bus.audio(s, 2);

~buff = Buffer.readChannel(s, ~path ++ "sample/sample1.wav", channels: [0]);
~buff2 = Buffer.readChannel(s, ~path ++ "sample/sample2.wav", channels: [0]);
~buff3 = Buffer.readChannel(s, ~path ++ "sample/sample3.wav", channels: [0]);
~buff4 = Buffer.readChannel(s, ~path ++ "sample/sample4.wav", channels: [0]);
~buff5 = Buffer.readChannel(s, ~path ++ "sample/sample5.wav", channels: [0]);

s.sync; //Wait for the buffers to be loaded;

y = Synth(\del, [\in: ~del]);


// Make an array of synths to be used as voices

~synths = Array.fill(3, {Synth(\granular, [\buff: ~buff, \t_trig:0, \pos: 0.5, \rate: ([0, 4, 5, 7, 9, 12, 16, 17] - 12).choose.midiratio, \spread: 0.05, \out:~del ])});

Task({

    10.do({
        ~synths[0].set(\buff, [~buff, ~buff2, ~buff3, ~buff4, ~buff5].wchoose([0.5, 0.3, 0.1, 0.08, 0.02]), \t_trig, 1, \t, rrand(10, 400), \dur, rrand(0.020, 0.40), \pos, rrand(0.0, 0.8), \l, rrand(0.4, 4), \rate, ([0, 4, 5, 7, 9, 12, 16, 17] - 12).choose.midiratio, \spread, rrand(0.005, 0.1), \p, rrand(-0.3, 0.3), \out, ~del, \pa, rrand(-0.5, 0.5), \att, rrand(6, 9), \a, rrand(0.05, 0.1), \f, rrand(50, 150));

        rrand(4, 9).wait;
    });

        30.do({
        ~synths[0].set(\buff, [~buff, ~buff2, ~buff3, ~buff4, ~buff5].wchoose([0.5, 0.3, 0.1, 0.08, 0.02]), \t_trig, 1, \t, rrand(10, 400), \dur, rrand(0.020, 0.40), \pos, rrand(0.0, 0.8), \l, rrand(0.4, 4), \rate, ([0, 4, 5, 7, 9, 12, 16, 17] - 12).choose.midiratio, \spread, rrand(0.005, 0.1), \p, rrand(-0.3, 0.3), \out, ~del, \pa, rrand(-0.5, 0.5), \att, rrand(6, 9), \a, rrand(0.05, 0.1), \f, rrand(50, 150));

        ~synths[1].set(\buff, [~buff, ~buff2, ~buff3, ~buff4, ~buff5].wchoose([0.5, 0.3, 0.1, 0.08, 0.02]), \t_trig, 1, \t, rrand(10, 400), \dur, rrand(0.020, 0.40), \pos, rrand(0.0, 0.8), \l, rrand(0.4, 4), \rate, ([0, 4, 5, 7, 9, 12, 16, 17]).choose.midiratio, \spread, rrand(0.005, 0.1), \p, rrand(-0.3, 0.3), \out, ~del, \pa, rrand(-0.5, 0.5), \att, rrand(6, 9), \a, rrand(0.01, 0.05), \f, rrand(50, 150));

        rrand(0.1, 4).wait;

    });

            20.do({
            ~synths[0].set(\buff, [~buff, ~buff2, ~buff3, ~buff4, ~buff5].wchoose([0.5, 0.3, 0.1, 0.08, 0.02]), \t_trig, 1, \t, rrand(10, 400), \dur, rrand(0.020, 0.40), \pos, rrand(0.0, 0.8), \l, rrand(0.4, 4), \rate, ([0, 4, 5, 7, 9, 12, 16, 17] - 12).choose.midiratio, \spread, rrand(0.005, 0.1), \p, rrand(-0.3, 0.3), \out, ~del, \pa, rrand(-0.5, 0.5), \att, rrand(6, 9), \a, rrand(0.05, 0.1), \f, rrand(50, 150));

            ~synths[1].set(\buff, [~buff, ~buff2, ~buff3, ~buff4, ~buff5].wchoose([0.5, 0.3, 0.1, 0.08, 0.02]), \t_trig, 1, \t, rrand(10, 400), \dur, rrand(0.020, 0.40), \pos, rrand(0.0, 0.8), \l, rrand(0.4, 4), \rate, ([0, 4, 5, 7, 9, 12, 16, 17]).choose.midiratio, \spread, rrand(0.005, 0.1), \p, rrand(-0.3, 0.3), \out, ~del, \pa, rrand(-0.5, 0.5), \att, rrand(6, 9), \a, rrand(0.05, 0.1), \f, rrand(50, 150));

            ~synths[2].set(\buff, [~buff, ~buff2, ~buff3, ~buff4, ~buff5].wchoose([0.5, 0.3, 0.1, 0.08, 0.02]), \t_trig, 1, \t, rrand(10, 400), \dur, rrand(0.020, 0.40), \pos, rrand(0.0, 0.8), \l, rrand(0.4, 4), \rate, ([0, 4, 5, 7, 9, 12, 16, 17] + 12).choose.midiratio, \spread, rrand(0.005, 0.1), \p, rrand(-0.3, 0.3), \out, ~del, \pa, rrand(-0.5, 0.5), \att, rrand(6, 9), \a, rrand(0.05, 0.1), \f, rrand(50, 150));

        rrand(0.1, 3).wait;

    });
                10.do({
            ~synths[0].set(\buff, [~buff, ~buff2, ~buff3, ~buff4, ~buff5].wchoose([0.5, 0.3, 0.1, 0.08, 0.02]), \t_trig, 1, \t, rrand(10, 400), \dur, rrand(0.020, 0.40), \pos, rrand(0.0, 0.8), \l, rrand(0.4, 4), \rate, ([0, 4, 5, 7, 9, 12, 16, 17] - 12).choose.midiratio, \spread, rrand(0.005, 0.1), \p, rrand(-0.3, 0.3), \out, ~del, \pa, rrand(-0.5, 0.5), \att, rrand(6, 9), \a, rrand(0.05, 0.1), \f, rrand(50, 150));

        rrand(1, 3).wait;

});



}).play(quant: 4);
})
)

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

First L!vE K@ding session!

posted by on 2014.01.13, under Supercollider
13:

As promised, here’s my first live coding screencast! The video unfortunately turned out to be not very good: ffmpeg on Linux failed me miserably. I thought it was worth sharing anyways, so, here it is. 😉
Some comments: I have used some SynthDefs that I have already prepared and some samples that I have loaded beforehand. This is achieved by the tabs “initialize” and “synths” that you see in the video. This is not a “blank page” approach to live coding, but it’s what I have realized works for me, since I am more interested in improvising patterns than the actual sound synthesis (which I also did in this session, by the way). In particular, one of the SynthDefs which I am really liking is \looper, a custom made looper which allows me to capture audio from other synths and control its parameters to get nice glitchy patterns. I’m really liking it. :) On the other end, \pad_fm is a very simple pad with fm modulation. Of course, if anybody is interested in these SynthDefs I will certainly share.
Oh, also almost everything happens in ProxySpace.
Enjoy 😉

Finite fields and musical phrasings

posted by on 2013.12.20, under Supercollider
20:

In this post I want to talk about musical phrasings in algorithmic composition and algebra over finite fields. Yep, algebra, so brace yourself  :-).
I am pretty sure you have been exposed to clock arithmetic: basically, you consider integer numbers modulo a natural number p. Now, in the case p is a prime, the commutative ring \mathbb{Z}_{p} is actually a field with finite elements. There is a name for that, and it is finite field, or Galois* field.
Now consider a pxp-matrix A with entries in \mathbb{Z}_{p}\:: A will give us a map \varphi_{A} from \mathbb{Z}_{p} to itself via

\varphi_{A}(i):=\sum_{j=0\ldots p-1}(A_{ij}\:j)\:{\rm mod}\:p

where A_{ij} are the entries of A. Now, consider a function f from \mathbb{Z}_{p} to a finite set S, and consider the subgroup P of the group of permutations of p objects given by elements \pi satifying

f(\pi(i)) = f(i)

If the function f is not injective, this subgroup will be not empty. Notice that for any function f of the type above, the matrix A gives us another function A^{*}f defined as**

A^{*}f(i):=f(\varphi_{A}(i))

Now we can ask ourselves: given a function f, can we find a matrix A such that

(A^{*})^{k}f = f

for some natural number k? What this means is that we want to find a matrix such that applied k-times to the function f returns the function itself. This problem is equivalent to finding a matrix A such that

A^{k} = \pi,\quad\pi\in{P}

In the case in which the function f is injective, this coincides with the problem of finding idempotents matrices in a finite field: the fantastic thing is that they are known to exist***, and even better their number is known in many situations!
“Ok, now, what all of this has to do with musical phrasing?! No, seriously, I’m getting annoyed, what really? ”
I hear your concern, but as with almost everything in life, it’s just a matter of perspective. So, consider the set S as a set of pairs (pitch, duration) for a note. A function f above will tell us in which order we play a note and what is the duration of each note: in other words, it is a musical phrasing. By picking a matrix A, we can generate from f a new phrasing, given by the function A^{*}f, and we can reiterate the process. If A is such that it satisfies the condition above, after a finite number of steps, the phrasing will repeat. Hence, the following Supercollider code

s.boot;

SynthDef(\mall,{arg out=0,note, amp = 1;
    var sig=Array.fill(3,{|n| SinOsc.ar(note.midicps*(n+1),0,0.3)}).sum;
    var env=EnvGen.kr(Env.perc(0.01,1.2), doneAction:2);
    Out.ar(out, sig*env*amp!2);
}).add;

(
var matrix, index, ind, notes, times, n, a;

notes = [48, 53, 52, 57, 53, 59, 60] + 12;
times = [1/2, 1/2, 1, 1/2, 1/2, 1, 1]*0.5;
n = 7;
matrix = Array.fill(n,{Array.fill(n, {rrand(0, n-1);})});
index = (0..(n-1));

a = Prout({
     inf.do({
            ind = [];
           
            matrix.collect({|row|
               ind = ind ++ [(row * index).sum % n];
               ((row * index).sum % n).yield;
            });
           index = ind;
         
     });
   }); 
       
   

Pbind(*[\instrument: \mall, \index: a, \note: Pfunc({|ev| notes[ev[\index]];}), \dur:Pfunc({|ev|
 times[ev[\index]];})]).trace.play;
)

s.quit;

represents a “sonification” of the probability distribution of finding a matrix A with the properties above, for p=7. We are assuming that the various matrices have equal probability to be generated in the code above.
So, how does this sound?
Like this

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

*By the way, you should check out the life of Galois, just to crush all your stereotypes about mathematicians. 😉
**Mathematicians love these “dual” definitions.
***Apart from the identity matrix and elements of P themselves, clearly.

Ambient soundscapes

posted by on 2013.08.09, under Supercollider
09:

It’s been a while since my last post, but I’ve been busy with the release of an Ep. And work. And other things. 😉
Here’s a code for all ambient soundscape lovers, which shows the power of code based programming languages. The code is not the cleanest, but I hope you get the idea, i.e. tons of oscillators, and filters! :)
I like here that the long drones are different in textures due to the fact that the single oscillators are randomly chosen.

s.boot;

~out=Bus.audio(s,2);

//Synth definitions

SynthDef(\pad,{arg out=0,f=#[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],d=0,a=0.1;
    var sig=0;
    var sig2=SinOsc.ar(f[15],0,0.08);
    var env=EnvGen.kr(Env.linen(6,7,10),doneAction:2);
    sig=Array.fill(16,{|n| [SinOsc.ar(f[n]+SinOsc.ar(f[n]*10,0,d),0,a),VarSaw.ar(f[n]+SinOsc.ar(f[n]*10,0,d),0,0.5,a),LFTri.ar(f[n]+SinOsc.ar(f[n]*10,0,d),0,a),WhiteNoise.ar(0.001)].wchoose([0.33,0.33,0.33,0.01])});
    sig=Splay.ar(sig,0.5);
    Out.ar(out,((sig+sig2)*env)!2);
}).add;

SynthDef(\out,{arg out=0,f=0;
    var in=In.ar(~out,2);
    in=RLPF.ar(in,(8000+f)*LFTri.kr(0.1).range(0.5,1),0.5);
    in=RLPF.ar(in,(4000+f)*LFTri.kr(0.2).range(0.5,1),0.5);
    in=RLPF.ar(in,(10000+f)*LFTri.kr(0.24).range(0.5,1),0.5);
    in=in*0.5 + CombC.ar(in*0.5,4,1,14);
    in=in*0.99 + (in*SinOsc.ar(10,0,1)*0.01);
    Out.ar(out,Limiter.ar(in,0.9));
}).add;

//Choose octaves;
a=[72,76,79,83];
b=a-12;
c=b-12;
d=c-12;

//Set the main out

y=Synth(\out);

//Main progression

t=fork{
    inf.do({
        y.set(\f,rrand(-1000,1000));
        Synth(\pad,[\f:([a.choose,b.choose] ++ Array.fill(5,{b.choose}) ++ Array.fill(5,{c.choose}) ++ Array.fill(4,{d.choose})).midicps,\a:0.1/rrand(2,4),\d:rrand(0,40),\out:~out]);
        rrand(5,10).wait;})

};


t.stop;

s.quit;

Of course, you could easily generalize this to a larger number of oscillators, filters, etc.
And even more, consider this just as a base for further sound manipulation, i.e. stretch it, granulize it, etc.
Experiment. Have fun. Enjoy. :)

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

Piano, patterns and gestures

posted by on 2013.02.12, under Supercollider
12:

I always loved piano as a kid, but for life circumstances I could never study it.  Ended studying guitar instead. Here’s a little code in Supercollider, exploring piano improvisation and “gestural” phrasing.

MIDIClient.init;

~mOut = MIDIOut.new(3);

//Set the scale to be Cmajor
~scale=[0,2,4,5,7,9,11];

//Define pattern proxies which will be modified by the task t below

a=PatternProxy(Pxrand([3,3,3,1,3,3],inf));
b=PatternProxy(Pseq([1/2],inf));
r=PatternProxy(Pseq([12],inf));
n=Prand([4,8,16],inf).asStream;

t=Task({
Pdef(\x,Pbind(\type,\midi,\chan,0,
          \midiout,~mOut,
          \scale,~scale,
          \root,-12,
          \degree,Pxrand([[0,3,5],[3,5,7],[4,6,8],[5,7,11]],inf),
          \legato,1,
          \amp,[{rrand(0.6,0.8)},{rrand(0.5,0.6)},{rrand(0.5,0.6)}]*0.7,    \dur,Prand([Pseq([1,1,1,1],1),Pseq([1,1,2],1),Pseq([1,2,1],1)],inf))).play(quant:1);

Pdef(\y,Pbind(\type,\midi,\chan,0,
          \midiout,~mOut,
          \scale,~scale,
          \root,r,
          \degree,a,
          \legato,1,
          \amp,{rrand(0.5,0.6)},
\dur,b)).play(quant:1);

10.wait;

t=Task({
    inf.do({
        if (0.7.coin,{ 
         c=[[3,0,7,1,9,11,0,4],[[3,7],0,7,Rest,9,[0,11],0,4]].choose.scramble;
             r.source=Pseq([[12,24].wchoose([0.7,0.3])],inf);
         d=n.next;
             a.source=Pseq([Pxrand(c,d),Pxrand([3,3,3,1,3,3],inf)]);
             b.source=Pseq([Pseq([1/8],d),Pseq([1/2],inf)]);
           });
       rrand(3,4).wait;})}).play(quant:1);
    };
).play(quant:1);

I’ve used a PatternProxy for the various notes degrees, velocity and duration, so to be able to modify it on the fly via the Task t, which controls the improvised part.

I came later to realize that it would be probably better to use Pfindur, instead that a Pseq to release the phrasing… I’ll try that soon. 😉

The MIDI has been routed to Ableton Live, and what you can hear in the following is its standard piano instrument.

Audio clip: Adobe Flash Player (version 9 or above) is required to play this audio clip. Download the latest version here. You also need to have JavaScript enabled in your browser.

For something amazing about  coding, piano and improvisation check Andrew Sorensen work with Impromptu. Superb.

 

 

pagetop