//audiovisual programming / mapping and visualization
//organized by lullcec, barcelona 18-20 may 2012
//----------------------------
//session #02.0
//animation
//--simple examples
(
var width= 640;
var height= 480;
var win= Window("animation", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.fillColor= Color.white;
Pen.fillRect(Rect(usr.frame%width, height*0.5, 10, 20));
};
usr.animate= true;
)
(
var width= 640;
var height= 480;
var win= Window("animation2", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= 0.5;
Pen.strokeColor= Color.white;
100.do{|i|
Pen.line(Point(width*0.5, height*0.5), Point(width.rand, height.rand));
Pen.stroke;
};
};
usr.animate= true;
)
//--changing parameters while it is running
(
var width= 640;
var height= 480;
var win= Window("animation live control", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~num= 4;
~col= Color.white;
~size= 40;
~spread= 100;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.strokeColor= ~col;
~num.do{|i|
Pen.strokeRect(Rect(usr.frame+(i*~spread)%width, height*0.5, ~size, ~size));
};
};
usr.animate= true;
)
~num= 8
~spread= 3
~spread= 13
~num= 20
~size= 10
~num= 200
~spread= 4
~size= 100
(
var width= 640;
var height= 480;
var win= Window("redlines", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~speed= 0.1;
~width= 4;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= ~width;
70.do{|i|
Pen.strokeColor= Color.red(i/69);
Pen.line(Point(width*0.5, height*0.5), Point(width*0.33, height*0.33).rotate(i/69*2pi+(usr.frame*~speed))+Point(width*0.5, height*0.5));
Pen.stroke;
};
};
usr.animate= true;
)
~speed= 0.2
~speed= -0.2
~speed= 0.002
~speed= 2.2
~speed= 2.5
~speed= 3
~width= 1
~width= 10
//--strings
~font= Font("Geneva", 40);
(
var width= 640;
var height= 480;
var win= Window("text animation", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.fillColor= Color.white;
Pen.font= ~font;
Pen.stringAtPoint("123456789".rotate(((usr.frame*0.03).asInteger%5)), Point(usr.frame*0.7%width, height*0.5));
};
usr.animate= true;
)
~font= Font("Helvetica", 8);
(
var width= 640;
var height= 480;
var win= Window("text animation2", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
CmdPeriod.doOnce({win.close});
~rows= 50;
~cols= 30;
usr.drawFunc= {
Pen.smoothing= false;
Pen.fillColor= Color.white;
Pen.font= ~font;
~rows.do{|x|
~cols.do{|y|
Pen.stringAtPoint(10.rand.asString, Point(x/~rows*width+(0.5/~rows*width), y/~cols*height+(0.5/~cols*height)));
};
};
};
usr.animate= true;
)
~rows= 1
~cols= 1
~rows= 10
~cols= 10
~font= Font("Helvetica", 24)
~font= Font("Helvetica", 14)
(
Routine({
50.do{
~rows= ~rows+1;
~cols= ~cols+1;
0.1.wait;
};
}).play
)
//--animation with simple sound
s.boot
(
var width= 640;
var height= 480;
var win= Window("white oval", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var syn= {|freq= 400, pan= 0| Pan2.ar(SinOsc.ar(freq, 0, 0.2), pan)}.play;
usr.background= Color.black;
win.front;
~speed= 5;
~updown= 0.5;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
var x= usr.frame*~speed%width;
var y= height*~updown.value(usr.frame);
syn.set(\freq, y.linexp(0, height, 800, 400), \pan, x.linlin(0, width, -1, 1));
Pen.width= 30;
Pen.strokeColor= Color.white;
Pen.strokeOval(Rect(x, y, 50, 50));
};
usr.animate= true;
)
~speed= -3
~speed= 40
~speed= 400
~speed= 0.1
~speed= 1
~updown= 0.25
~updown= 0.9
~updown= {1.0.rand}
~updown= {|i| sin(i*0.01)*0.5+0.5}
~updown= {|i| sin(i*0.01+sin(i*0.11))*0.5+0.5}
//more about mapping audio and sound in session #03
//----------------------------
//session #02.1
//colour-modes, trailing effects, rotation, scaling, translation
Color.white
Color(0.1, 0.2, 0.3, 1) //red, green, blue, alpha
Color.red(1, 0.4) //amount, alpha
Color.green(0.5, 0.9)
Color.hsv(1, 0.5, 0.25, 1) //hue, sat, val, alpha
//see Color helpfile
//--using hsv color mode
(
var width= 640;
var height= 480;
var win= Window("hsvlines", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~speed= 0.1;
~width= 1;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= ~width;
70.do{|i|
Pen.strokeColor= Color.hsv(i/70, 0.5, 0.8);
Pen.strokeOval(Rect.aboutPoint(Point(width*0.5, height*0.5).rotate(i/69*2pi+(usr.frame*~speed))+Point(width*0.5, height*0.5), width*0.9, height*0.9));
Pen.stroke;
};
};
usr.animate= true;
)
~speed= 0.2
~speed= -0.2
~speed= 0.002
~speed= 2.2
~speed= 2.5
~speed= 3
~speed= 3.1
~speed= 3.14
~speed= 3.1415
~speed= 2pi
~width= 2
~speed= 0.1
~width= 20
//--trail effect
//set clearOnRefresh to false and manually draw a big rect with some alpha every frame
(
var width= 640;
var height= 480;
var win= Window("trail effect", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~speed= 0.1;
~alpha= 0.1;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.fillColor= Color.grey(0.1, ~alpha); //here trail amount
Pen.fillRect(Rect(0, 0, width, height));
Pen.width= 5;
70.do{|i|
Pen.strokeColor= Color.hsv(i/70, 0.5, i/70);
Pen.line(Point(width*0.5, height*0.5), Point(width*0.33, height*0.33).rotate(i/69*2pi+(usr.frame*~speed))+Point(width*0.5, height*0.5));
Pen.stroke;
};
};
usr.animate= true;
usr.clearOnRefresh= false; //important
)
~alpha= 0.9
~alpha= 0.01
~speed= 0.2
~alpha= 0.5
~alpha= 0.01
(
var width= 640;
var height= 480;
var win= Window("white oval with trail", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~speed= 5;
~updown= 0.5;
~alpha= 0.1;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.fillColor= Color.grey(0.1, ~alpha);
Pen.fillRect(Rect(0, 0, width, height));
Pen.width= 30;
Pen.strokeColor= Color.white;
Pen.strokeOval(Rect(usr.frame*~speed%width, height*~updown.value(usr.frame), 50, 50));
};
usr.animate= true;
usr.clearOnRefresh= false;
)
~updown= {|i| sin(i*0.11)*0.5+0.5}
~speed= 20
~alpha= 0.25
~alpha= 0
~alpha= 0.01
~updown= {|i| sin(i*0.11)*sin(i*0.2)*0.3+0.5}
~speed= 200
~speed= -300
~speed= 80
~speed= 160.1
~updown= {|i| sin(i*0.11)%cos(i*0.2)*0.3+0.5}
~speed= 5
//--rotate
(
var width= 640;
var height= 480;
var win= Window("rotated squares", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var theta= 0;
usr.background= Color.black;
win.front;
~alpha= 0.1;
~speed= 0;
~width= 1;
~size= 10;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.fillColor= Color.grey(0.1, ~alpha);
Pen.fillRect(Rect(0, 0, width, height));
Pen.width= ~width;
Pen.rotate(theta, width*0.5, height*0.5);
theta= theta+~speed;
Pen.strokeColor= Color.white;
10.do{|i|
6.do{|j|
Pen.strokeRect(Rect.aboutPoint(Point(i/9*width, j/5*height), ~size, ~size));
};
};
};
usr.animate= true;
usr.clearOnRefresh= false;
)
~speed= 0.01
~speed= -0.01
~speed= -0.05
~speed= 2
~size= 4;
~size= 30;
~width= 4
~width= 0.2
~size= 1
~width= 1
~speed= pi*0.999
//--scale
(
var width= 640;
var height= 480;
var win= Window("scaled squares", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~alpha= 0.1;
~sx= 1;
~sy= 1;
~width= 1;
~size= 10;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.fillColor= Color.grey(0.1, ~alpha);
Pen.fillRect(Rect(0, 0, width, height));
Pen.width= ~width;
Pen.scale(~sx.value(usr.frame), ~sy.value(usr.frame));
Pen.strokeColor= Color.white;
10.do{|i|
6.do{|j|
Pen.strokeRect(Rect.aboutPoint(Point(i/9*width, j/5*height), ~size, ~size));
};
};
};
usr.animate= true;
usr.clearOnRefresh= false;
)
~sx= 0.5
~sy= 0.2
~sy= {|i| sin(i*0.01)*0.5+0.5}
~sx= 1
~width= 40
~sy= {|i| sin(i*0.01+sin(i*0.1))*0.5+0.5}
~size= 1
~width= 4
~size= 200
~sx= {|i| sin(i*0.007+sin(i*0.08))*0.5+0.5}
~size= 20
//--translate
(
var width= 640;
var height= 480;
var win= Window("translated squares", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~alpha= 0.1;
~tx= 0;
~ty= 0;
~width= 1;
~size= 10;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.fillColor= Color.grey(0.1, ~alpha);
Pen.fillRect(Rect(0, 0, width, height));
Pen.width= ~width;
Pen.translate(~tx.value(usr.frame), ~ty.value(usr.frame));
Pen.strokeColor= Color.white;
10.do{|i|
6.do{|j|
Pen.strokeRect(Rect.aboutPoint(Point(i/9*width, j/5*height), ~size, ~size));
};
};
};
usr.animate= true;
usr.clearOnRefresh= false;
)
~tx= 10
~tx= 40
~tx= {|i| i%(640/9)}
~ty= {|i| sin(i*0.01)*100}
~tx= {|i| cos(i*0.01)*100}
~size= 60
~alpha= 0.01
//everything at once - push and pop
(
var width= 640;
var height= 480;
var win= Window("rotate scale translate", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~rotate= 1;
~translate= 50;
~scale= 0.99;
~num= 50;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= 1;
Pen.translate(width*0.5, height*0.5); //offset drawing to the middle
Pen.push; //see also Pen.use
Pen.strokeColor= Color.white;
~num.do{
Pen.rotate(~rotate);
Pen.translate(0, ~translate);
Pen.scale(~scale, ~scale);
Pen.strokeOval(Rect(0, 0, 10, 10));
};
Pen.pop;
Pen.push;
Pen.fillColor= Color.red;
10.do{|i|
Pen.fillRect(Rect(i*10, i*10, 10, 10));
};
Pen.pop;
};
usr.animate= true;
)
~rotate= 2
~rotate= 0.2
~rotate= -4
~rotate= 0.4
~translate= 10;
~translate= 100;
~scale= 0.9
~translate= 50;
~scale= 1.06
~rotate= 4
~num= 3
~num= 300
~scale= 0.995
~scale= 0.999
~translate= 200
//----------------------------
//session #02.2
//custom shapes, styles and clipping
(
var width= 640;
var height= 480;
var win= Window("smoothing", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
var theta= 0;
usr.background= Color.black;
win.front;
~speed= 0.001;
~smooth= false;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.smoothing= ~smooth; //important
Pen.strokeColor= Color.white;
Pen.rotate(theta, width*0.5, height*0.5);
theta= theta+~speed;
100.do{|i|
Pen.strokeOval(Rect(100+(i*2), 100+i, width-200, height-200));
};
};
usr.animate= true;
)
~speed= -0.01
~speed= pi*0.5005
~speed= 2pi*0.5005
~speed= pi*0.6667
~smooth= true
~speed= 0.01
~smooth= false
~smooth= true
~smooth= false
(
var width= 640;
var height= 480;
var win= Window("join styles", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~join= 0;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= 50;
Pen.joinStyle= ~join;
Pen.strokeColor= Color.blue;
Pen.strokeRect(Rect(100, 100, width-200, height-200));
};
usr.animate= true;
)
~join= 1 //round
~join= 2 //bevel
~join= 0 //miter
(
var width= 640;
var height= 480;
var win= Window("cap styles", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
~cap= 0;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= 50;
Pen.capStyle= ~cap;
Pen.strokeColor= Color.blue;
Pen.line(Point(40, 40), Point(width*0.5, height*0.5));
Pen.line(Point(width*0.5, height*0.5), Point(width*0.8, height*0.1));
Pen.stroke;
};
usr.animate= true;
)
~cap= 1 //round
~cap= 2 //bevel
~cap= 0 //miter
//--custom shapes
(
var width= 640;
var height= 480;
var win= Window("custom", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= 1;
Pen.strokeColor= Color.white;
Pen.moveTo(Point(40, 40));
Pen.lineTo(Point(width*0.5, height*0.5));
Pen.lineTo(Point(width*0.8, height*0.1));
Pen.lineTo(Point(20, height*0.65));
Pen.lineTo(Point(40, 40));
Pen.stroke;
};
usr.animate= true;
)
//--clipping
//useful for masking and only draw in one area
(
var width= 640;
var height= 480;
var win= Window("clip", Rect(10, 10, width, height), false);
var usr= UserView(win, Rect(0, 0, width, height));
usr.background= Color.black;
win.front;
CmdPeriod.doOnce({win.close});
usr.drawFunc= {
Pen.width= 1;
Pen.strokeColor= Color.white;
Pen.addOval(Rect.aboutPoint(Point(width*0.5, height*0.5), width*0.25, height*0.25));
Pen.clip;
50.do{ //draw 50 random lines, but clip will mask out
Pen.line(Point(width.rand, height.rand), Point(width.rand, height.rand));
};
Pen.stroke;
};
usr.animate= true;
)
//----------------------------
//session #02.3
//drawing waveforms (time domain)
(
s.latency= 0.05;
s.waitForBoot{
//--variables
var l= 750; //global window size
var theta= 0;
var fps= 60;
var arr= Array.fill(l, 0); //same as half windowsize above
var o= OSCresponder(s.addr, '/tr', {|t, r, m|
if(m[2]==0, { //redraw once for each cycle of amps
b.getn(0, l-1, {|data| {arr= data; u.refresh}.defer});
});
}).add;
var trk, cnt= 0;
//--window setup
var width= l, height= l;
var w= Window("waveform", Rect(99, 99, width, height), false);
var u= UserView(w, Rect(0, 0, width, height));
var w2= width*0.5;
var h2= height*0.5;
//--interface
~trails= 1;
~speed= 0;
~sample= 1;
~amp= 0.5;
~version= 0;
//--synths
b= Buffer.alloc(s, l, 1);
SynthDef(\avTrk, {|in= 0, bufnum, rate= 40, sample= 1|
var z= In.ar(in, 1);
var trig= Impulse.kr(rate);
var index= Phasor.ar(trig, sample, 0, BufFrames.ir(bufnum)-1);
BufWr.ar(z, bufnum, index, 0);
SendTrig.kr(trig, 0, bufnum);
}).send(s);
s.sync;
trk= Synth(\avTrk, [\in, 0, \bufnum, b, \rate, fps], RootNode(s), \addToTail);
s.sync;
//--main loop
u.drawFunc= {
if(cnt==0, {
Pen.fillColor= Color.black; //erase first time
Pen.fillRect(Rect(0, 0, width, height));
});
trk.set(\sample, ~sample);
Pen.fillColor= Color.grey(0, ~trails);
Pen.fillRect(u.bounds); //manually clear
Pen.strokeColor= Color.green;
switch(~version,
0, { //line
Pen.rotate(theta, w2, h2);
Pen.translate(0, h2);
arr.do{|y, x|
var p= Point(x, y*(height*~amp));
if(x==0, {Pen.moveTo(p)}, {Pen.lineTo(p)});
};
Pen.stroke;
},
1, { //warp
Pen.rotate(theta, w2, h2);
Pen.translate(w2, h2);
arr.do{|y, x|
var p= Point(x*~amp, y*~amp).rotate(y*2pi);
if(x==0, {Pen.moveTo(p)}, {Pen.lineTo(p)});
};
Pen.stroke;
},
2, { //flower
Pen.translate(w2, h2);
Pen.moveTo(Point(arr[0], 0)*arr[0]);
arr.do{|y, x|
var p= Point(y, x)*y;
var a= x%width/width*2pi+theta;
Pen.lineTo(p.rotate(a));
};
Pen.stroke;
}
);
theta= theta+~speed;
cnt= cnt+1;
};
//--window management
u.clearOnRefresh= false; //do not erase - just draw on top of
w.onClose= {
trk.free;
o.remove;
b.free;
};
w.front;
CmdPeriod.doOnce({if(w.isClosed.not, {w.close})});
//note no routine here. the responder is driving the animation
};
)
//play your own sound or test with this...
//--tweet0038
a= play{PingPong.ar(LocalBuf(3e4,2).clear,Ringz.ar(CuspN.ar*Impulse.kr([9,8]/12)/9,LFPar.kr(1/[3,2]).range(51,[99,17])*9),0.5)}//#SuperCollider
//change these while the program is running
~sample= 2;
~sample= 10;
~sample= 1;
~trails= 0.2;
~speed= 0.1;
~speed= -0.05;
~trails= 0.01;
~amp= 0.02;
~speed= pi*0.25;
~amp= 0.2;
~sample= 2;
~version= 1;
~trails= 0.2;
~version= 2;
~sample= 1;
~version= 1;
~speed= 2pi*1.001;
~amp= 0.5;
a.release
//ADVANCED: bufferdisplay (waveform variant)
(
l= 1024; //global window/buffer size in pixels/samples
s.latency= 0.05;
s.waitForBoot{
//--variables
var theta= 0;
var fps= 60;
var arr= Array.fill(l, 0);
var cnt= 0;
//--window setup
var width= l, height= l;
var w= Window("bufferdisplay", Rect(99, 99, width, height), false);
var u= UserView(w, Rect(0, 0, width, height));
var w2= width*0.5;
var h2= height*0.5;
//--buffer
b= Buffer.alloc(s, l, 1);
s.sync;
//--interface
~trails= 1;
~speed= 0;
~amp= 0.5;
~version= 0;
//--main loop
u.drawFunc= {
//uncomment framerate display in the two lines below to gain some speed
Pen.color= Color.white;
Pen.stringAtPoint(""++u.frameRate, Point(10, 10));
//--
b.getn(0, b.numFrames-1, {|data| arr= data});
if(cnt==0, {
Pen.fillColor= Color.black; //erase first time
Pen.fillRect(Rect(0, 0, width, height));
});
Pen.fillColor= Color.grey(0, ~trails);
Pen.fillRect(u.bounds); //manually clear
Pen.strokeColor= Color.green;
switch(~version,
0, { //line
Pen.rotate(theta, w2, h2);
Pen.translate(0, h2);
arr.do{|y, x|
var p= Point(x, y*(height*~amp));
if(x==0, {Pen.moveTo(p)}, {Pen.lineTo(p)});
};
Pen.stroke;
},
1, { //warp
Pen.rotate(theta, w2, h2);
Pen.translate(w2, h2);
arr.do{|y, x|
var p= Point(x*~amp, y*~amp).rotate(y*2pi);
if(x==0, {Pen.moveTo(p)}, {Pen.lineTo(p)});
};
Pen.stroke;
},
2, { //flower
Pen.translate(w2, h2);
Pen.moveTo(Point(arr[0], 0)*arr[0]);
arr.do{|y, x|
var p= Point(y, x)*y;
var a= x%width/width*2pi+theta;
Pen.lineTo(p.rotate(a));
};
Pen.stroke;
}
);
theta= theta+~speed;
cnt= cnt+1;
};
//--window management
u.clearOnRefresh= false; //do not erase - just draw on top of
w.onClose= {
b.free;
};
w.front;
CmdPeriod.doOnce({if(w.isClosed.not, {w.close})});
u.animate= true;
};
)
//some synth that writes into the buffer
v= {RecordBuf.ar(Saw.ar, b)}.play
//change these while the program is running
~trails= 0.2;
~speed= 0.1;
~speed= -0.05;
~trails= 0.01;
~amp= 0.02;
~speed= pi*0.25;
~amp= 0.2;
~version= 1;
~trails= 0.2;
~version= 2;
~version= 1;
~speed= 2pi*1.001;
~amp= 0.5;
v.free;
//keep window open - start this synth and move mouse around
v= {RecordBuf.ar(SinOsc.ar(0, BPF.ar(VarSaw.ar(MouseX.kr(1, 1000, 1)), MouseY.kr(50, 5000, 1), 0.5)), b)}.play
~version= 1;
~trails= 0.01;
~speed= -0.03;
~speed= -0.05;
~trails= 1;
~amp= 0.5;
~speed= 2pi*0.25;
~trails= 0.1
~amp= 0.2;
~version= 2;
~version= 0;
~speed= 2pi*1.001;
~amp= 10;
~speed= 0;
v.free
//----------------------------
//session #02.4
//spectrograms (frequency domain)
//tracking amplitude with a bunch of band-pass filters
(
s.latency= 0.05;
s.waitForBoot{
//--window setup
var width= 500, height= 500;
var w= Window("amptrack", Rect(99, 99, width, height), false, false);
var u= UserView(w, Rect(0, 0, width, height));
//--variables
var fps= 60;
var num= 100; //number of tuned filter synths
var cnt= 0; //vertical drawing position
var amps= 0.dup(num); //array of current amplitudes
var o= OSCresponder(s.addr, '/tr', {|t, r, m| amps= amps.put(m[2], m[3])}).add;
var syns;
var wn= width/num;
var w2= width*0.5;
var h2= height*0.5;
//--interface
~freqMin= 200;
~freqMax= 6000;
~width= 120;
~speed= 1;
~extra= 1;
~version= 1;
//--synths
SynthDef(\avTrk, {|in, t_trig, time= 0.01, cutoff= 400, index= 0|
var z= In.ar(in, 1);
var val= Amplitude.kr(BPF.ar(BPF.ar(z, cutoff, 0.1, 5), cutoff, 0.1, 5), time, time);
SendTrig.kr(t_trig, index, val);
}).send(s);
s.sync;
syns= {|i| //each tracker with an unique peakfilter
Synth(\avTrk, [\in, 0, \index, i, \cutoff, i.linexp(0, num-1, ~freqMin, ~freqMax)]);
}.dup(num);
s.sync;
//--main loop
u.drawFunc= {
//--first frame clear to black
if(cnt==0, {
Pen.fillColor= Color.black;
Pen.fillRect(Rect(0, 0, width, height));
});
//--optional oval mask
/*
Pen.moveTo(Point(w2, 0));
Pen.arcTo(Point(width, 0), Point(width, h2), w2);
Pen.arcTo(Point(width, height), Point(w2, height), w2);
Pen.arcTo(Point(0, height), Point(0, h2), w2);
Pen.arcTo(Point(0, 0), Point(w2, 0), w2);
Pen.clip;
*/
switch(~version,
0, {
Pen.translate(wn*0.5, cnt%height);
amps.do{|amp, i|
Pen.fillColor= Color.grey((amp*~extra).clip(0, 1));
Pen.fillRect(Rect.aboutPoint(Point(wn*i, 0), wn*0.5, ~width));
};
cnt= cnt+~speed;
},
1, {
amps.do{|amp, i|
Pen.rotate(cnt, w2, h2);
Pen.strokeColor= Color.grey((amp*~extra).clip(0, 1));
Pen.strokeRect(Rect.aboutPoint(Point(wn*i, 0), ~width*0.1, ~width));
cnt= cnt+(~speed*0.000001);
};
},
2, {
Pen.rotate(cnt, w2, h2);
Pen.translate(w2, h2);
amps.do{|amp, i|
Pen.strokeColor= Color.grey((amp*~extra).clip(0, 1));
Pen.strokeOval(Rect.aboutPoint(Point(i*~speed, 0), ~width*0.5, ~width*0.5));
};
cnt= cnt+(~speed*0.01);
}
);
syns.do{|x| x.set(\t_trig, 1)}; //request amp data
};
//--window management
u.clearOnRefresh= false; //do not erase - just draw on top of
w.front;
CmdPeriod.doOnce({if(w.isClosed.not, {w.close}); o.remove;});
//Routine({while({w.isClosed.not}, {u.refresh; (1/fps).wait})}).play(AppClock);
u.animate= true;
};
)
a= {Saw.ar(100*SinOsc.ar(SinOsc.ar(SinOsc.ar(0.1)*0.2)).abs+50, 0.5)}.play
//change these while the program is running
~width= 50;
~width= 200;
~speed= 2;
~speed= -0.1;
~speed= pi;
~version= 0;
~width= 20;
~speed= 1;
~width= 1;
~speed= 10;
~width= 500;
~version= 2;
~width= 100;
~speed= 1;
~speed= -1.5;
~width= 20;
~extra= 7;
a.free
////keep window open - play your own sound or test with this...
//--tweet0014
a= play{a=SinOscFB;sum({|i|a.ar(a.ar(a.ar(a.ar(i+1,1/9,999),1/9,a.ar(1/9,1,1/9)),a.ar(0.1,3),i+2*999),a.ar(1/9,1/9),1/9)}!9)!2}//#SuperCollider
a.free
//using fft
(
s.latency= 0.05;
s.waitForBoot{
//--variables
var l= 512; //try with 1024 if you have a fast machine
var scale= if(l<=256, {2}, {1}); //scale can be 1 or 2
var cnt= 0; //horizontal drawing position
var fftArray= Array.fill(l, 0);
var o= OSCresponder(s.addr, '/tr', {|t, r, m|
var v= m[3].min(1); //brutal clip of mags here
var i= l.div(2);
fftArray= fftArray.put([i-m[2], i+m[2]], v); //mirror middle of array
}).add;
var trk;
//--window setup
var width= l+10, height= l+10;
var w= Window("fft", Rect(99, 99, width, height), false);
var u= UserView(w, Rect(0, 0, width, height));
//--interface
~speed= 1;
~version= 0;
~radius= 2/scale;
~depth= 0.01;
~trails= 0.5;
~fps= 60;
//--synths
b= Buffer.alloc(s, l, 1);
SynthDef(\avTrk, {|in= 0, t_trig= 0|
var z= In.ar(in, 1);
var chain= FFT(b, z);
Array.fill(l.div(2), {|i|
var a= Unpack1FFT(chain, l, i, 0);
var b= Demand.kr(chain>=0, 0, a);
SendTrig.kr(t_trig, i, b);
});
}).send(s);
s.sync;
trk= Synth(\avTrk, [\in, 0], RootNode(s), \addToTail);
s.sync;
//--main loop
u.drawFunc= {
switch(~version,
0, { //rectangles
Pen.translate(5, 5);
fftArray.do{|a, y|
var p= Point(cnt*scale, height-10-(y*scale));
Pen.fillColor= Color.grey((1-a).clip(0, 1));
Pen.fillRect(Rect.aboutPoint(p, scale*~radius, scale*~radius));
};
cnt= cnt+~speed%fftArray.size;
Pen.strokeColor= Color.red;
Pen.line(Point(cnt*scale, 0), Point(cnt*scale, l*scale));
Pen.stroke;
},
1, { //ovals with a little transparency
Pen.translate(5, 5);
fftArray.do{|a, y|
var p= Point(cnt*scale, height-10-(y*scale));
Pen.fillColor= Color.grey((1-a).clip(0, 1), 0.5);
Pen.fillOval(Rect.aboutPoint(p, scale*~radius, scale*~radius));
};
cnt= cnt+~speed%fftArray.size;
},
2, { //rotation
Pen.fillColor= Color.grey(1, ~trails);//clear color with some alpha
Pen.fillRect(Rect(0, 0, width, height));//manually clear with rect
fftArray.do{|a, y|
var p= Point(cnt*scale, height-(y*scale));
Pen.rotate(y/l*0.25*scale*2pi*~depth, width*0.5, height*0.5);
Pen.fillColor= Color.grey((1-a).clip(0, 1));
Pen.fillOval(Rect.aboutPoint(p, scale*~radius, scale*~radius));
};
cnt= cnt+~speed%fftArray.size;
},
3, { //lines
Pen.fillColor= Color.grey(1, ~trails);
Pen.fillRect(Rect(0, 0, width, height));
fftArray.do{|a, y|
var p= Point(cnt.fold(0, l*scale), height-y);
Pen.strokeColor= Color.grey(1-(a+0.5).clip(0, 1), 0.5);
Pen.moveTo(p*a); //move to before rotation special here
Pen.rotate(y/l*pi*0.5*scale*~depth, width*0.5, height*0.5);
Pen.lineTo(p);
Pen.stroke;
};
cnt= cnt+~speed;
}
);
trk.set(\t_trig, 1); //to all send trigs
};
//--window management
u.clearOnRefresh= false; //do not erase - just draw on top of
w.onClose= {
trk.free;
o.remove;
b.free;
};
w.front;
//Routine({while({w.isClosed.not}, {u.refresh; (1/~fps).wait})}).play(AppClock);
u.animate= true;
CmdPeriod.doOnce({if(w.isClosed.not, {w.close})});
};
)
//play your own sound or test with this...
//--tweet0014
a= play{a=SinOscFB;sum({|i|a.ar(a.ar(a.ar(a.ar(i+1,1/9,999),1/9,a.ar(1/9,1,1/9)),a.ar(0.1,3),i+2*999),a.ar(1/9,1/9),1/9)}!9)!2}//#SuperCollider
//change these while the program is running
~version= 1;
~radius= 4;
~speed= 8;
~speed= 256/6;
~radius= 256/25;
~speed= -1;
~version= 2;
~trails= 0.01;
~radius= 5;
~speed= 2;
~radius= 0.5;
~depth= -0.002;
~depth= 3;
~radius= 1;
~trails= 0.5;
~version= 3;
~depth= 0.5;
~speed= 5;
~depth= -0.1;
~depth= -0.01
~trails= 0.01;
a.free
//----------------------------
//session #02.5
//bitmaps and scrolling views
//show SCImage (osx cocoa only), RedGIF (in quark redSys)
GUI.cocoa;
i= SCImage(SCDoc.helpSourceDir +/+ "images/icon.supercollider.png");
a= i.plot
p= i.pixels;
i.pixels= p.as(Array).rotate(100).as(Int32Array)
a.refresh
i.pixels= p.as(Array).collect{|x| if(x< -1, {1}, {x})}.as(Int32Array)
a.refresh
1000.do{p.put(p.size.rand, p.choose)}
i.pixels= p
a.refresh
(
r= Routine({
inf.do{
a.refresh;
(1/60).wait;
};
}).play(AppClock);
)
500.do{i.setPixel([255, 255, 255].asRGBA, 50.rand, 50.rand)}
r.stop
i.free
a.close