BLOGGER TEMPLATES AND TWITTER BACKGROUNDS

Sunday, 28 February 2010

Drum sequencing with Patterns

This is v2 of my drum sequencer. It uses Patterns instead of a routine and therefore has a slightly more intuitve method of editing, as you can see the whole pattern laid out in a grid. There are randomised Patterns used to control the pitch of the cymbal and kick, and the decay on the hi-hat. The code could be neatened up a lot but there are way cooler things I could be doing...like...
1. Integrating a GUI to control volume/pitch/decay of different drums.
2. Create a way of selecting different patterns.
3. Create a controller to put shuffle on the hi-hats.
4. Make some GUI-editable laser sounds.
5. Integrate a bassline synthesiser.
6. Put some chords on top.
7. Make an arpeggiator...


// Kick Drum

SynthDef(\kick,
    {arg vol= 1, decay= 1, pitch= 1, filter= 1, on=0;
    var sin, pw, kik, kikfilter, volon;
    volon= vol*on;
    sin= LFTri.ar(freq: Line.kr(40,20,0.1*decay,doneAction:2)*pitch,
            add: 0, mul: 0.3*volon);
    pw= Pulse.ar(freq: 40, add: 0,
               mul: EnvGen.ar(Env.perc(0,0.07,0.3*volon)));
    kik= Mix.new([sin,pw]);
    kikfilter= LPF.ar(in: kik, freq: XLine.kr(200,30,0.1*decay)*filter);

    Out.ar(0, kikfilter)}).store  

// Snare Drum

SynthDef(\snare,
    {arg vol= 1, on= 0, decay= 1, pitch= 1, filter= 1, filter2= 1;
    var noise, filtap, volon, tri, snare, snaref, snaref2;
    volon= vol*on;
    filtap= EnvGen.ar(Env.perc(0,0.2*decay,0.2*volon,1));
    noise= WhiteNoise.ar(mul: filtap, add: Line.kr(-3.5,2,1));
    tri= Pulse.ar(freq: Line.kr(60*pitch,228,0.3,doneAction:2),
               mul: Line.kr(0.1,0.00,0.1)*volon);
    snare= noise+tri;
    snaref= HPF.ar(in: snare, freq: Line.kr(800,200,0.22)*filter);
    snaref2= LPF.ar(in: snaref, freq: Line.kr(600,1000,0.81)*filter2);
Out.ar(0, snaref*on)}).store

// Hi-hats

SynthDef(\hats,
    {arg vol= 1, decay= 1, on=0;
    var noise, filter, envel, menv,onvol;
    onvol= on*vol;
    menv= EnvGen.ar(Env.perc(0.3,0.01,1,4));
    noise= PinkNoise.ar(mul: menv*onvol*7, add: Line.kr(0,0,0.03*decay,doneAction:2));
    envel= EnvGen.ar(Env.adsr(0,0.2*decay,0.7,0.2,2900));
    filter= HPF.ar(in: noise, freq: envel);
Out.ar(0, filter)}).store

// Other thing

SynthDef(\cymbal,
    {arg vol= 0.5, decay= 1, pitch= 1, on= 0;
    var sq1, sq2, volon;
    volon= vol*on;
    sq1= Pulse.ar(freq: Line.kr(623*pitch,223,0.2*decay,doneAction:2)*pitch,
            mul: 0.3*volon);
    sq2= Pulse.ar(add: 0,
    freq:EnvGen.ar(Env.triangle(0.8*decay,300)),
        mul: 0.3*volon);
Out.ar(0, sq1*sq2)}).store


