first commit

main
Michael Winter 7 years ago
commit 46fda32eb7

@ -0,0 +1,5 @@
# generator_hierarchical_dust_and_necklaces
note that the release with all the audio and video releases is available
at:
http://www.unboundedpress.org/code_releases/generator_hierarchical_dust_and_necklaces_source.zip

1
audio/.gitignore vendored

@ -0,0 +1 @@
*.wav

@ -0,0 +1,12 @@
(
// MAIN LAUNCH
~dir = thisProcess.nowExecutingPath.dirname;
"generator_hierarchical_dust_and_necklaces_synthdef.scd".loadRelative(true, {
"generator_hierarchical_dust_and_necklaces_visuals.scd".loadRelative(true, {
Buffer.read(s, thisProcess.nowExecutingPath.dirname +/+ "../audio/generator.wav", action: {
|buf|
~buf = buf;
{~generateVisuals.value(buf)}.defer;
});
})});
)

@ -0,0 +1,56 @@
(
SynthDef(\hierarchical_dust, {
arg stable = 10, unstable = 10, buf = 0, loop = 0, cycle_len = 10;
var local_in, hold, change, state, latch, hierarchical_dust, generator, env_master, env_spectrum, env_vol, chain, spectrum_mult;
// Feedback in state
local_in = LocalIn.kr(2, 0);
// Make each state last at least 15 seconds, however these variables could be different / manipulated in the array [15, 15, 15]
// That is, they could be turned into user variables
// Note the second two account for the fade in and fade out of the necklace, so it will be at least 30 seconds long
hold = PulseCount.kr(Impulse.kr(1), Changed.kr(local_in[0])) > Select.kr(local_in[0], [15, 15, 15]);
// Change state trigger
change = TWChoose.kr(Impulse.kr(1), [0, 1], [Select.kr(local_in[0] > 0, [unstable, stable]), 1].normalizeSum) * hold;
// Change state
state = Stepper.kr(change + TDelay.kr(local_in[0] > 1, 15), 0, 0, 2);
// Monitor
Poll.kr(Impulse.kr(1), hold, \hold);
Poll.kr(Impulse.kr(1), change, \change);
Poll.kr(Impulse.kr(1), state, \state);
// Trigger for filter changes
hierarchical_dust = (
Impulse.kr(8) *
(TRand.kr(0, 1, Impulse.kr(8)) <= 0.5) *
(TRand.kr(0, 1, Impulse.kr(1)) <= 0.75) *
(state <= 0)
);
// Playback the soundfile
generator = PlayBuf.ar(1, buf, BufRateScale.kr(buf), 1, 0, 1);
latch = Impulse.kr(Latch.kr((60 * cycle_len).reciprocal, local_in[1]));
env_master = EnvGen.kr(Env.sine(Latch.kr(60 * cycle_len, latch)), latch * (loop + Impulse.kr(0)));
Poll.kr(Impulse.kr(1), env_master, \env);
// Feedback out state
LocalOut.kr([state, latch]);
// Gate bins of the FFT
env_spectrum = pow(env_master, 3) * 0.75;
chain= FFT(LocalBuf(128).clear, generator);
spectrum_mult = { |i| TRand.kr(0, 1, hierarchical_dust) > Latch.kr(env_spectrum, hierarchical_dust)} ! 64;
chain = chain.pvcalc(64, {|mags, phases| [mags * spectrum_mult, phases] });
// Output
env_vol = pow(env_master, 2);
Out.ar([0,1], IFFT(chain).dup * env_vol * (1 - EnvGen.kr(Env.asr(15, 0.9, 15, \sine), state % 2)));
// Send info to Visuals
SendTrig.kr(Impulse.kr(24), 0,
1 - EnvGen.kr(Env.sine(1/6.0, env_vol), Select.kr(state > 0, [hierarchical_dust, state - Delay1.kr(state) < 0])));
SendTrig.kr((state - Delay1.kr(state) < 0) * PulseCount.kr(Changed.kr(local_in[0])) >= 1, 1);
SendTrig.kr(Changed.kr(state), 2, state > 0);
SendReply.kr(Impulse.kr(24), '/tr', spectrum_mult, 3);
}).send(s);
)

@ -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)
);
};
)

1
video/.gitignore vendored

@ -0,0 +1 @@
*.mov
Loading…
Cancel
Save