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 ]);

*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;