# Some SuperCollider code for the bored – sinGrain

Granular synthesis with sinusoidal grains + a simple GUI.
Its a Synthdef using sinGrainB (a ugen from the SC3-plugins package) by Josh. You can set boundaries for random values for grain- amplitudes, durations, panning and frequencies. Frequency can be split, so only two frequencies are played instead of random frequencies in between the two values. Frequencies can be set using number boxes or a range slider. Grains can be triggered periodically (by choosing Impulse) or irregular (choosing Dust from the trigger menu), both use the spd slider for their speed.

```// SinGrain with Interface

(
// grain envelope
z = Env([0,1,0], [1,1], \sine).asSignal(1024);
s.sendMsg(\b_alloc, b = s.bufferAllocator.alloc(1), 1024, 1, [\b_setn, b, 0, 1024] ++ z);
)

(
SynthDef(\sinGrain, {|out=0, envbuf, gate=1, atk=0.5, dec=0.2, sus=0.9, rel=0.5, ttype=0, tspeed=5, durMin=1.25, durMax=1.5, freqType=1, freqMin=220, freqMax=220, ampMin=0.8, ampMax=1, panMin=0, panMax=0, gain=0.65|
var env, source, trigger, pan, dur, amp, freq;
trigger = Select.kr(ttype, [Impulse.kr(tspeed), Dust.kr(tspeed)]);
env = EnvGen.kr(Env.adsr(atk, dec, sus, rel), gate, doneAction:2);
amp = TRand.kr(ampMin, ampMax, trigger);
dur = TRand.kr(durMin, durMax, trigger);
pan = TRand.kr(panMin, panMax, trigger);
freq = Select.kr(freqType, [
Demand.kr(trigger, 0, Drand([freqMin, freqMax], inf)),
TRand.kr(freqMin, freqMax, trigger)
]);
source = SinGrainB.ar(trigger, dur, freq, envbuf, amp);
source = Pan2.ar(source, pan, gain);
Out.ar(out, source * env);
}).send(s);
)

/*
s.sendMsg(\s_new, \sinGrain, x=s.nextNodeID, 0, 0, \out, 0);
s.sendMsg(\n_set, \panMin, -1, \panMax, 1);
s.sendMsg(\n_set, x, \gate, 0);
*/

/**************************************** GUI ****************************************/
(
var synthNode = 3000;
w = Window("sinGrain", 370@320, false, true);
w.front;

Button(w, Rect(0, 0, 370, 40))
.states_([
["push", Color.rand, Color.rand],
["push", Color.rand, Color.rand]
])
.action_({|button|
if(button.value == 1, {
s.sendMsg(\s_new, \sinGrain, synthNode, 0, 0, \gate, 1)
},{
s.sendMsg(\n_set, synthNode, \gate, 0)
}
);
});

//Trigger type
g = EZPopUpMenu(w, Rect(-22, 50, 180, 20), "trigger");
g.addItem(\Impulse, {|a| (s.sendMsg(\n_set, synthNode, \ttype, 0))});
g.addItem(\Dust, {|a| (s.sendMsg(\n_set, synthNode, \ttype, 1))});
g.value = 0;

// Trigger speed
EZSlider(w, Rect(-22, 80, 365, 20), "spd", [0, 30, \lin, 0.1, 5].asSpec, {|slider| s.sendMsg(\n_set, synthNode, \tspeed, slider.value)}, nil, true, 60, 0, 0, 20, \horz);

StaticText(w, Rect(10, 110, 30, 20)).string_("amp");
//Amplitude Range Slider
RangeSlider(w, Rect(40, 110, 300, 20))
.lo_(0.8)
.hi_(1.0)
.action_({|amp| s.sendMsg(\n_set, synthNode, \ampMin, amp.lo, \ampMax, amp.hi)});

StaticText(w, Rect(10, 140, 30, 20)).string_("dur");
//Duration Range Slider
RangeSlider(w, Rect(40, 140, 300, 20))
.lo_(0.4)
.hi_(0.5)
.action_({|dur| s.sendMsg(\n_set, synthNode, \durMin, [0, 3.0, \lin, 0.01].asSpec.map(dur.lo), \durMax, [0, 3.0, \lin, 0.01].asSpec.map(dur.hi))});

StaticText(w, Rect(10, 170, 30, 20)).string_("pan");
//Panning Range Slider
RangeSlider(w, Rect(40, 170, 300, 20))
.lo_(0.5)
.hi_(0.5)
.action_({|pan| s.sendMsg(\n_set, synthNode, \panMin, [-1, 1.0, \lin, 0.01].asSpec.map(pan.lo), \panMax, [-1, 1.0, \lin, 0.01, 0].asSpec.map(pan.hi))});

//Trigger type
h = EZPopUpMenu(w, Rect(-13, 200, 180, 20), "split freq");
h.addItem(\split, {|a| (s.sendMsg(\n_set, synthNode, \freqType, 0))});
h.addItem(\random, {|a| (s.sendMsg(\n_set, synthNode, \freqType, 1))});
h.value = 1;

// FREQUENCY IS SET BY TWO NUMBER BOXES OR RANGE SLIDER

//Freq Min Max boxes
EZNumber(w, Rect(5, 230, 130, 20), "freq min", [20, 20000, \lin, 1, 220, "Hz"].asSpec, {|fmin| s.sendMsg(\n_set, 3000, \freqMin, fmin.value)});
EZNumber(w, Rect(150, 230, 130, 20), "freq max", [20, 20000, \lin, 1, 220, "Hz"].asSpec, {|fmax| s.sendMsg(\n_set, 3000, \freqMax, fmax.value)}, labelHeight:20);

StaticText(w, Rect(10, 260, 30, 20)).string_("freq");
//Frequency Range Slider
RangeSlider(w, Rect(40, 260, 300, 20))
.lo_(0.5)
.hi_(0.5)
.action_({|freq| s.sendMsg(\n_set, synthNode, \freqMin, [20, 20000, \exp, 1, 220].asSpec.map(freq.lo), \freqMax, [20, 20000, \exp, 1, 220].asSpec.map(freq.hi))});

// Trigger speed
EZSlider(w, Rect(-22, 290, 365, 20), "gain", [0, 1, \lin, 0.01, 0.65].asSpec, {|volume| s.sendMsg(\n_set, synthNode, \gain, volume.value)}, nil, true, 60, 0, 0, 20, \horz);

CmdPeriod.doOnce({w.close});
)
<pre>

```