﻿ ambient « Coding, Sounds and Colors | A blog about algorithmic experiments in music and visual art. Sort of.

## 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])});

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

## 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 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));

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));

// 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 ])});

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);
})
)

## 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);

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));

//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.