Monday, February 21, 2011

A Short Study In Recursive Functions


(
//define our basic sine synth, with pink noise amplitude correction: amplitude = (1/freqency)
z = Server.internal;
SynthDef("just-sine",{|freq=100,atk=0.01, rel=10, sus=(-4), amp=0.005,pan =0,gate=0, mr=1, ma=1, mm=1|
Out.ar(0,Mix.ar(Pan2.ar(FSinOsc.ar( [1,1] *.x freq,0,amp/(freq+192)),pan)) * EnvGen.ar(Env.perc(atk,rel, 1, sus),gate, doneAction:2) );}).load(z);
)


(
//recursive function to bring frequency f below 2**14 or quit after 20 tries
~pitchCorrect = {|f,s=1|
(f < (2**14)).or(s>20).if ({f;},{ ~pitchCorrect.(f / (2**((f.log2.floor)/2).ceil),s+1);});

};

//express i as an array of binary digits (redo of the .asBinaryDigits method for integers > 8 bits
~count = {|i|
({|x|((1)*(i/(2**x)%2).floor)}!i.log2.ceil).asInt[0..(i.log2/2).floor.asInt];
};


~r = Routine {
~bounce = {|p,n,s,max|
var c = ~count.(p), pc= (2**(c.sum)).asInt, ps = (c.size+1).log2.ceil;
p.postln;
pc.factors.collect({|pp,j|
var m = Synth("just-sine"), pf=p.factors.permute(p).wrapAt(j).log2.ceil;
m.set(\freq,~pitchCorrect.(pf * 40 *(n**((1+c.sum).log2.ceil%2))*(((ps+1)/ps)**(pc.factors.size+n)))+j);
m.set(\pan, 1/p.factors.size * (-1**j));
m.set(\rel,(p.factors.size+n+s).sqrt * (1/~count.(p).size.log10),\atk,(n+s)/2048,\sus,-2 * p.factors.size.log2,\amp,32 * (1/(n+1)),\gate,1);
});
(1/(n+s)).wait;

(max<0).if({^max});

(n>s).if({~bounce.(p+1,1,~count.(p+1).sum,max-1) },{~bounce.(p,n+1,s,max)});
};

//start at 1024, go for 512 steps
~bounce.(1024,1,2,512);
};
~r.play;
)

z.scope


201102211 by Backtrace