Hello all,
I hope I will be able to explain this well. If you are reading this and need more information, please feel free to comment and I will update my question. Github repo is here: GitHub - spyridonpallis/SuperCollider-Sampler: Boilerplate code for a real-time audio sampler built using SuperCollider.
Overview: I am working on a GUI and am trying to update the color of 8 TextFields while also being considerate of the TempoClock and quantization of Pdefs. As the beat progresses, the TextFields should each change color to let me know where I am in the sequence.
Here is a screenshot of GUI. The highlighted 1s and 0s are mapped to a Pseq for the /amp argument. These Pseqs are playing from within Pdefs which are quantized to 4:
GUI:
CODE:
I have 2 Routines running as a PauseStream (TY for your help on this jamshark70).
The first Routine (~task1) is keeping track of the time/ beat and I am factoring in Duration here because if the duration argument is say, 8, it will take longer for the Amplitude values to trigger, compared to say, the duration is 1/32, which triggers very fast, so I am speeding up and slowing down accordingly.
The second Routine (~task2) is what is actually updating the colors of the TextFields. I’m using this ‘fulldur’ value to essentially break it down into beats of 4. Once the beats trigger the 4, 8, 12, 16… etc, the colors update and move down.
~task1 = PauseStream(Routine{
inf.do {
if(~durbank[~t1_a_dur_state_a] == 8){~q0dur = ~q0dur + 1; ~waitTime = 8};
if(~durbank[~t1_a_dur_state_a] == 4){~q1dur = ~q1dur + 1; ~waitTime = 4};
if(~durbank[~t1_a_dur_state_a] == 2){~q2dur = ~q2dur + 1; ~waitTime = 2};
if(~durbank[~t1_a_dur_state_a] == 1){~q3dur = ~q3dur + 1; ~waitTime = 1};
if(~durbank[~t1_a_dur_state_a] == 0.5){~q4dur = ~q4dur + 1; ~waitTime = 0.5};
if(~durbank[~t1_a_dur_state_a] == 0.25){~q5dur = ~q5dur + 1; ~waitTime = 0.25};
if(~durbank[~t1_a_dur_state_a] == 0.125){~q6dur = ~q6dur + 1; ~waitTime = 0.125};
if(~durbank[~t1_a_dur_state_a] == 0.0625){~q7dur = ~q7dur + 1; ~waitTime = 0.0625};
if(~durbank[~t1_a_dur_state_a] == 0.03125){~q8dur = ~q8dur + 1; ~waitTime = 0.03125};
~fulldur = ~q0dur+~q1dur+~q2dur+~q3dur+~q4dur+~q5dur+~q6dur+~q7dur+~q8dur;
//(((t.beats.floor)%t.beatsPerBar+1)).postln;
if(~fulldur >= 32){
~q0dur=0;
~q1dur=0;
~q2dur=0;
~q3dur=0;
~q4dur=0;
~q5dur=0;
~q6dur=0;
~q7dur=0;
~q8dur=0;
~fulldur=0;
};
~fulldur.postln;
(~waitTime*(t.tempo)).wait;
}
});
~task1.play(quant:4);
~task2 = PauseStream(Routine {
inf.do {
{
x = case
//{(t.beats.floor+1) <= 4}
//{(t.bar) == 1}
{(~fulldur) <= 3}
{~t1_a_amp_1_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_3_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_8_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{(t.beats.floor+1) <= 8}
//{(t.bar) == 2}
{(~fulldur) <= 7}
{~t1_a_amp_1_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_3_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_8_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{(t.beats.floor+1) <= 12}
//{(t.bar) == 3}
{(~fulldur) <= 11}
{~t1_a_amp_3_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_1_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_8_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{(t.beats.floor+1) <= 16}
//{(t.bar) == 4}
{(~fulldur) <= 15}
{~t1_a_amp_4_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_3_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_1_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_8_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{(t.beats.floor+1) <= 20}
//{(t.bar) == 5}
{(~fulldur) <= 19}
{~t1_a_amp_5_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_1_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_8_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{(t.beats.floor+1) <= 24}
//{(t.bar) == 6}
{(~fulldur) <= 23}
{~t1_a_amp_6_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_1_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_8_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{(t.beats.floor+1) <= 28}
//{(t.bar) == 7}
{(~fulldur) <= 27}
{~t1_a_amp_7_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_1_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_8_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{(t.beats.floor+1) <= 32}
//{(t.bar) == 8}
{(~fulldur) <= 31}
{~t1_a_amp_8_a.stringColor_(Color.grey, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_1_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_2_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_4_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_5_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_6_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
~t1_a_amp_7_a.stringColor_(Color.white, rand(3,1), rrand(3, 17));
}
//{t.beats.floor <= 36};
{(t.beats.floor+1) < 31};
}.defer;
0.01.wait
}
});
~task2.play(quant: 4);
Now, this is all working as expected. But where I am having trouble is getting this perfectly sync’d/ quantized with the Pdefs that is playing the Pseqs. Here is what one of my Pdefs looks like. This is in a separate function called ~kicks.value().
(
Pdef(\a1, Pbind(
\instrument, \mainbuf, \group, ~sources,
\patch, ~patch1a,
\amp, ~t1_a_pseq_1_amp_main_a,
\dur, ~a1dur * ~t1_a_pseq_1_dur_var,
\atk, ~a1atk * ~t1_a_pseq_1_atk_var,
\rel, ~a1rel * ~t1_a_pseq_1_rel_var,
\rate, ~a1rate * ~t1_a_pseq_1_rate_var,
\pos, ~a1pos * ~t1_a_pseq_1_pos_var * ~rrand1,
\bank, ~a1buf,
)).quant_(4);
);
Every time I update the duration, I need the .stringColor_ method to reset exactly with the Pdefs. I am handling this now with an approach that is ALMOST working, but not exactly. When I change the Duration, everything is being re-triggered at once. I am doing this:
- I am updating the waitTime based on the Duration.
- I am rescheduling the Task.
- I am triggering the function that contains the Pdef.
{
if(~durbank[~t1_a_dur_state_a] == 8){~waitTime = 8};
if(~durbank[~t1_a_dur_state_a] == 4){~waitTime = 4};
if(~durbank[~t1_a_dur_state_a] == 2){~waitTime = 2};
if(~durbank[~t1_a_dur_state_a] == 1){~waitTime = 1};
if(~durbank[~t1_a_dur_state_a] == 0.5){~waitTime = 0.5};
if(~durbank[~t1_a_dur_state_a] == 0.25){~waitTime = 0.25};
if(~durbank[~t1_a_dur_state_a] == 0.125){~waitTime = 0.125};
if(~durbank[~t1_a_dur_state_a] == 0.0625){~waitTime = 0.0625};
if(~durbank[~t1_a_dur_state_a] == 0.03125){~waitTime = 0.03125};
~task1 = ~reschedulePauseStream.(~task1, 4);
~task2 = ~reschedulePauseStream.(~task2, 4);
~kicks.value();
}.value();
The Routines are quantized to 4. The Pdefs are quantized to 4. But when I do this, sometimes the Pdef is being triggered way before.
For example,
If I am playing a beat on 1/4 duration and get to the fifth TextField, then update the beat to 1/8 duration, I will hear the duration pick up speed, but the color updating lags sometimes up to a full beat.
Does anyone have any better ideas on how to solve this problem? I am afraid I am spinning my wheels here and am just looking for some feedback/ ideas.
Thank you!