Thursday, August 14, 2008

CC3 Week 3 - Granular Synthesis

I ended up choosing the most simple example patch to work with for my granular synthesis patch. This is because I already made a buffer last semester and wanted to change. One really annoying part of this weeks exercise was how I've used the SCRangeSlider. I really should stop using this slider as it isn't designed for what I'm doing. I just prefer how it looks but it makes the process much harder. When testing my patch you need to hold down OPTION when dragging the sliders.

For this patch I have created global variables to control the parameters of the granular synthesiser and also used separate synthdefs for each waveform I have made available. There is a lot of repeated code but at this stage I don't know any other way to code this patch with the same outcome.

The colours are okay. They could be better, but with so much messing around I eventually just wanted to get this done.







(


var sbs;

~gFreqMenu = 0;
~gFreq = 80;
~gAmp = 0.05;
~gDur = 1.0;
~gWait = 0.01;

SynthDef("FSinOsc", {

// Args
arg gFreq = 440, gAmp = 1.0, gDur = 3.0;

// Vars
var osc, env, envGen, out;

// Unit Generators
osc = FSinOsc.ar(freq: gFreq);
env = Env.sine(
dur: gDur,
level: 1
);
envGen = EnvGen.ar(
envelope: env,
gate: 1,
levelScale: gAmp,
doneAction: 2
);
out = envGen * osc;

// Output
Out.ar(
bus: 0,
channelsArray: out.dup
)
}).send(s);


SynthDef("SinOsc", {

// Args
arg gFreq = 440, gAmp = 1.0, gDur = 3.0;

// Vars
var osc, env, envGen, out;

// Unit Generators
osc = SinOsc.ar(freq: gFreq);
env = Env.sine(
dur: gDur,
level: 1
);
envGen = EnvGen.ar(
envelope: env,
gate: 1,
levelScale: gAmp,
doneAction: 2
);
out = envGen * osc;

// Output
Out.ar(
bus: 0,
channelsArray: out.dup
)
}).send(s);




SynthDef("LFTri", {

// Args
arg gFreq = 440, gAmp = 1.0, gDur = 3.0;

// Vars
var osc, env, envGen, out;

// Unit Generators
osc = LFTri.ar(freq: gFreq);
env = Env.sine(
dur: gDur,
level: 1
);
envGen = EnvGen.ar(
envelope: env,
gate: 1,
levelScale: gAmp,
doneAction: 2
);
out = envGen * osc;

// Output
Out.ar(
bus: 0,
channelsArray: out.dup
)
}).send(s);





SynthDef("Pulse", {

// Args
arg gFreq = 440, gAmp = 1.0, gDur = 3.0;

// Vars
var osc, env, envGen, out;

// Unit Generators
osc = Pulse.ar(freq: gFreq);
env = Env.sine(
dur: gDur,
level: 1
);
envGen = EnvGen.ar(
envelope: env,
gate: 1,
levelScale: gAmp,
doneAction: 2
);
out = envGen * osc;

// Output
Out.ar(
bus: 0,
channelsArray: out.dup
)
}).send(s);



SynthDef("Saw", {

// Args
arg gFreq = 440, gAmp = 1.0, gDur = 3.0;

// Vars
var osc, env, envGen, out;

// Unit Generators
osc = Saw.ar(freq: gFreq);
env = Env.sine(
dur: gDur,
level: 1
);
envGen = EnvGen.ar(
envelope: env,
gate: 1,
levelScale: gAmp,
doneAction: 2
);
out = envGen * osc;

// Output
Out.ar(
bus: 0,
channelsArray: out.dup
)
}).send(s);

//w.close;


// WHOLE WINDOW
w = SCWindow.new.front;
// Parameters
w.bounds = Rect(170,150,450,380); // Rectangular Window Bounds (Bottom Left Width Height)
w.name_("Grainulator"); // Window Name
w.alpha_(0.8); // Transparency
// w.boxColor_(Color.black);


// PANEL
e = SCCompositeView(w,Rect(10,50,430,310));
e.background = Color.new255(100,0,50);
//Gradient(Color.blue,Color.black);


// DROP DOWN MENU (WAVEFORM)
l = [
"Fast Sine Wave","Sine Wave","Triangle Wave","Square Wave","Saw Tooth Wave"];
sbs = SCPopUpMenu(w,Rect(10,10,150,20));
sbs.items = l;
sbs.background_(Color.new255(100,0,50));
sbs.stringColor_(Color.white);

sbs.action = { arg sbs;
~gFreqMenu = sbs.value.postln;

};

// TEXT (FREQ)
r = SCStaticText(e, Rect(350, 80, 100, 20));
r.stringColor_(Color.white);
r.string = "Frequency";
r.font_(Font("Arial", 12));



// SLIDER (FREQ)
r = SCRangeSlider(e, Rect(30, 85, 300, 15))
.lo_(0.001)
.hi_(1)
.range_(1)
.knobColor_(HiliteGradient(Color.blue, Color.white, Color.red))
.action_({ |slider|
slider.lo=0;
r.value=""++(slider.hi*2000) ++"Hz";
~gFreq = slider.hi*2000;
r.stringColor_(Color.white);

[\sliderLOW, slider.lo, \sliderHI, slider.hi].postln;
});


// NUMBER BOX (FREQ)
r = SCTextField(
parent: e,
bounds: Rect(350, 110, 50, 15) // Left Top Width Height
).boxColor_(Color.new255(100,0,50));


// TEXT (AMP)
t = SCStaticText(e, Rect(350, 150, 100, 20));
t.stringColor_(Color.white);
t.string = "Amplitude";
t.font_(Font("Arial", 12));


// SLIDER (AMP)
t = SCRangeSlider(e, Rect(30, 85+70, 300, 15))
.lo_(0.0001)
.hi_(1)
.range_(1)
.knobColor_(HiliteGradient(Color.blue, Color.white, Color.red))
.action_({ |slider|
slider.lo=0;
t.value=""++(slider.hi*10) ++"";
~gAmp = slider.hi*10;
t.stringColor_(Color.white);

[\sliderLOW, slider.lo, \sliderHI, slider.hi].postln;
});


// NUMBER BOX (AMP)
t = SCTextField(
parent: e,
bounds: Rect(350, 180, 50, 15) // Left Top Width Height
).boxColor_(Color.new255(100,0,50));


// TEXT (DUR)
u = SCStaticText(e, Rect(350, 220, 150, 20));
u.stringColor_(Color.white);
u.string = "Duration";
u.font_(Font("Arial", 12));


// SLIDER (DUR)
u = SCRangeSlider(e, Rect(30, 225, 300, 15))
.lo_(0.001)
.hi_(1)
.range_(1)
.knobColor_(HiliteGradient(Color.blue, Color.white, Color.blue))
.action_({ |slider|
slider.lo=0;
u.value=""++(slider.hi*1) ++"s";
~gDur = slider.hi*1;
u.stringColor_(Color.white);

[\sliderLOW, slider.lo, \sliderHI, slider.hi].postln;
});


// NUMBER BOX (DUR)
u = SCTextField(
parent: e,
bounds: Rect(350, 250, 50, 15) // Left Top Width Height
).boxColor_(Color.new255(100,0,50));



// TEXT (WAIT)
p = SCStaticText(e, Rect(350, 290, 150, 20));
p.stringColor_(Color.white);
p.string = "Iteration Time";
p.font_(Font("Arial", 12));


// SLIDER (WAIT)
p = SCRangeSlider(e, Rect(30, 295, 300, 15))
.lo_(0.001)
.hi_(1)
.range_(1)
.knobColor_(HiliteGradient(Color.blue, Color.white, Color.red))
.action_({ |slider|
slider.lo=0;
p.value=""++(0.01/slider.hi*1) ++"s";
~gWait = 0.01/slider.hi*1;
p.stringColor_(Color.white);

[\sliderLOW, slider.lo, \sliderHI, slider.hi].postln;
});



// NUMBER BOX (WAIT)
p = SCTextField(
parent: e,
bounds: Rect(350, 320, 50, 15) // Left Top Width Height
).boxColor_(Color.new255(100,0,50));


)

(
Routine({
inf.do({

~gFreqMenu.switch(0,{Synth("FSinOsc", [\gFreq, ~gFreq, \gAmp, ~gAmp, \gDur, ~gDur])},
1,{Synth("SinOsc", [\gFreq, ~gFreq, \gAmp, ~gAmp, \gDur, ~gDur])},
2,{Synth("LFTri", [\gFreq, ~gFreq, \gAmp, ~gAmp, \gDur, ~gDur])},
3,{Synth("Pulse", [\gFreq, ~gFreq, \gAmp, ~gAmp, \gDur, ~gDur])},
4,{Synth("Saw", [\gFreq, ~gFreq, \gAmp, ~gAmp, \gDur, ~gDur])}
);
// Create Grain
// Synth("Pulse", [\gFreq, {rrand(80, 300).postln}, \gAmp, 0.05, \gDur, 1.0]);
// [1000, 8000] [200, 400]
// Grain Delta - 0.1, 0.01
~gWait.wait;
})
}).play;

)




[1] Christian Haines. "Creative Computing: Semester 2 - Week 3 - Granular Synthesis". Lecture presented at the Electronic Music Unit, University of Adelaide, South Australia, 14th August 2008

No comments: