Well… I’d remove some of the code duplication, e.g. something like
(note: a bug/limitation appears to exist in the syntax highlighter on the forum…)
// Orchestral Sound texture v1
(
s.options.numBuffers = 1024 * 32;
//increase the memory available to the server
s.options.memSize = 8192 * 128;
s.waitForBoot({
//LOAD SAMPLES //////////////////////////////////////////////////////////////////
// create data structure to load samples
var patterns = ();
var loadfunc;
if (~samples.notNil) {
~samples.do({
|key|
if (~samples[key].notNil) {
~samples[key][\buffers].do({
| buffer |
if (buffer.notNil) {
buffer.free;
};
});
};
});
};
~samples = ();
// add function to load samples
loadfunc = {
// loaded samples will be stored under samples[key]
| key, relpath, namefilter, destination, basepath="~/development/supercollider/sso/sso/Sonatina Symphonic Orchestra/Samples" |
var path = PathName(basepath +/+ relpath);
var tmp_buffers = path.entries.removeAllSuchThat({|item| item.fileName.contains(namefilter); });
var tmp_array = tmp_buffers.collect({
| item, index |
var d = ();
var string = item.fileNameWithoutExtension;
var output = string.findRegexp("[abcdefgABCDEFG]#?[0123456789]");
var noteNameAll = output[0][1];
var octNumber = noteNameAll.rotate(1)[0].asString.asInteger;
var noteName = noteNameAll[0].asString;
var isSharp = noteNameAll.contains("#"); // boolean
var midiNumber = (octNumber +1) * 12;
switch( noteName,
"c", { midiNumber = midiNumber+0; },
"d", { midiNumber = midiNumber+2; },
"e", { midiNumber = midiNumber+4; },
"f", { midiNumber = midiNumber+5; },
"g", { midiNumber = midiNumber+7; },
"a", { midiNumber = midiNumber+9; },
"b", { midiNumber = midiNumber+11; },
);
if (isSharp) {midiNumber = midiNumber + 1;};
[noteNameAll, noteName, isSharp, octNumber, midiNumber];//.debug("[fullname, note, sharp, octave, midinum]");
d[\midi] = midiNumber.asInteger;
d[\note] = noteNameAll;
d[\buffer] = Buffer.readChannel(s, item.fullPath.debug("reading file"), channels:1);
d;
});
key.debug("loading");
tmp_array.sortBy(\midi);
destination[key] = ();
destination[key][\lowest_note] = tmp_array[0][\midi];
destination[key][\buffers] = tmp_array.collect({|item| item[\buffer]; });
destination[key][\midinotes] = tmp_array.collect({|item| item[\midi]; });
destination;
};
// Load all samples
~samples = loadfunc.(\violins_1st_sus, "1st Violins", "1st-violins-sus-", ~samples);
~samples = loadfunc.(\violins_2nd_sus, "2nd Violins", "2nd-violins-sus-", ~samples);
~samples = loadfunc.(\celli_sus, "Celli", "celli-sus-", ~samples);
~samples = loadfunc.(\basses_sus, "Basses", "basses-sus-", ~samples);
~samples = loadfunc.(\oboes_sus, "Oboes", "oboes-sus-", ~samples);
~samples = loadfunc.(\bassoons_sus, "Bassoons", "bassoons-sus-", ~samples);
~samples = loadfunc.(\clarinets_sus, "Clarinets", "clarinets-sus-", ~samples);
s.sync;
SynthDef(\play_orchestra, {
|out=0,amp=0.5, gate=1, buf, rate=1.0,pan=0.0, atk=0.01, dcy=0.2, sus=0.7, rel=0.1|
var sig, env;
env = EnvGen.ar(Env.adsr(atk, dcy, sus, rel), gate, doneAction:2);
sig = Mix.ar(PlayBuf.ar(2, buf, BufRateScale.ir(buf)*rate, 1, doneAction:0));
sig = sig * amp * env;
Out.ar(out, Pan2.ar(sig, pan));
}).add;
// a synth to play buffers in a granular way
// NOTE: you will need buffers to be loaded as MONO !!!
SynthDef(\grain_buffer, {
|out=0, gate=1, amp=0.9, buf, atk=5, rel=5, rate=1, pan=0.0|
var sig, env;
var density = LFNoise0.kr(25).range(1, 5);
var trigger = Impulse.kr( density );
var pos = 0.5 + TRand.kr(trigger, -0.35, 0.35);
var length = 1 + TRand.kr(trigger, 0.25, 0.35);
env = EnvGen.kr(Env.asr(atk, 1, rel, -4), gate, doneAction:2);
sig = GrainBuf.ar(2,
trigger,
length,
buf,
rate,
pos,
2,
pan: pan);
sig = sig * amp * env;
Out.ar(out, sig);
}).add;
SynthDef(\verb, {
|out=0, mix=0.6, room=0.8, damp=0.6|
var in;
in = In.ar(out, 2);
in = FreeVerb.ar(in, mix, room, damp);
Out.ar(out, Pan2.ar(in));
}).add;
s.sync;
patterns[\violins_1st_sus] = Pbind(
\instrument, \grain_buffer,
\scale, Scale.major,
\root, Pfunc({~root}),
\octave, Pwrand([5,6,7],[1,0.5, 0.125].normalizeSum, inf),
\degree, Pxrand([1, 4, 5], inf)-1,
\index, Pfunc { |e| ((e.use{ ~midinote.()} - ~samples[\violins_1st_sus][\lowest_note] - 1)/3).floor },
\buf, Pindex(~samples[\violins_1st_sus][\buffers], Pkey(\index)),
\rate, (Pfunc{ |e| e.use {~midinote.()}} - Pindex(~samples[\violins_1st_sus][\midinotes], Pkey(\index))).midiratio,
\amp, Pwhite(0.05, 0.1, inf),
\dur, Pwhite(4,8, inf),
\type, Pwrand([\note, \rest], [1,0.25].normalizeSum, inf),
\atk, Pkey(\dur) * 0.6,
\rel, Pkey(\atk),
\out, 0,
\pan, Pwhite(-0.8, 0.2,inf)
);
patterns[\violins_2nd_sus] = Pbind(
\instrument, \grain_buffer,
\scale, Scale.major,
\root, Pfunc({~root}),
\octave, Pwhite(5,6,inf).round(1),
\degree, Pxrand([1, 4, 5], inf)-1,
\index, Pfunc { |e| ((e.use{ ~midinote.()} - ~samples[\violins_2nd_sus][\lowest_note]-1)/3).floor },
\buf, Pindex(~samples[\violins_2nd_sus][\buffers], Pkey(\index)),
\rate, (Pfunc{ |e| e.use {~midinote.()}} - Pindex(~samples[\violins_1st_sus][\midinotes], Pkey(\index))).midiratio,
\amp, Pwhite(0.05, 0.1, inf),
\dur, Pwhite(4,8, inf),
\type, Pwrand([\note, \rest], [1,0.25].normalizeSum, inf),
\atk, Pkey(\dur) * 0.6,
\rel, Pkey(\atk),
\out, 0,
\pan, Pwhite(-0.2, 0.8,inf)
);
patterns[\celli_sus] = Pbind(
\instrument, \grain_buffer,
\scale, Scale.major,
\root, Pfunc({~root}),
\octave, Pwrand([3, 4], [0.25, 1].normalizeSum, inf),
\degree, Pseq([1], inf)-1,
\index, Pfunc { |e| ((e.use{ ~midinote.()} - ~samples[\celli_sus][\lowest_note]-1)/3).floor },
\buf, Pindex(~samples[\celli_sus][\buffers], Pkey(\index)),
\rate, (Pfunc{ |e| e.use {~midinote.()}} - Pindex(~samples[\celli_sus][\midinotes], Pkey(\index))).midiratio,
\amp, Pwhite(0.1, 0.2, inf),
\dur, Pwhite(2,7, inf),
\type, Pwrand([\note, \rest], [1,0.125].normalizeSum, inf),
\atk, Pkey(\dur) * 0.6,
\rel, Pkey(\atk),
\out, 0,
\pan, Pwhite(-0.3, 0.3,inf)
);
patterns[\basses_sus] = Pbind(
\instrument, \grain_buffer,
\scale, Scale.major,
\root, Pfunc({~root}),
\octave, 3,
\degree, Pseq([1], inf)-1,
\index, Pfunc { |e| ((e.use{ ~midinote.()} - ~samples[\basses_sus][\lowest_note]-1)/3).floor },
\buf, Pindex(~samples[\basses_sus][\buffers], Pkey(\index)),
\rate, (Pfunc{ |e| e.use {~midinote.()}} - Pindex(~samples[\basses_sus][\midinotes], Pkey(\index))).midiratio,
\amp, Pwhite(0.1, 0.2, inf),
\dur, Pwhite(4,8, inf),
\type, Pwrand([\note, \rest], [1,0.125].normalizeSum, inf),
\atk, Pkey(\dur) * 0.6,
\rel, Pkey(\atk),
\out, 0,
\pan, 0.0
);
patterns[\oboes_sus] = Pbind(
\instrument, \grain_buffer,
\scale, Scale.major,
\root, Pfunc({~root}),
\octave, Pwhite(5,6,inf).round(1),
\degree, Pwrand([1,5],[0.3, 0.6], inf)-1,
\index, Pfunc { |e| ((e.use{ ~midinote.()} - ~samples[\oboes_sus][\lowest_note]-1)/3).floor },
\buf, Pindex(~samples[\oboes_sus][\buffers], Pkey(\index)),
\rate, (Pfunc{ |e| e.use {~midinote.()}} - Pindex(~samples[\oboes_sus][\midinotes], Pkey(\index))).midiratio,
\amp, Pwhite(0.1, 0.2, inf),
\dur, Pwhite(4,8, inf),
\type, Pwrand([\note, \rest], [1,0.25].normalizeSum, inf),
\atk, Pkey(\dur) * 0.6,
\rel, Pkey(\atk),
\out, 0,
\pan, Pwhite(-0.2, 0.8,inf)
);
patterns[\clarinets_sus] = Pbind(
\instrument, \grain_buffer,
\scale, Scale.major,
\root, Pfunc({~root}),
\octave, Pwhite(5,6,inf).round(1),
\degree, Pwrand([1,5],[0.3, 0.6], inf)-1,
\index, Pfunc { |e| ((e.use{ ~midinote.()} - ~samples[\clarinets_sus][\lowest_note]-1)/3).floor },
\buf, Pindex(~samples[\clarinets_sus][\buffers], Pkey(\index)),
\rate, (Pfunc{ |e| e.use {~midinote.()}} - Pindex(~samples[\clarinets_sus][\midinotes], Pkey(\index))).midiratio,
\amp, Pwhite(0.2, 0.3, inf),
\dur, Pwhite(4,8, inf),
\type, Pwrand([\note, \rest], [1,0.25].normalizeSum, inf),
\atk, Pkey(\dur) * 0.6,
\rel, Pkey(\atk),
\out, 0,
\pan, Pwhite(-0.8, 0.2,inf)
);
patterns[\bassoons_sus] = Pbind(
\instrument, \grain_buffer,
\scale, Scale.major,
\root, Pfunc({~root}),
\octave, Pwhite(4,5,inf).round(1),
\degree, Pwrand([1,5],[0.3, 0.6], inf)-1,
\index, Pfunc { |e| ((e.use{ ~midinote.()} - ~samples[\bassoons_sus][\lowest_note]-1)/3).floor },
\buf, Pindex(~samples[\bassoons_sus][\buffers], Pkey(\index)),
\rate, (Pfunc{ |e| e.use {~midinote.()}} - Pindex(~samples[\bassoons_sus][\midinotes], Pkey(\index))).midiratio,
\amp, Pwhite(0.1, 0.2, inf),
\dur, Pwhite(4,8, inf),
\type, Pwrand([\note, \rest], [1,0.25].normalizeSum, inf),
\atk, Pkey(\dur) * 0.6,
\rel, Pkey(\atk),
\out, 0,
\pan, Pwhite(-0.4, 0.4,inf)
);
~root = 0;
~ensemble = Pfx(Ppar([
patterns[\violins_1st_sus],
patterns[\violins_2nd_sus],
patterns[\oboes_sus],
patterns[\clarinets_sus],
patterns[\bassoons_sus],
patterns[\celli_sus],
patterns[\basses_sus]
],inf), \verb).asEventStreamPlayer;
~ensemble.play;
});
);
~root = 0; // also try to use 5, 7 and 9
~ensemble.play;
(
~ensemble.stop;
~samples.do({
|key|
~samples[key][\buffers].do({
| buffer |
buffer.free;
});
});
)
Since the patterns you use all look very similar, it’s possible to simplify those as well (variations on a base pattern) but I didn’t do it here, because in general I expect different patterns to be more independent.