SpatioScope monitor volume levels on multiple speakers


s.boot;


// quick first example: 

z = SpatioScope.new; // default is 4 speakers 


// 4 chans of sound

{ LFDNoise3.ar([2, 3, 5, 8] * 1000) * LFNoise2.kr([5, 8, 13, 21] * 0.1).max(0); }.play;


// survives cmd-period

thisProcess.stop;


{ PanAz.ar(4, ClipNoise.ar, LFSaw.kr(SinOsc.ar(0.03) * 1), 0.1) }.play;


// stop and start

z.stop;

z.start;


*new(locations, server, parent, bounds)

locations: positions in space of [-1, 1] for x and y

server: on which server to watch

parent: which window or view to show on

bounds: view bounds.


// supply locations by hand - 1@1 is left bottom.

z = SpatioScope([ -0.5 @ -0.7, 0.5 @ -0.4, 0.8 @ 0.8, -0.5 @ 0.5, 0@0 ]); 



*gridPos(numx, numy) // calculate positions for a grid

numx: number of speakers in the x-direction

numy: number of speakers in the y-direction

SpatioScope.gridPos(4,6);


*grid(numx, numy radius, angleOffset, server, parent, bounds) // make a SpatioScope for a grid

numx, numy as in *gridPos

server, parent, bounds as in *new


z = SpatioScope.grid(4,6);

*ringPos(num, radius, angleOffset) // calculate positions for a ring

num: number of speakers in the ring

radius: radius from center

angleOffset: angleOffset of first speaker (0 = right, -0.5pi is top)

SpatioScope.ringPos(5);

SpatioScope.ringPos(8);


*ring(num, radius, angleOffset, server, parent, bounds) // make a SpatioScope for a ring

num, radius, angleOffset as in *ringPos

server, parent, bounds as in *new


z = SpatioScope.ring(5); // 1 is right

z = SpatioScope.ring(8); // more speakers

z = SpatioScope.ring(8, 0.8); // ring radius

z = SpatioScope.ring(5, 0.5, 0.5pi); // radius, rotate location clockwise -> bottom

z = SpatioScope.ring(6, 0.5, pi); // radius, rotate location clockwise -> left

z = SpatioScope.ring(7, 0.5, 1.5pi); // radius, rotate location clockwise -> top


// ring + subwoofer in center

z = SpatioScope(SpatioScope.ringPos(6, 0.8, pi) ++ [0@0]);


*rings(nums, radii, angleOffsets, server, parent, bounds)

// concentric rings, as in dome-style setups  (e.g. Animax Bonn, IEM-Cube Graz)

nums: number of speakers in each ring

radii: the radii of each ring (nil distributes the radii between 0 and 1)

angleOffsets: the angle offsets for each ring; if a single value, it applies to all rings.

server, parent, bounds: as above.

z = SpatioScope.rings([8, 4]); // 2 rings, outer ring is lower channels


z = SpatioScope.rings([8, 4], nil, -0.5pi); // 1 on top

z = SpatioScope.rings([8, 4], [0.4, 0.75]); // low chan numbers inside

z = SpatioScope.rings([12, 8, 4], nil, -0.5pi); // 3 rings



// roughly the angle offsets for IEM CUBE

z = SpatioScope.rings([12, 8, 4], nil, (-0.5 + [0, 0.125, 0.25]) * pi); 


// roughly the Animax Dome setup in Bonn

z = SpatioScope.rings([16, 12, 8, 4], nil, (-0.5 + [0.0625, 0.083, 0.125, 0.25]) * pi); 



// test with several sources

{ { Ringz.ar(Dust2.ar(5), exprand(300, 10000), exprand(0.03, 0.1)) }.dup(12) }.play;


internals:


z.locations // knows its locations

z.server // and its server

z.numChannels // inferred from number of locations

z.offset // zero by default, can be set so that outputs to watch begin at higher channels

z.proxy // a proxy does the amp watching

z.resp // a respondernode listen for the incoming amp values

z.skipjack // a skipjack restarts the spatioscope after thisProcess.stop

z.parent // its view


z.offset_(8);

z.offset_(0);


// closing the gui and reopening does not work yet. hmmm.

z.parent.close;

z.gui;