Each one has two synthdef:
Tadashi: \sin1, \sin2
Sean: \sin3, \sin4
Chris: \sin5, \sin6
Liew: \sin7, \sin8
The Synthdef has the folling signature: SynthDef(\sinx, {|out=0, freq=50, amp=0.3, pan=0, dur=20|
You can only use SinOsc ugen as sound source (Also Env, Pan, Out, Rand..etc related ugen), no filter, reverb...
( // every one's node need has different range
var idRangeStart = 10000, idRangeEnd = 14000; var nodeId = idRangeStart; ~getNodeId = { if(nodeId == idRangeEnd, { nodeId = idRangeStart; }, { nodeId = (nodeId + 1); }) }; )
This is the oscdef where you receive a msg. When you receive a msg, you need to calculate the next params for the node.(synth name, amp, freq, dur, etc. (The limitation will explain in next section) waitTime is the time after you init the synth, how long do you wait to pass it to another person. count is the passing count the message will pass, when it became 0, this will not pass to the next person, the event has finish.
( OSCdef(\receivcer, {|msg, time, addr, recvPort| if(msg[1] == ('/trig/' ++ ~me.value()).asSymbol, { var synthName, synthIndex, waitTime, freq, dur, amp, pan, count; synthIndex = msg[2]; waitTime = msg[3]; freq = msg[4]; dur = msg[5]; amp = msg[6]; pan = msg[7]; count = msg[8];
synthIndex = ~nextSynth.value(synthIndex);
waitTime = ~nextWaitTime.value(waitTime);
freq = ~nextFreq.value(freq);
dur = ~nextDur.value(dur);
amp = ~nextAmp.value(amp);
pan = ~nextPan.value(pan);
synthName = ('sin' ++ synthIndex).asSymbol;
"oschub sine: receiving msg".postln;
(synthName: synthName,
pan:pan,
amp:amp,
dur:dur,
freq:freq,
waitTime:waitTime).postln;
~oscHub.sendMsg(
"/s_new", synthName, ~getNodeId.value(), 0, 1,
\freq, freq,
\dur, dur,
\amp, amp,
\pan, pan
);
if( (dur > 0.0001) && (amp > 0.0001) && (count > 0) , {
fork {
var next = ~nextPerson.value();
('sending msg to ' ++ next).postln;
waitTime.wait;
// send the messgae to next person
~oscHub.sendMsg(
"/h_comm", "/trig/" ++ next,
synthIndex,
waitTime,
freq,
dur,
amp,
pan,
count-1 // passing count minus one every time
);
};
}); }, { "ignoreing".postln; }); },'/h_comm'); )
In the performance: you can start a event at any time, but sending msg to "/h_comm", the first argument means the person receive the function. For example, I will tadashi a msg:
~oscHub.sendMsg(
"/h_comm", "/trig/tadashi",
3, //synthIndex, in this case the synth is \sin3
10, //waitTime
100, //freq
20, //dur
0.3, //amp
0, //pan
10, //passing count, it will passing around players, it will make 10 synth node in total
);
Config, each player will inplement their own ~next function, and you can change it at anytime during the performance.
( // your name ~me = 'sean';
// next synth number ~nextSynth = {|index| var ret; ret = rrand(1, 4); if(index==4, { ret = [2,3,4].wchoose([0.2, 0.5, 0.3]); }); if(index==3, { ret = [1,3,4].wchoose([0.3, 0.4, 0.3]); }); if(index==2, { ret = [1,2,4].wchoose([0.3, 0.2, 0.5]); }); if(index==1, { ret = [1,2,3].wchoose([0.1, 0.45, 0.45]); }); ret; };
// wait time between the two event must be larger than current value, but when it's go beyond 60, it back to 1 ~nextWaitTime = {|waitTime| waitTime = waitTime + rrand(2, 5);
// new rules if (waitTime > 60 ,{ waitTime = 1; });
waitTime; };
// next freq, must be different from current value
~nextFreq = {|freq| if(freq < 500, { if (freq < 30, { rrand(300, 10000); }, { freq + exprand(10.0, 200); }) }, { if(freq > 5000, { freq/100 + rand(10.0); }, { freq + rrand(200.0, 2000); }) }) };
// next duratioon, need to be lower every time. ~nextDur = {|dur| if(dur < 40, { dur = dur / ([1.05, 1.1, 1.25, 1.95].wchoose([0.2, 0.4, 0.3, 0.1])); }, { dur/([1.05, 1.2, 1.3, 2.2].choose); }) };
// next amp, need to be lower every time ~nextAmp = {|amp| amp/([1.05, 1.1, 1.5, 2.1, 3.5].wchoose([0.5, 0.3, 0.1, 0.05, 0.05])); };
// next pan, has no limitation ~nextPan = {|pan| if(pan < 0, { pan + rrand(0.6, 0.8); }, { pan - exprand(0.02, 0.5); }); };
~nextPerson = ['tadashi', 'chris', 'liew'].wchoose([0.4, 0.1, 0.5]); )
You need to do two things in the performance:
-
start a event by send a msg to another people
~oscHub.sendMsg( "/h_comm", "/trig/tadashi", 3, //synthIndex, in this case the synth is \sin3 10, //waitTime 100, //freq 20, //dur 0.3, //amp 0, //pan 10, //passing count, it will passing around players, it will make 10 synth node in total );
-
change all the ~next function above on the fly
I'm thinking we can only start trigger events at first 15 minutes or so. You can still change the ~next function, the sound will faded out slowly.