first commit
This commit is contained in:
commit
46fda32eb7
5
README.md
Normal file
5
README.md
Normal file
|
|
@ -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
Normal file
1
audio/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.wav
|
||||
BIN
generator_hierarchical_dust_and_necklaces_score.pdf
Normal file
BIN
generator_hierarchical_dust_and_necklaces_score.pdf
Normal file
Binary file not shown.
|
|
@ -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
Normal file
1
video/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.mov
|
||||
Loading…
Reference in a new issue