//SLUGens released under the GNU GPL as extensions for SuperCollider 3, by Nick Collins, http://composerprogrammer.com/index.html
VMScan2D 2D scanning pattern virtual machine
#x,y= VMScan2D.ar(bufnum, fairness, mul, add)
Converts a buffer of virtual machine instructions into the synthesis of a 2D path.
bufnum- Number of buffer holding instructions on the server in the form of successive COMMAND/PARAM PAIRS
The limited command set:
0 interpolate from last to new point over PARAM *5000 samples (ie down to about 10 Hz, sampling rate dependent)
1 new random point from (PARAM.rand,PARAM.rand)
2 new point by perturbing last point by PARAM
3 new point by interpolating from last point to its inversion (x,y) -> (1.0-x, 1.0-y)
4 new point by interpolating (t=PARAM) last two points
5 new point by scaling last point (multiply both x and y), scaling= PARAM
6 new x position for point at PARAM
7 new y position for point at PARAM
8 do next command if probability PARAM
9 goto instruction PARAM within the buffer
In most cases, sensible values for PARAM are from 0.0 to 1.0! But instruction 9 will need much larger address values.
Scanning paths are generated from successions of straight line segments.
fairness- If 0.0, interpolation is equal in x and y; if 1.0, y just leaps, x even; -1.0 x just leaps, y even
//Examples
(
//create instruction set; just interpolate (0,0) -> (1,1) -> (0,1) -> (1,0) and loop, with 441 sample interpolation between each point
c=[6,0,7,0,6,1,7,1,0,0.0882,6,0,7,1,0,0.0882,6,1,7,0,0,0.0882,6,0,7,0,0,0.0882,9,4]++Array.fill(50,0.0);
d=Buffer.sendCollection(s, c, 1);
)
//create buffer for wave terrain. I want the equation z = 2*(((x/100)**2) + ((abs(sin(10*y))/50)**(1/3)))-1
//over a 100 by 50 area
//2d to 1d conversion follows index= y*rowlength+ x
(
var width= 100; //= num cols
var height=50; //=num rows, though indexing bottom to top; i.e., standard Cartesian co-ordinates
a=Array.fill(width*height,{arg i;
var xnow, ynow, x, y;
xnow= i%width;
ynow= (i-xnow).div(width);
x=xnow/width;
y=ynow/height;
2*(((x)**2) + ((abs(sin(10*y)))**(1/3)))-1
});
b=Buffer.sendCollection(s, a, 1);
)
(
//test scanning virtual machine
{
var scan2d, wt;
scan2d= VMScan2D.ar(d.bufnum);
WaveTerrain.ar(b.bufnum,scan2d[0],scan2d[1],100,50)}.play
)
(
//create instruction set; just interpolate (0,0) -> (1,1) -> (0,1) -> (1,0) and loop, with 441 sample interpolation between each point
c=[6,0,7,0,1,1.0,1,0.5,0,rrand(0.05,0.2),6,1,7,1,0,0.0882,6,0,7,1,8,0.7,0,0.0882,8,0.4,1,0.5,6,1,7,0,0,0.0882,6,0,7,0,0,0.0882,9,4];
d.sendCollection(c);
)
(
//mouse control of path extent
{
var scan2d, wt;
scan2d= VMScan2D.ar(d.bufnum);
WaveTerrain.ar(b.bufnum,scan2d[0]*MouseX.kr,scan2d[1]*MouseY.kr,100,50)}.play
)
//random instruction sets
(
c=Array.fill(50,{arg i; if(i.even,{9.rand},{1.0.rand})});
Post << c << nl; //in case you like one
d.sendCollection(c);
)
(
t=Task({
inf.do {
c=Array.fill(50,{arg i; if(i.even,{9.rand},{1.0.rand})});
d.sendCollection(c);
exprand(0.05,1).wait;
}
}
).play;
)
t.stop;
//change terrain!
(
var width= 100; //= num cols
var height=50; //=num rows, though indexing bottom to top; i.e., standard Cartesian co-ordinates
a=Array.fill(width*height,{arg i;
var xnow, ynow, x, y;
xnow= i%width;
ynow= (i-xnow).div(width);
x=xnow/width;
y=ynow/height;
(((1.3*(cos(rrand(1,2)*x+1.7))**2) - ((abs(sin(rrand(1.2,4.9)*y)))**(1/2)))).max(-1.0).min(1.0)
});
b.sendCollection(a);
)
//more considerate construction of instruction sets
(
c= Array.fill(40,{arg i; if(i.odd,{if(0.6.coin,{[0,exprand(0.005,0.5)]}, {[8,rrand(0.1,1.0),9,2*rrand(0,15)]})},{if(0.6.coin,{[[1,3,4,5].choose,[exprand(0.1,1.0),rrand(0.1,1.0),exprand(0.01,0.2)].choose]},{[6,1.0.rand,7,1.0.rand]})}); }).flatten.postln;
Post << (c[0..79]) << nl;
d.sendCollection(c[0..79]);
)
//presets
(
c= [ 5, 0.045032007298424, 0, 0.16829266097, 4, 0.21671941633821, 0, 0.097617059383181, 3, 0.039779075792183, 8, 0.60886644124985, 9, 28, 6, 0.6432192325592, 7, 0.42085599899292, 0, 0.49528216896303, 4, 0.99470864534378, 8, 0.84870989322662, 9, 12, 1, 0.47667115650489, 0, 0.49904105498093, 6, 0.78044593334198, 7, 0.5973949432373, 0, 0.0079938346573139, 6, 0.49935853481293, 7, 0.26820993423462, 0, 0.30518372109199, 6, 0.35976254940033, 7, 0.091889262199402, 0, 0.012580000107232, 6, 0.39456367492676, 7, 0.071749925613403, 8, 0.15818494558334, 9, 16, 6, 0.59569001197815, 7, 0.30783140659332, 8, 0.36180495023727, 9, 14, 3, 0.66818692684174, 8, 0.75634309053421, 9, 8, 6, 0.53690254688263, 7, 0.59401845932007, 0, 0.27458241967347, 4, 0.18244198560715, 8, 0.13642364740372, 9, 30, 6, 0.92603194713593, 7, 0.28209984302521, 0, 0.0090666346152647, 6, 0.078964591026306, 7, 0.50376713275909, 0, 0.077060097964172, 1, 0.94782749414444, 0, 0.012215198751997, 5, 0.08951347633044, 0, 0.23426103829321, 5, 0.97009623442827, 8, 0.95121469497681, 9, 12, 6, 0.30078971385956, 7, 0.27361023426056, 8, 0.56096186637878, 9, 16 ];
d.sendCollection(c[0..79]);
)
//aaaaaaaah
(
c=[ 1, 0.012401115664331, 0, 0.0085625787306813, 6, 0.92073178291321, 7, 0.92452263832092, 0, 0.0067897107572423, 6, 0.52498006820679, 7, 0.89580702781677, 0, 0.0080293935557327, 1, 0.76127503778645, 8, 0.50952353477478, 9, 4, 1, 0.011272358865916, 8, 0.49296754598618, 9, 30, 5, 0.5126657733169, 8, 0.53715790510178, 9, 2, 5, 0.11751061316084, 0, 0.027315109664648, 6, 0.23468768596649, 7, 0.71995985507965, 0, 0.20785921190348, 6, 0.80761659145355, 7, 0.14734661579132, 0, 0.21667175878798, 6, 0.82812416553497, 7, 0.555588722229, 0, 0.26813978221146, 6, 0.62556290626526, 7, 0.89661765098572, 0, 0.0085612522419438, 6, 0.77029120922089, 7, 0.77577233314514, 0, 0.035287317732313, 5, 0.58347815275192, 0, 0.17061046232705, 6, 0.30991017818451, 7, 0.89471626281738, 8, 0.29139889478683, 9, 12 ];
d.sendCollection(c);
)
//rrrar
(
c=[ 6, 0.62479221820831, 7, 0.84334719181061, 0, 0.12737253976876, 1, 0.34590717554092, 8, 0.90837938785553, 9, 14, 3, 0.64444444179535, 0, 0.0076382220180926, 6, 0.21171295642853, 7, 0.061154127120972, 0, 0.087469286732226, 5, 0.90200103839312, 8, 0.80244028568268, 9, 20, 4, 0.13062523433243, 0, 0.040084850746492, 1, 0.3471907625919, 0, 0.2711738771992, 5, 0.051819064032369, 0, 0.3250898321643, 4, 0.6964198589325, 8, 0.80261430740356, 9, 0, 1, 0.18071593046188, 8, 0.77187951803207, 9, 0, 1, 0.38054929971695, 8, 0.10199545621872, 9, 6, 5, 0.1556055188179, 0, 0.0079423607059602, 1, 0.16413666490274, 0, 0.015987433587358, 6, 0.89596319198608, 7, 0.27058398723602, 0, 0.096067733476108, 6, 0.81998920440674, 7, 0.4519407749176, 0, 0.35322635035146, 4, 0.025783616661822 ];
d.sendCollection(c);
)
//additional ideas: polar co-ordinates, scanning paths on circle boundaries connecting two last points?