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

Voicings

posted by on 2018.04.21, under Supercollider
21:

Here’s a little exercise concerning voicings management in SuperCollider. The idea is very simple: we have a collection of samples we would like to trig randomly, but a retrig is allowed only if the whole sample has finished playing. To do this we have to keep track of active Synths (or “voices”), in order to avoid retriggering those. This role is played by the array ~voices: indeed, the index of the array identifies the buffer to be played, while a value of 0 or 1 denotes an available or unavailable voice, respectively. At the moment of the instantiation of a Synth on the server, SuperCollider allows us to assign a function to be executed when the given synth is free, which in our case sets the ~voices value corresponding to the given buffer to 0. In the infinite loop cycle we can then check for the value of ~voices at a random position i: if this value is 0, we create a new Synth with the corresponding buffer, and set the correspondent voice number to 1. Otherwise, we continue with the inf cycle. By changing the values in the rrand function you can decide how sparse the various instances will be.
You can use this technique with any type of SynthDef, in order to have a fixed voice system which does not allow retriggering or voice stealing. Also, the way I have done it is not the most elegant one: you can search for NodeWatcher (a way to monitor Nodes on the server) for an alternative approach.
Here’s the code

s.boot;



(
SynthDef(\voice, {|buff, trig = 1, out = 0, amp = 1|

    var sig = PlayBuf.ar(2, buff, 1, trig, doneAction: 2);

    Out.ar(out, sig *  amp);

 }).add;

SynthDef(\reverb, {|in = 0|
    var sig = In.ar(in, 2);
    sig = CombC.ar(sig, 0.5, 0.5, 3);
    sig = FreeVerb.ar(sig, 0.5, 0.5, 0.7);
    Out.ar(0, sig);
}).add;
)



(

fork({

var samplePath;
var ind;


    //Setting up reverb line

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

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

~voices = [];

~buffers = [];

//Loading buffers
    samplePath = thisProcess.nowExecutingPath.dirname ++ "/sounds/*";
    ~buffers = samplePath.pathMatch.collect {|file| Buffer.read(s, file, 0, 44100 * 9);};

s.sync;


~buffers.do({
    ~voices = ~voices.add(0);
});

    ind = Prand(Array.fill(~buffers.size, {|i| i}), inf).asStream;

    inf.do({
        ~voices.postln;
        i = ind.next;
       
        z = ~voices[i];

            if( (z == 0),  {

            x = Synth(\voice, [\buff: ~buffers[i], \out: ~rev, \amp: rrand(0.8, 1.0)]);
                x.onFree({~voices[i] = 0});
            ~voices[i] = 1;
           
            }, {});
   
        rrand(0.1, 0.6).wait;
        });

}).play;
)

s.quit;

All the samples have to be in a folder called “sounds” inside the same folder your .scd file is. I have used some few piano samples from Freesounds.org, since I wanted to achieve a minimalist piano atmosphere. Here’s how it sounds

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.

The Molecular Music Box in SuperCollider

posted by on 2014.08.19, under Supercollider
19:

Via Reaktor tutorials I came across this video. I have already talked about generative systems that create rich patterns (see here, and here), and how simple rules can give rise to emergent complexity.
Watch the video to know what the simple rules are in this case (and to see why it is called “molecular” :) ), or look at the following SuperCollider code, which, I must say, took me a bit more than I thought

MIDIClient.init;

~mOut = MIDIOut.new(3);

(
var seed = 48;
var degrees, deg;
var length = Pseq([4, 3], inf).asStream;
var dur = length.next();
var bars = 25;
var quant = 16;
var notes = [];
var loop = [];
var pos = [];
var next = 0;

degrees = [];

//Building the MIDI values for the white keys

9.do({|i|
degrees = degrees++([0, 2, 4, 5, 7, 9, 11] + (12*i));
});

//Starting notes from the seed

deg = Pseq(degrees, inf, degrees.indexOf(seed)).asStream;


(bars * quant).do({|i|
  var note;

    if((i%quant == 0) && (notes != []),
    {
     loop = loop.add(notes);
     notes = [];
    });

    if((i%quant == next) && (pos.includes(next) == false),{
      notes = notes.add([deg.next(), dur/4]);
      pos = pos.add(next);
      next = (next + dur)%quant;
    });

    if ( (i%quant == next) && (pos.includes(next) == true),{
     dur = length.next();
     notes = notes.add([deg.next(), dur/4]);
     next = (next + dur)%quant;
    });

   });

  loop.do({|patt, i|
      patt.postln;
      patterns = patterns++([i * 4, Pbind(*[\type,\midi,\chan,0,
         \midiout,~mOut,
        [\midinote, \dur]: Pseq(patt, inf),
        \legato: 1,
            \amp: rrand(0.1,0.5)])]);
      });

  Ptpar(patterns, 1).trace.play;
)

Notice that you can very easily change any of the rules (duration length, scale used, etc.) with a few keyboard strokes: the power of a text based programming language! :)
I have sent the output of this to the Grand Piano instrument in Ableton Live 9.
Here is the result for 4C3

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.


and here is the one for 9C14½

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