Skip to content

Instantly share code, notes, and snippets.

@lisongx
Last active March 1, 2016 12:53
Show Gist options
  • Save lisongx/d159fc9739cde58cea5d to your computer and use it in GitHub Desktop.
Save lisongx/d159fc9739cde58cea5d to your computer and use it in GitHub Desktop.
Network piece: Sinusoidal Computation

Syntdef

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...

Utils

( // 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); }) }; )

Receiver Function

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]); )

Performance

You need to do two things in the performance:

  1. 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
     );
    
  2. change all the ~next function above on the fly

Finish

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment