//SLUGens released under the GNU GPL as extensions for SuperCollider 3, by Nick Collins, http://composerprogrammer.com/index.html

GravityGrid2 dynamical system simulation (Newtonian gravitational force)

GravityGrid2.ar(reset, rate, newx, newy, bufnum, mul, add)

Fixed masses apply Newtonian gravitational force dynamics to a central moving mass which cannot escape the [-1, 1] grid in x or y. The position of the moving mass is sonified as an oscillator by its distance from the centre.

This is a relatively expensive oscillator to run.

reset- Restart the moving mass at a random position within the square (k-rate input)

rate- amount of position update per sample (k-rate)

newx- kr input to be sampled for new x positions for the moving mass on reset

newy- kr input to be sampled for new y positions for the moving mass on reset

bufnum- Bufnum for a buffer containing weights and positions for the fixed influencing masses. In the format entry [0] is the number of masses, then 3 components (x, y, mass multiplier) for each mass in turn (see below). You can dynamically change this buffer as long as the data contents stay consistent- i.e. if you change suddenly to having twice as many masses, make sure you've provided x,y and weight values for them!

b = Buffer.alloc(s, 1+(25*3), 1); //mass buffer big enough for up to 25 masses

b.setn(0,[5]++(Array.fill(5,{[1.0.rand2,1.0.rand2,rrand(0.1,1.0)]}).flatten)); //set weights

{Pan2.ar(GravityGrid2.ar(Impulse.kr(1),MouseX.kr(0.1,1,'exponential'),LFNoise0.kr(1,0.8),LFNoise0.kr(1,0.8), b.bufnum),0.0)}.play

(

var n;

n=rrand(1,20); //random number of masses

b.setn(0,[n]++(Array.fill(n,{[1.0.rand2,1.0.rand2,rrand(0.1,1.0)]}).flatten)); //change weights to new random values

)

{Pan2.ar(GravityGrid2.ar(Impulse.kr(MouseY.kr(1,1000,'exponential')),MouseX.kr(0.1,1,'exponential'),LFNoise0.kr(1,0.8),LFNoise0.kr(1,0.8), b.bufnum),0.0)}.play

//lower gravity

(

var n;

n=rrand(1,20); //random number of masses

b.setn(0,[n]++(Array.fill(n,{[1.0.rand2,1.0.rand2,0.01*rrand(0.1,1.0)]}).flatten)); //change weights to new random values

)

{Pan2.ar(GravityGrid2.ar(Impulse.kr(0),MouseX.kr(0.1,10,'exponential'),LFNoise0.kr(1,0.8),LFNoise0.kr(1,0.8), b.bufnum),0.0)}.play

(

//deliberate corners

b.setn(0,[4]++(Array.fill(4,{arg i; [if(i<2,1,-1),if(i%2==0,1,-1),0.1*rrand(0.1,1.0)]}).flatten)); //set weights

)

(

//deliberate corners further away

b.setn(0,[4]++(Array.fill(4,{arg i; [if(i<2,rrand(1,2.3),-1),if(i%2==0,1,rrand(-1.1,-1.5)),0.1*rrand(0.1,1.0)]}).flatten)); //set weights

)

//very fun and noisy!

{Pan2.ar(GravityGrid2.ar(Impulse.kr(0),MouseX.kr(1,1000,'exponential'),LFNoise0.kr(1,0.8),LFNoise0.kr(1,0.8), b.bufnum),0.0)}.play

//if something fun turns up in the four mass version

b.getn(0,13,{arg in; in.postln;})

//here's one I made earlier

b.setn(0, [ 4, 1, 1, 0.029076481238008, 1, -1, 0.061766054481268, -1, 1, 0.096376851201057, -1, -1, 0.09320655465126 ])

//and another

b.setn(0, [ 4, 1.4228951931, 1, 0.080506414175034, 1.3617297410965, -1.3782749176025, 0.027821443974972, -1, 1, 0.038790885359049, -1, -1.3663036823273, 0.047782249748707 ])

//higher gravity but larger placement area outside box which constrains the moving particle

(

var n;

n=rrand(1,20); //random number of masses

b.setn(0,[n]++(Array.fill(n,{[5.0.rand2,5.0.rand2,exprand(0.1,100.0)]}).flatten)); //change weights to new random values

)

//noise piece

{Resonz.ar(GravityGrid2.ar(Impulse.kr(LFNoise0.kr([0.2,0.3],7,8)),MouseX.kr(0.1,10)*[11.2,12.5], LFNoise0.kr(5.4,0.4),LFNoise0.kr(10,0.8), b.bufnum),SinOsc.ar(0.03,0,2000,3000),SinOsc.ar(0.03,0,0.3,0.4))}.play