Thursday, April 16, 2009

Pattern FX with Pfx

It's time to bring out my drum machine again. I've done effects with it before, but this is a new method, slightly more intuitive as you don't need to mess about with busses, it's all handled by the patterns.

(
SynthDef(\drums, {|out = 0, bassLevel = 0 , snareLevel = 0, hatLevel = 0, tomLevel = 0, pan1 = -1, pan2 = -1, pan3 = 1, pan4 = 1|

var env1, env2, env3, env4, bass, snare, hat, tom, bassOut, snareOut, hatOut, tomOut, mixer;
env1 = EnvGen.kr(Env.perc(0.001, 0.2, 1, -4), 1, doneAction:2);
env2 = EnvGen.kr(Env.perc(0.001, 0.5, 1, -1), 1, doneAction:2);
env3 = EnvGen.kr(Env.perc(0.002, 0.3, 1, -2), 1, doneAction:2);
env4 = EnvGen.kr(Env.perc(0.001, 0.1, 1, -5), 1, doneAction:2);
bass = SinOsc.ar(80) + Crackle.ar(1, 0.5);
bassOut = Pan2.ar(bass*env1, pan1, bassLevel);

snare = SinOsc.ar(120) - WhiteNoise.ar(0.5, 0.5);
snareOut = Pan2.ar(snare*env4, pan2, snareLevel);

hat = Klank.ar(`[ [ 6563, 9875 ],
[ 0.6, 0.5 ],
[ 0.002, 0.003] ], PinkNoise.ar(1));
hatOut = Pan2.ar(hat*env3, pan2, hatLevel);

tom = SinOsc.ar(440);
tomOut = Pan2.ar(tom*env4, pan4, tomLevel);

mixer = Mix.new([bassOut, snareOut, hatOut, tomOut]);


Out.ar(out, mixer);

}).store

)




Pfx, or at least it's near relation Pfxb, is currently being debated on the SC Users list so some people might be having problems with it. It seems to work fine for me with OS X, but I think it's a pretty new feature so you might need the latest SuperCollider release candidate if you want to give it a try.

This code is very closely adapted from the Pfx help file, all I've really done is bodge my drum machine sythdef onto it, but it works very well.

(
SynthDef(\echo, { arg out=0, maxdtime=0.2, dtime=0.2, decay=2, gate=1;
var env, in;
env = Linen.kr(gate, 0.05, 1, 0.1, 2);
in = In.ar(out, 2);
XOut.ar(out, env, CombL.ar(in * env, maxdtime, dtime, decay, 1, in));
}, [\ir, \ir, 0.1, 0.1, 0]).store;

SynthDef(\distort, { arg out=0, pregain=40, amp=0.2, gate=1;
var env;
env = Linen.kr(gate, 0.05, 1, 0.1, 2);
XOut.ar(out, env, (In.ar(out, 2) * pregain).distort * amp);
}, [\ir, 0.1, 0.1, 0]).store;

SynthDef(\wah, { arg out=0, gate=1;
var env, in;
env = Linen.kr(gate, 0.05, 1, 0.4, 2);
in = In.ar(out, 2);
XOut.ar(out, env, RLPF.ar(in, LinExp.kr(LFNoise1.kr(0.3), -1, 1, 200,
8000), 0.1).softclip * 0.8);
}, [\ir, 0]).store;
)


(




a = Pseq ([1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]);
b = Pseq ([0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0]);
c = Pseq ([0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0]);
d = Pseq ([0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1]);
e = Pwhite (0.14, 0.16, inf);

p = Pbind(
\instrument, \drums,
\dur, e,
\bassLevel, Pseq ([a], inf),
\snareLevel, Pseq ([b], inf),
\hatLevel, Pseq ([c], inf),
\tomLevel, Pseq ([d], inf)

);


q = Pfx(p, \echo, \dtime, 0.02, \decay, 0.1);

r = Pfx(q, \distort, \pregain, 20, \amp, 0.25);

o = Pfx(r, \wah).play;
)






Pfx takes a pattern and the name of the effect synthdef as arguemnts, then the names and the arguments you'd usually pass to the synthdef to control it. Pfx then takes the patern you've specified and plays it through the effect you've given it.

As shown in the above code, you can easily nest Pfx patterns to layer on more effects. I've got my original drum machine pattern defined as normal then I've passed it to a Pfx named q, then passed that new pattern on to r and then o, so I end up with my initially defined pattern passed through three effects.

Sounds dubesque.

1 comment:

  1. Nice sounds! When I started using SuperCollider I wanted to know how to make a step sequencer, I wish someone had just told me how to do it with patterns. This is a nice way of doing it. I like the fact that you can alter the patterns while they're playing, like this:

    a.list = [1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]

    b.list = [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1 ]

    ReplyDelete