(
var clock,
hh, hhpatt, kd, kdpatt, sn, snpatt, cy, cypatt,
cypitch, hhdecay, basspitch, snrdc;
clock= TempoClock(8);
kd= Pseq([1,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,0],inf);
hh= Pseq([1,1,1,1, 1,0,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1],inf);
sn= Pseq([0,0,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0],inf);
cy= Pseq([0,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,1,0],inf);

cypitch= Pxrand([1,2,3,0.3, 1.2,0.6],inf);
hhdecay= Pseq([1,1,2,1, 1,2,1,1, 1,3,1,1, 1,2,1,1],inf);
basspitch= Pseq([2,2,3],inf);
snrdc= Prand([1,1,1,1,1,1.3],inf);

hhpatt= Pbind(    \on,Pseq([hh],inf),
    \instrument, \hats,
    \decay,Pseq([hhdecay],inf));
kdpatt= Pbind(  \on,Pseq([kd],inf),
    \instrument, \kick,
    \vol,1,\decay,4,\pitch,Pseq([basspitch],inf),\filter,115);
snpatt= Pbind( \on,Pseq([sn],inf),
    \instrument, \snare,
    \vol,1,\decay,Pseq([snrdc],inf),\pitch,5);
cypatt= Pbind( \on,Pseq([cy],inf),
    \instrument, \cymbal,
    \vol,1,\decay,1.5,\pitch,Pseq([cypitch],inf));

Ppar([hhpatt,kdpatt,snpatt,cypatt]).play(clock); )
 

Using routines

I used a routine to sequence a pattern for the drum sounds that I made. It is however horribly longwinded to make or alter the pattern. I realise now that I could have assigned each different SynthDef to a letter variable, which would have shortened the code a bit, but the overall method is unintuitive and not very elegant. After a bit of research, I found code for a simple drum machine on this website: http://superdupercollider.blogspot.com/2009/02/simple-drum-machine.html. This uses the pattern mechanism and is a lot nicer!
This is my code (using SynthDefs from the previous post):


(
Routine.new({
    inf.do({ arg i;
    var speed, speed2;
    speed=0.2;
    speed2= speed*2;
    Synth(\kick,[\vol,4,\decay,2,\pitch,2,\filter,112]);
    speed.wait;
    Synth(\hats,[\vol,3,\decay,1]);
    speed.wait;
    Synth(\hats,[\vol,3,\decay,3]);
    speed.wait;
    Synth(\hats,[\vol,3,\decay,1]);
    speed.wait;
    Synth(\snare,[\vol,1,\decay,1,\pitch,5,\filter2,0]);
    speed.wait;
    Synth(\kick,[\vol,4,\decay,2,\pitch,2,\filter,2]);
    speed.wait;
    Synth(\hats,[\vol,3,\decay,1]);
    speed.wait;
    Synth(\hats,[\vol,3,\decay,1]);
    speed.wait;
    Synth(\hats,[\vol,3,\decay,1]);
    speed.wait;
    Synth(\cymbal);
    Synth(\hats,[\vol,3,\decay,1]);
    speed.wait;
    Synth(\kick,[\vol,4,\decay,2,\pitch,1,\filter,112]);
    speed2.wait;
    Synth(\snare,[\vol,1,\decay,1,\pitch,5,\filter2,0]);
    speed.wait;
    Synth(\hats);
    speed.wait;
    Synth(\hats,[\vol,3,\decay,2]);
    speed.wait;
    Synth(\cymbal,[\pitch,1.2]);
    speed.wait;

});}).play)

Friday, 26 February 2010

Synthesising drums & creating SynthDefs for them

// Kick Drum

({
var sin, pw;

sin= SinOsc.ar(freq: Line.kr(70,40,0.1,doneAction:2),    
      add: 0, mul: 0.3);
pw= Pulse.ar(freq: 40, add: 0,
     mul: EnvGen.ar(Env.perc(0,0.07,0.2)));
Mix.new([sin,pw]);
}.play)

