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;