Whitney Balls
clean-up #4:
This is something I originally wrote for the article Audiovisuals with SC and now rewrote as separate classes. There are four classes all implementing the same system slightly differently. Two for graphics (Whitney
, Whitney2
) and the other two for patterns (Pwhitney
, Pwhitney2
).
The principle for this system is described by John Whitney in his book Digital Harmony (1980) and reimplemented musically by Jim Bumgardner in his Whitney Music Box (2006). The idea is simple but complex patterns arise - both in graphics and in harmony/rhythm. The innermost ball moves at a certain speed, the ball next to it doubles that speed and the ball next to that triples the speed etc. There's a sound played for each ball as it passes through 0. Each ball's sound plays at a different frequency mapped to some scale, overtone series or something else.
The code for the above video example is taken from the help file...
(
s.latency= 0.05;
s.waitForBoot{
var width= 500, height= 500;
var w= Window("Whitney balls", Rect(99, 99, width, height), false);
var u= UserView(w, Rect(0, 0, width, height));
SynthDef(\sin, {|freq= 400, amp= 0.2, pan= 0, rel= 0.9|
var e= EnvGen.ar(Env.perc(0.005, rel), 1, doneAction:2);
var z= SinOsc.ar(freq, e*pi, e);
Out.ar(0, Pan2.ar(z, pan, amp));
}).send(s);
s.sync;
//--set up the whitney system
f= Whitney(20, {|ball, i|
Synth(\sin, [\freq, (64+i).midicps, \amp, 2/f.num]);
Pen.fillOval(Rect.aboutPoint(Point(ball.x, ball.y), 5, 5));
});
u.drawFunc= {
Pen.rotate(2pi*0.75, width*0.5, height*0.5);
Pen.translate(width*0.5, height*0.5);
Pen.strokeColor= Color.red;
Pen.line(Point(0, 0), Point(0, width*0.5));
Pen.stroke;
Pen.color= Color.grey(1, 0.7);
f.next; //update the system
f.balls.do{|b, i| //draw the balls
Pen.strokeOval(Rect.aboutPoint(Point(b.x, b.y), 4, 4));
};
};
CmdPeriod.doOnce({if(w.isClosed.not, {w.close})});
u.background= Color.black;
w.front;
Routine({
var nextTime;
while({w.isClosed.not}, {
nextTime= Main.elapsedTime+(1/60);
u.refresh;
(nextTime-Main.elapsedTime).max(0.001).wait;
});
}).play(AppClock);
};
)
f.speed= 0.02 //change speed
f.speed= 0.002
f.theta= 0 //restart
f.spread= 15 //change distance between balls
f.spread= 5
(
f.func= {|ball, i|
Synth(\sin, [
\freq, i.linexp(0, f.num-1, 300, 3000),
\amp, i.linlin(0, f.num-1, 0.1, 0.05),
\rel, i.linlin(0, f.num-1, 1, 0.2),
\pan, 0.4.rand2
]);
Pen.fillOval(Rect.aboutPoint(Point(ball.x, ball.y), 5, 5));
}
)
f.num= 10
f.num= 30
f.num= 55
f.speed= 0.01
f.speed= 0.0002
f.speed= 0.001
f.speed= 0.005
(
f.func= {|ball, i|
Synth(\sin, [
\freq, (i.degreeToKey(Scale.indian)+48).midicps,
\amp, i.linlin(0, f.num-1, 0.1, 0.05),
\rel, i.linlin(0, f.num-1, 2, 0.2),
\pan, 0.4.rand2
]);
Pen.fillOval(Rect.aboutPoint(Point(ball.x, ball.y), 6, 6));
};
f.num= 36;
f.theta= 0;
f.spread= 6;
f.speed= 0.001;
)
Updates:
- 131118: added Whitney2 class and new help docs - just download the attached zip file again
Attachments: | |
---|---|
Whitney.zip |