SynthDef(\kick,
    {arg vol= 1, decay= 1, pitch= 1, filter= 1;
    var sin, pw, kik, kikfilter;
    sin= LFTri.ar(freq: Line.kr(40,20,0.1*decay,doneAction:2)*pitch,
            add: 0, mul: 0.3*vol);
    pw= Pulse.ar(freq: 40, add: 0,
               mul: EnvGen.ar(Env.perc(0,0.07,0.3*vol)));
    kik= Mix.new([sin,pw]);
    kikfilter= LPF.ar(in: kik, freq: XLine.kr(200,30,0.1*decay)*filter);

    Out.ar(0, kikfilter)}).load(s);   

a= Synth(\kick);
b= Synth(\kick,[\vol,1,\decay,2,\pitch,2,\filter,2]);
c= Synth(\kick,[\vol,1,\decay,4,\pitch,2,\filter,115]);
d= Synth(\kick,[\vol,1,\decay,2,\pitch,9,\filter,10]);


// Snare Drum

SynthDef(\snare,
    {arg vol= 1, decay= 1, pitch= 1, filter= 1, filter2= 1;
    var noise, filtap, tri, snare, snaref, snaref2;
    filtap= EnvGen.ar(Env.perc(0,0.2*decay,0.2*vol,1));
    noise= WhiteNoise.ar(mul: filtap, add: Line.kr(-3.5,2,1));
    tri= Pulse.ar(freq: Line.kr(60*pitch,228,0.3,doneAction:2),
               mul: Line.kr(0.1,0.00,0.1)*vol);
    snare= noise+tri;
    snaref= HPF.ar(in: snare, freq: Line.kr(800,200,0.22)*filter);
    snaref2= LPF.ar(in: snaref, freq: Line.kr(600,1000,0.81)*filter2);
Out.ar(0, snaref)}).play(s)


e= Synth(\snare,[\vol,1,\decay,1.5,\pitch,5]);
f= Synth(\snare,[\vol,1,\decay,1,\pitch,0,\filter,0.19]);
g= Synth(\snare,[\vol,1,\decay,1,\pitch,5,\filter2,0]);

// Hi-hats

SynthDef(\hats,
    {arg vol= 1, decay= 1;
    var noise, filter, envel, menv;
    menv= EnvGen.ar(Env.perc(0.3,0.01,1,4));
    noise= WhiteNoise.ar(mul: menv*vol*4, add: Line.kr(0,0,0.03*decay,doneAction:2));
    envel= EnvGen.ar(Env.adsr(0,0.4*decay,0.7,0.2,2900));
    filter= HPF.ar(in: noise, freq: envel);
Out.ar(0, filter)}).play(s)

h= Synth(\hats,[\vol,3,\decay,1]);
i= Synth(\hats,[\vol,1,\decay,2]);

// Cymbals...(not quite)

SynthDef(\cymbal,
    {arg vol= 0.5, decay= 1, pitch= 1;
    var sq1, sq2;
    sq1= Pulse.ar(freq: Line.kr(623,223,0.2*decay,doneAction:2)*pitch, mul: 0.3*vol);
    sq2= Pulse.ar(add: 0,
    freq:EnvGen.ar(Env.triangle(0.8*decay,300)),
        mul: 0.3*vol);
Out.ar(0, sq1*sq2)}).play(s)

j= Synth(\cymbal);

Drum synthesis tutorials from 'The Dance Music Manual' -Snoman.

Monday, 15 February 2010

Arrays

Defining arrays
a = [1,3,5,7,9];
#[1,3,5,7,9] → fixed array;
a= Array.fill(5, {arg i; i*2+1});
a= Array.with(1,3,5,7,9);
a= Array.series(5,1,2);


x= Array.geom(10,1,2) → [1,2,4,8,16,32,64,128,256,512];
r= Array.rand(10,0,9) → Ten random numbers from 0 - 9;


Modifying/accessing arrays
a = a.add(11); → [1,3,5,7,9,11];
a.put(2,55);  →  [1,3,55,7,9];
a[2] → 55;
a.scramble →  [ 1, 3, 5, 7, 9 ]
                            [ 5, 9, 1, 3, 7 ]
                            [ 7, 3, 9, 5, 1 ]
                            [ 7, 3, 9, 5, 1 ]

