|
|
|
@ -0,0 +1,186 @@
|
|
|
|
|
(
|
|
|
|
|
~generateVisuals = {
|
|
|
|
|
arg buf;
|
|
|
|
|
var control_window, width_cw = 600, height_cw = 100,
|
|
|
|
|
stable_slider, unstable_slider, cycle_slider, stable_val, unstable_val, cycle_val,
|
|
|
|
|
border = true, border_button, loop_button,start_button,
|
|
|
|
|
hierarchical_dust_window, width_hdw = 600, height_hdw = 600, shade_hd = 1, spectrum_mult_hd = Array.fill(128, {1}), state_hd = 0,
|
|
|
|
|
necklaces_window, width_nw = 400, height_nw = 600, shade_n = 0, reset_hd_window,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// All the possible necklaces
|
|
|
|
|
necklaces = [[[2,0,1],[2,1,0]],
|
|
|
|
|
[[2,0,1,0],[2,1,0,1],[2,2,0,1],[2,1,2,0],[2,2,1,0]],
|
|
|
|
|
[[2,0,1,0,1],[2,1,0,1,0],[2,2,0,1,0],[2,0,2,0,1],[2,1,2,0,1],[2,2,1,0,1],
|
|
|
|
|
[2,2,2,0,1],[2,0,2,1,0],[2,1,2,1,0],[2,1,2,2,0],[2,2,1,2,0],[2,2,2,1,0]],
|
|
|
|
|
[[2,0,1,0,1,0],[2,1,0,1,0,1],[2,2,0,1,0,1],[2,0,2,0,1,0],[2,1,2,0,1,0],[2,2,1,0,1,0],
|
|
|
|
|
[2,2,2,0,1,0],[2,0,2,1,0,1],[2,0,2,2,0,1],[2,1,0,2,0,1],[2,1,2,1,0,1],[2,1,2,2,0,1],
|
|
|
|
|
[2,2,0,2,0,1],[2,2,1,2,0,1],[2,2,2,1,0,1],[2,2,2,2,0,1],[2,0,2,1,2,0],[2,0,2,2,1,0],
|
|
|
|
|
[2,1,0,2,2,0],[2,1,2,1,2,0],[2,1,2,2,1,0],[2,1,2,2,2,0],[2,2,1,2,1,0],[2,2,1,2,2,0],
|
|
|
|
|
[2,2,2,1,2,0],[2,2,2,2,1,0]],
|
|
|
|
|
[[2,0,1,0,1,0,1],[2,1,0,1,0,1,0],[2,2,0,1,0,1,0],[2,0,2,0,1,0,1],[2,1,2,0,1,0,1],
|
|
|
|
|
[2,2,1,0,1,0,1],[2,2,2,0,1,0,1],[2,0,1,2,0,1,0],[2,0,2,1,0,1,0],[2,0,2,2,0,1,0],
|
|
|
|
|
[2,1,0,2,0,1,0],[2,1,2,1,0,1,0],[2,1,2,2,0,1,0],[2,2,0,2,0,1,0],[2,2,1,2,0,1,0],
|
|
|
|
|
[2,2,2,1,0,1,0],[2,2,2,2,0,1,0],[2,0,1,2,1,0,1],[2,0,1,2,2,0,1],[2,0,2,0,2,0,1],
|
|
|
|
|
[2,0,2,1,2,0,1],[2,0,2,2,1,0,1],[2,0,2,2,2,0,1],[2,1,0,2,1,0,1],[2,1,0,2,2,0,1],
|
|
|
|
|
[2,1,2,0,2,0,1],[2,1,2,1,2,0,1],[2,1,2,2,1,0,1],[2,1,2,2,2,0,1],[2,2,0,2,1,0,1],
|
|
|
|
|
[2,2,0,2,2,0,1],[2,2,1,0,2,0,1],[2,2,1,2,1,0,1],[2,2,1,2,2,0,1],[2,2,2,0,2,0,1],
|
|
|
|
|
[2,2,2,1,2,0,1],[2,2,2,2,1,0,1],[2,2,2,2,2,0,1],[2,0,2,0,2,1,0],[2,0,2,1,2,1,0],
|
|
|
|
|
[2,0,2,1,2,2,0],[2,0,2,2,1,2,0],[2,0,2,2,2,1,0],[2,1,0,2,1,2,0],[2,1,0,2,2,1,0],
|
|
|
|
|
[2,1,0,2,2,2,0],[2,1,2,0,2,2,0],[2,1,2,1,2,1,0],[2,1,2,1,2,2,0],[2,1,2,2,1,2,0],
|
|
|
|
|
[2,1,2,2,2,1,0],[2,1,2,2,2,2,0],[2,2,0,2,2,1,0],[2,2,1,2,1,2,0],[2,2,1,2,2,1,0],
|
|
|
|
|
[2,2,1,2,2,2,0],[2,2,2,1,2,1,0],[2,2,2,1,2,2,0],[2,2,2,2,1,2,0],[2,2,2,2,2,1,0]]],
|
|
|
|
|
|
|
|
|
|
binary_map = [[0, 0], [0, 1], [1, 0]], binary_rep,
|
|
|
|
|
necklace_len_count = Array.fill(necklaces.size, {1}),
|
|
|
|
|
necklace_count = all {: Array.fill(n.size, {1}), n <- necklaces },
|
|
|
|
|
synth, osc_func, necklace_func, necklace, necklace_transition, necklace_fade_in, necklace_fade_out, run = true;
|
|
|
|
|
|
|
|
|
|
// Generate the necklaces
|
|
|
|
|
necklace_func = {var necklace_len_index, necklace_index;
|
|
|
|
|
necklace_len_index = ({|i| i} ! necklaces.size).wchoose(necklace_len_count.normalizeSum);
|
|
|
|
|
necklace_len_count = necklace_len_count + 1;
|
|
|
|
|
necklace_len_count[necklace_len_index] = 0;
|
|
|
|
|
|
|
|
|
|
necklace_index = ({|i| i} ! necklace_count[necklace_len_index].size).wchoose(necklace_count[necklace_len_index].normalizeSum);
|
|
|
|
|
necklace_count[necklace_len_index] = necklace_count[necklace_len_index] + 1;
|
|
|
|
|
necklace_count[necklace_len_index][necklace_index] = 0;
|
|
|
|
|
necklace = necklaces[necklace_len_index][necklace_index];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Fade necklaces in and out
|
|
|
|
|
necklace_fade_out = Routine {
|
|
|
|
|
26.do({ arg i; shade_n = (25-i).abs/25.0; (1.0/25).wait;});
|
|
|
|
|
necklace_fade_out.yieldAndReset;
|
|
|
|
|
};
|
|
|
|
|
necklace_fade_in = Routine {
|
|
|
|
|
2.wait; necklace_func.value; 26.do({ arg i; shade_n = i/25.0; (1.0/25).wait;});
|
|
|
|
|
necklace_fade_in.yieldAndReset;
|
|
|
|
|
}.play;
|
|
|
|
|
necklace_transition = Routine {
|
|
|
|
|
necklace_fade_out.play; 1.wait; necklace_fade_in.play;
|
|
|
|
|
necklace_transition.yieldAndReset;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get messages from SynthDef
|
|
|
|
|
osc_func = OSCFunc({ arg msg, time;
|
|
|
|
|
switch(msg[2],
|
|
|
|
|
0, {shade_hd = msg[3]},
|
|
|
|
|
1, {necklace_transition.play},
|
|
|
|
|
2, {state_hd = msg[3]},
|
|
|
|
|
3, {spectrum_mult_hd = msg[3..]}
|
|
|
|
|
)},'/tr', s.addr);
|
|
|
|
|
|
|
|
|
|
reset_hd_window = {
|
|
|
|
|
arg border = true, isLaunch = true;
|
|
|
|
|
// Create window for projection
|
|
|
|
|
hierarchical_dust_window = Window("hierarchical dust window",
|
|
|
|
|
if(isLaunch,
|
|
|
|
|
{Rect(100, Window.availableBounds.height - height_hdw, width_hdw, height_hdw)},
|
|
|
|
|
{hierarchical_dust_window.bounds}), true, border);
|
|
|
|
|
hierarchical_dust_window.background = Color.white;
|
|
|
|
|
hierarchical_dust_window.front;
|
|
|
|
|
|
|
|
|
|
// Animate
|
|
|
|
|
hierarchical_dust_window.drawFunc = {
|
|
|
|
|
Pen.use {
|
|
|
|
|
Pen.color = Color.gray(1-shade_hd);
|
|
|
|
|
Pen.addRect(Rect(0, 0, hierarchical_dust_window.bounds.width, hierarchical_dust_window.bounds.height));
|
|
|
|
|
Pen.perform(\fill);
|
|
|
|
|
|
|
|
|
|
Pen.color = Color.gray(shade_hd);
|
|
|
|
|
if(state_hd == 1, {
|
|
|
|
|
binary_rep = (all {: binary_map[x], x <- necklace }).flatten;
|
|
|
|
|
|
|
|
|
|
{ |i|
|
|
|
|
|
Pen.line(
|
|
|
|
|
hierarchical_dust_window.bounds.width-if(binary_rep[i] == 1,{40},{30})@(((hierarchical_dust_window.bounds.height-40)
|
|
|
|
|
/ 128) * i + 150),
|
|
|
|
|
hierarchical_dust_window.bounds.width-20@(((hierarchical_dust_window.bounds.height-40) / 128) * i + 150))
|
|
|
|
|
} ! binary_rep.size;});
|
|
|
|
|
|
|
|
|
|
{ |i| if(spectrum_mult_hd[i] == 1,
|
|
|
|
|
{Pen.line(
|
|
|
|
|
20@(((hierarchical_dust_window.bounds.height-40) / 128) * i + 150),
|
|
|
|
|
40@(((hierarchical_dust_window.bounds.height-40) / 128) * i + 150))})} ! 64;
|
|
|
|
|
Pen.stroke;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
reset_hd_window.value;
|
|
|
|
|
|
|
|
|
|
// Create window for score
|
|
|
|
|
necklaces_window = Window("necklaces window",
|
|
|
|
|
Rect(width_hdw + 100, Window.availableBounds.height - height_nw, width_nw, height_nw));
|
|
|
|
|
necklaces_window.background = Color.white;
|
|
|
|
|
necklaces_window.onClose = { run = false; hierarchical_dust_window.close; control_window.close; ~synth.free };
|
|
|
|
|
necklaces_window.front;
|
|
|
|
|
|
|
|
|
|
// Animate
|
|
|
|
|
necklaces_window.drawFunc = {
|
|
|
|
|
Pen.use {
|
|
|
|
|
Pen.color = Color.gray(if(state_hd == 1,{0}, {0.5}), shade_n);
|
|
|
|
|
{ |i| Pen.line((200-75)@((i-1)*15 + 300), (200+75)@((i-1)*15 + 300)) } ! 3;
|
|
|
|
|
Pen.stroke;
|
|
|
|
|
|
|
|
|
|
{ |i| Pen.addOval(
|
|
|
|
|
Rect(200 - 75 + ((i+1) * (150.0 / (necklace.size + 2)) + 4),
|
|
|
|
|
(2-necklace[i]-1) * 15 + 300 - 7, 14, 14)) } ! necklace.size;
|
|
|
|
|
Pen.perform(\fill);
|
|
|
|
|
Pen.stroke;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Refresh
|
|
|
|
|
{ while { run } { hierarchical_dust_window.refresh; necklaces_window.refresh; 24.reciprocal.wait; } }.fork(AppClock);
|
|
|
|
|
|
|
|
|
|
// Create window for user controls
|
|
|
|
|
control_window = Window.new("control window",
|
|
|
|
|
Rect(100, Window.availableBounds.height - height_hdw - height_cw - 30, width_cw, height_cw));
|
|
|
|
|
control_window.onClose = { run = false; hierarchical_dust_window.close; necklaces_window.close; ~synth.free };
|
|
|
|
|
control_window.front;
|
|
|
|
|
unstable_val = TextField().fixedWidth_(50).string_("15");
|
|
|
|
|
stable_val = TextField().fixedWidth_(50).string_("10");
|
|
|
|
|
cycle_val = TextField().fixedWidth_(50).string_("10");
|
|
|
|
|
unstable_slider = Slider(control_window).orientation_(\horizontal).action_({
|
|
|
|
|
var scaled_val = (unstable_slider.value * 25 + 5).trunc;
|
|
|
|
|
~synth.set(\unstable, scaled_val);
|
|
|
|
|
unstable_val.string = scaled_val;});
|
|
|
|
|
unstable_slider.value = 0.4;
|
|
|
|
|
stable_slider = Slider(control_window).orientation_(\horizontal).action_({
|
|
|
|
|
var scaled_val = (stable_slider.value * 25 + 5).trunc;
|
|
|
|
|
~synth.set(\stable, scaled_val);
|
|
|
|
|
stable_val.string = scaled_val;});
|
|
|
|
|
stable_slider.value = 0.2;
|
|
|
|
|
cycle_slider = Slider(control_window).orientation_(\horizontal).action_({
|
|
|
|
|
var scaled_val = (cycle_slider.value * 25 + 5).trunc;
|
|
|
|
|
~synth.set(\cycle_len, scaled_val);
|
|
|
|
|
cycle_val.string = scaled_val;});
|
|
|
|
|
cycle_slider.value = 0.2;
|
|
|
|
|
border_button = Button(control_window).states_([["border", Color.black], ["border", Color.black, Color.grey]]).value_(1).action_(
|
|
|
|
|
{|v| hierarchical_dust_window.close; reset_hd_window.value(if(v.value == 1,{true},{false}), false)});
|
|
|
|
|
loop_button = Button(control_window).states_([["loop", Color.black], ["loop", Color.black, Color.grey]]).action_(
|
|
|
|
|
{|v| ~synth.set(\loop, v.value)});
|
|
|
|
|
start_button = Button(control_window).states_([["start", Color.black]]).action_(
|
|
|
|
|
{|v| Routine{
|
|
|
|
|
state_hd = 0;
|
|
|
|
|
necklace_fade_in.play;
|
|
|
|
|
~synth.free;
|
|
|
|
|
(1).wait;
|
|
|
|
|
~synth = Synth.newPaused(\hierarchical_dust, [\buf, buf]);
|
|
|
|
|
(1).wait;
|
|
|
|
|
{stable_slider.valueAction = stable_slider.value;
|
|
|
|
|
unstable_slider.valueAction = unstable_slider.value;
|
|
|
|
|
cycle_slider.valueAction = cycle_slider.value;
|
|
|
|
|
loop_button.valueAction = loop_button.value;}.defer;
|
|
|
|
|
(2).wait;
|
|
|
|
|
~synth.run;
|
|
|
|
|
}.play;});
|
|
|
|
|
control_window.layout = VLayout(
|
|
|
|
|
HLayout([StaticText().string="unstable -> stable", stretch: 1], [HLayout(unstable_slider, unstable_val), stretch: 4]),
|
|
|
|
|
HLayout([StaticText().string="stable -> unstable", stretch: 1], [HLayout(stable_slider, stable_val), stretch: 4]),
|
|
|
|
|
HLayout([StaticText().string="cycle length", stretch: 1], [HLayout(cycle_slider, cycle_val), stretch: 4]),
|
|
|
|
|
HLayout(nil, nil, nil, border_button, loop_button, start_button)
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
)
|