Professional Documents
Culture Documents
11.2 Analogue Modelling
11.2 Analogue Modelling
11.2 Analogue Modelling
Contents:
Avoiding aliasing; use band limited waveforms (i.e. Saw not LFSaw for higher
frequencies)
(
{
[LFSaw.ar(1000),Saw.ar(1000)]
}.plot(0.01)
)
But then, both are perfectly serviceable for low frequencies and the rougher edge
to LFSaw can be useful.
Sidenote on aliasing:
Fundamental frequencies at divisors of the sampling rate have harmonics which only
alias at harmonic locations!
//no aliasing
{Saw.ar(1102.5+(MouseX.kr(0,10).round(1)),0.5)}.scope
{Saw.ar(440,0.2)}.play //plain
{Mix(Saw.ar(440*[0.99,1.01],0.2))}.play //plain
//if want perceptual (log freq) same difference each side need 0.99 and
0.99.reciprocal, but we'll overlook that for now
//to alter phases need LFSaw; but could also just add some subtle frequency
modulation
(
{
Mix.fill(4,{
var freqmult;
//between 1 +- 0.01
freqmult= 1+SinOsc.ar(LFNoise1.kr(rrand(0.25,0.5),4,5),pi.rand,0.01);
LFSaw.ar(440*(freqmult),pi.rand,0.2)
})
}.play
)
//question for you; why don't I need to use Rand rather than rrand in this case?
(
{Mix.fill(4,
{Saw.ar(440*(1+SinOsc.ar(LFNoise1.kr(rrand(0.25,0.5),4,5),pi.rand,0.02)),0.2)}) }.p
lay
)
Comparing Filters
//standard filter
(
z = {
Resonz.ar(
Mix(Saw.ar([0.99,1,1.01]*440,0.3)),
MouseX.kr(100,20000,\exponential), // cutoff freq.
MouseY.kr(0.1, 1.0, \linear), // rq
0.5); // mul
}.play
)
z.free;
//The BEQSuite (sc3-plugins pack) has some nice filters, which take less energy
away:
(
z = {
BLowPass4.ar(
Mix(Saw.ar([0.99,1,1.01]*440,0.3)),
MouseX.kr(100,20000,\exponential), // cutoff freq.
MouseY.kr(0.1, 1.0, \linear), // rq
0.5); // mul
}.play
)
z.free;
z.free;
Triggers are used in the Demand UGen to cue a 'demand' for a new value from the
attached specialist demand rate UGens (which all begin with D and have names
analogous to patterns)
(
{var sequence = Dseq([-0.3,0.5,0.0,0.4],inf); //Dseq is demand rate
Demand.ar(Impulse.ar(10),0, sequence);
}.plot(1.0)
)
So far, similar functionality might be constructed with Select, Index, EnvGen,
IEnvGen et al
(
{var sequence = Dseq([-0.3,Drand([-1,1],1),0.0,0.4],inf); //Dseq is demand rate
Demand.ar(Impulse.ar(100),0, sequence);
}.plot(1.0)
)
Musical use:
(
{var freq, sequence = Dseq([60,Drand([48,72],1),63,62.8],inf); //Dseq is demand
rate
Saw.ar(freq, 0.1)
}.play
)
SyncSaw.ar(freq, 300,0.1);
}.play
)
[
SyncSaw.ar(freq[0], LFNoise0.kr(7,100,230),0.1),
SyncSaw.ar(freq[1], LFNoise2.kr(17,400,630),0.1)
]
}.play
)
More demanding: Duty allows you to specify a duration sequence for controlling when
the next value is demanded
//interaction of durations for holding current value and output value sequence
{Duty.ar(Dseq([0.025,0.05],inf),0,Dseq([-0.5,0.5,0,-1,1],inf))}.plot(0.6)
The next three examples are provided as more involved patches; you might want to
try to work out what is going on!
freq=
Duty.kr(Dseq([0.25,0.25,0.5,0.75,0.75,0.75,0.25,0.25,0.25]*tempo,inf),0,Dseq([60,62
,63,65,67,55,53,Drand([51,49,58,70],1),70,Drand([70, 48,72,36],1)],inf)).midicps;
filterfreq= Duty.kr(Dseq([0.25,0.25,0.25,0.25,1.0]*tempo,inf),0,Dseq(Array.fill(16,
{exprand(300,5000)}),inf));
source= Mix(SyncSaw.ar([1,0.5,0.25,1.01,
1.25]*(freq.lag(0.05)),LFNoise2.kr([0.25,0.5,1,2,4]*(tempo*2),200,300), 0.1));
filtered= BLowPass4.ar(source,filterfreq.lag(0.0625),0.5);
Pan2.ar(filtered, LFNoise1.kr(tempo,0.25))
}.play
)
//note that if you make the Duty's .ar you'll see a substantial increase in CPU
usage!
(
{
var source, filter, env;
var trig, freq, freq2;
filter= BLowPass.ar(0.5*source,300+(MouseX.kr(100,20000,'exponential')*env),0.2,
env);
//Pan2.ar(filter,0.0);
}.play
)
//using InterplEnv
(
{
var source, filter;
var freq;
freq=
IEnvGen.kr(InterplEnv([60,62,63,67,70,67,70,72,48].scramble,0.125.dup(8)),Phasor.ar
(LFNoise0.kr(1)>0,0.5*(1.0/SampleRate.ir),0.0,1.0).round(1/8)).midicps;
filter= BLowPass.ar(0.5*source,1000+(2000*EnvGen.ar(Env([0,1,0],
[0.01,0.25]),Impulse.kr(2))),0.2);
Limiter.ar(GVerb.ar(filter*0.25) + Pan2.ar(filter))
}.play
)