(var scr;
a= Array.fill(5, {arg i; i*2+1});
scr = {arg b; b.scramble};
b = scr.value(a);
c = scr.value(b);
a.postln;b.postln;c.postln;)

a.rotate(2); → [7,9,1,3,5] (rotates array around the given index);
a; → [false,false,true,true,true];
a.reverse → [9,7,5,3,1];


Example code
({var stars, stars2, stars3, sky, waves, spacetime, heat, shine, shine2, shine3, sparkle;


x= SinOsc.ar(freq:3,mul:0.5);
waves= (Pan2.ar
(in: Resonz.ar
(in: WhiteNoise.ar(0.5), freq: SinOsc.ar(freq:0.5,mul:59,add: 200)),  
   pos: SinOsc.ar(freq:0.4, mul: 0.3)));
shine= (Pan2.ar
(in: SinOsc.ar(freq: EnvGen.ar(Env.new(
[262,262,131,131,311,311,208,208,
349,349,622,622,523,523,415,415,
1865,1865,1047,1047,622,622,523,
523,262,262,131,131,208,208,131,
131,196,196,208,208,196,196,208,
208,147,65],[0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1,0.1,0.1,0.1,0.1,0.1,0.1,
0.1,0.1,0.1,0.1,0.1,0.3],'step')),
mul: 0.3),
pos:x)); 


shine2= (Pan2.ar
(in: Saw.ar(freq: EnvGen.ar(Env.new(
[1865,1865,1047,1047,622,622,523,
523,262,262,131,131,208,208,131,
622,622,699,699,587,587,622,622,
523,523,587,587,466,466,392,392,
131,196,196,208,208,196,196,208,
208,147,65],[0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1,0.1,0.1,0.1,0.1,0.1,0.1,
0.1,0.1,0.1,0.1,0.1,0.3],'step')),
    mul: 0.3),
        pos:x));
shine3= (Pan2.ar
(in: Pulse.ar(freq: EnvGen.ar(Env.new(
[49,49,52,52,49,49,52,52,49,49,52,52,
49,49,52,52,49,49,52,52,49,49,52,52,
49,49,52,52,49,49,52,52],[0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 
0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])),
    mul: 0.7),
        pos:x));


stars= [523, 622, 1047, 1175];
stars2= [587, 466, 784, 8800];
stars3= [699, 294, 1568, 523];
heat= [x,x*0.7,x*2,x];
spacetime= Pulse.ar(freq:Line.kr(880,220,4,doneAction:2),mul:0.3);
sky= Array.fill(4,{arg i; 
SinOsc.ar(freq: stars.at(i), 
                  mul: heat.at(i), 
                  add: 0)});  
sparkle= HPF.ar(in: shine, freq: Line.kr(10,1000,4));
waves+Mix(sky)+spacetime+sparkle+shine2;}.play)


in this patch i used arrays to assign frequency and volume levels. the different 'stars' variables store different chords that can be changed manually, hopefully ill work out how to do that automatically. i have been experimenting with different code layouts to find a style that is comfortable for me, and also with naming variables. naming variables adds a whole new dimension to it all. i like the idea of making SC poetry...supercollider forces you to have a totally different perspective on how music and sound is created, and its really inspiring. it turns all of the emotional impact of music into numbers, which are infinite....so theres endless creative possibilities to be explored!
the swingOSC GUI stuff looks a bit lame but there seems to be a few people using it with processing, and the flosc project attempts to integrate supercollider with flash. but first i am going to start on my coursework...


Cool Stuff
http://peabody.sapp.org/class/st2/lab/notehz/ - frequency/pitch chart
http://www.benchun.net/flosc/

Hello World

Previous blog posts are at http://superkaleidoscope.wordpress.com/.

Wordpress sucks!