-
-
Save zeffii/7735278 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// persistent sound chain | |
NRev revL => dac.left; | |
NRev revR => dac.right; | |
revL.gain(0.0012); | |
revR.gain(0.0012); | |
Pan2 hatVPan => NRev hatVerb => dac; | |
hatVPan.gain(0.643); | |
hatVerb.mix(0.043); | |
625::ms/4 => dur tick_time; | |
// [43,43,41-12,46, 42,45-12,47+12,47] @=> int note_array[]; | |
//[43, 42-12, 43, 41-12,43, 47, 41-12, 42, 0,42-12] @=> int note_array[]; | |
[43, 45, 61, 48-12, 43, 45-12, 46, 48, 43-12, 46, 49, 52-12, 46, 45, 47-12, 55] @=> int note_array[]; | |
Step s3 =>Envelope freqFilterEnv => blackhole; | |
// filter range 400 - 3500 (comfy) | |
12 => int num_loops_intro; | |
freqFilterEnv.duration(tick_time * 16 * (num_loops_intro-1)); | |
freqFilterEnv.keyOn(1); | |
int loop_num; | |
repeat(num_loops_intro){ | |
for(0 => int i; i<note_array.cap(); i++){ | |
note_array[i] => int mnote; | |
if (mnote>0){ | |
Math.random2f(-.6, .6) => float rpan; | |
generate_osc("saw", mnote, rpan, 0.02, | |
[22, 120, 19, 2], /* envADSR */ | |
[2, 162, 59, 212], /* filterADSR */ | |
filtSweep(), 1.2); | |
} | |
tick_time/1.5 => now; | |
} | |
loop_num++; | |
if (loop_num ==(num_loops_intro-2)){ | |
freqFilterEnv.duration(tick_time * 16 * 1); | |
freqFilterEnv.keyOff(1); | |
} | |
} | |
[1,0,0,0, 1,0,0,0, 1,0,0,1, 0,0,1,0] @=> int bd_pattern[]; | |
[1,0,2,0, 1,0,2,0, 1,0,2,0, 1,3,0,2] @=> int ht_pattern[]; | |
[0,1,0,1, 0,1,0,1, 0,2,0,0, 1,0,1,1] @=> int ch_pattern[]; | |
trigger_chord("stomp3"); | |
repeat(5){ | |
for(0 => int i; i<16; i++){ | |
if (bd_pattern[i] == 1) trigger_kick(); | |
if (ht_pattern[i] == 1) trigger_hat("short"); | |
else if (ht_pattern[i] == 2) trigger_hat("long"); | |
else if (ht_pattern[i] == 3) do_shake(260); | |
if (ch_pattern[i] == 1) trigger_chord("stomp"); | |
else if (ch_pattern[i] == 2) trigger_chord("stomp2"); | |
tick_time/1.5 => now; | |
} | |
} | |
fun void trigger_kick(){ | |
Math.random2f(-.6, .6) => float rpan; | |
generate_osc("sin", 57-27, rpan, 0.032, [2, 172, 19, 12],[2, 272, 69, 12], 54, 5.2); | |
generate_osc("sin", 32, rpan, 0.132, [2, 172, 19, 12],[2, 522, 9, 12], 7354, 2.2); | |
} | |
fun void trigger_hat(string mode){ | |
Math.random2f(-.6, .6) => float rpan; | |
if (mode=="short") | |
generate_osc("sss", 60, rpan, 0.0052, [2, 32, 59, 12],[2, 131, 129, 12], 7954, 1.6); | |
else if (mode=="long") | |
generate_osc("sss", 80, rpan, 0.019, [2, 72, 59, 12],[2, 327, 369, 12], 7354, 4.8); | |
} | |
fun void trigger_chord(string ch_type){ | |
int chord[]; | |
int decay_len, fdecay_len, ffreq; | |
float fQ; | |
if (ch_type=="stomp") [46,47,50,53] @=> chord; | |
if (ch_type=="stomp2") [46,58,61,53] @=> chord; | |
if (ch_type == "stomp" || ch_type == "stomp2"){ | |
172 => decay_len, | |
212 => fdecay_len, | |
2354 => ffreq; | |
5.2 => fQ; | |
} | |
if (ch_type=="stomp3") { | |
[63,58,61,58] @=> chord; | |
472 => decay_len, | |
212 => fdecay_len, | |
854 => ffreq; | |
2.7 => fQ; | |
} | |
for(0 => int i; i<chord.cap(); i++){ | |
Math.random2f(-.6, .6) => float rpan; | |
generate_osc("sin", chord[i], rpan, 0.012, | |
[2, decay_len, 19, 12], | |
[2, fdecay_len, 69, 12], | |
ffreq, fQ); | |
} | |
} | |
3::second => now; | |
// monophonic synth | |
fun void s_generate_osc( | |
string osc_type, | |
int note, | |
float pan, | |
float vgain, | |
int adsr[], int fadsr[], | |
int ffreq, float qual) | |
{ | |
/* | |
The chuck language doesn't permit an if/else statement to determine the | |
oscillator type of a variable named (for instance) vocOsc. I wanted the if / else | |
to act as a switch, depening on the string value of osc_type, i would have : | |
if (osc_type == "saw") SawOsc vocOsc; | |
else if (osc_type == "sin") SinOsc vocOsc; | |
etc... | |
tragically, the monstrosity below is a workaround that instantiates all oscillator | |
types, with gain 0.0 then sets the wanted osctype to gain > 0.0. | |
*/ | |
int mode; | |
if (osc_type=="saw") 0 => mode; | |
else if (osc_type=="sin") 1 => mode; | |
else if (osc_type=="tri") 2 => mode; | |
else if (osc_type=="sqr") 3 => mode; | |
else if (osc_type=="pls") 4 => mode; | |
else if (osc_type=="sss") 5 => mode; | |
ADSR voiceEnv; | |
LPF filt; | |
note => Std.mtof => float frequency; | |
SawOsc vocOscSW => filt => voiceEnv; vocOscSW.gain(0.0); frequency => vocOscSW.freq; | |
SinOsc vocOscSI => filt => voiceEnv; vocOscSI.gain(0.0); frequency => vocOscSI.freq; | |
TriOsc vocOscTR => filt => voiceEnv; vocOscTR.gain(0.0); frequency => vocOscTR.freq; | |
SqrOsc vocOscSQ => filt => voiceEnv; vocOscSQ.gain(0.0); frequency => vocOscSQ.freq; | |
PulseOsc vocOscPS => filt => voiceEnv; vocOscPS.gain(0.0); frequency => vocOscPS.freq; | |
Noise vocOscNS => filt => voiceEnv; vocOscNS.gain(0.0); | |
adsr[0] => int a; | |
adsr[1] => int d; | |
adsr[2] => int s; | |
adsr[3] => int r; | |
fadsr[0] => int fa; | |
fadsr[1] => int fd; | |
fadsr[2] => int fs; | |
fadsr[3] => int fr; | |
voiceEnv.set( a::ms, d::ms, s/100, r::ms ); | |
voiceEnv => Pan2 panObj => dac; | |
//voiceEnv => DelayL flanger1 => panObj; | |
Math.random2(2, 15) => int delayRandom; | |
//flanger1.delay(delayRandom::samp); | |
//flanger1.gain(0.7); | |
pan => panObj.pan; | |
panObj.left => revL; | |
panObj.right => revR; | |
if (mode==0) vgain => vocOscSW.gain; | |
if (mode==1) vgain => vocOscSI.gain; | |
if (mode==2) vgain => vocOscTR.gain; | |
if (mode==3) vgain => vocOscSQ.gain; | |
if (mode==4) vgain => vocOscPS.gain; | |
if (mode==5) vgain => vocOscNS.gain; | |
// filter function taken (and modified) from William Dilworth | |
44100/frequency => float grain; | |
Step s5 => ADSR filtEnv => blackhole; | |
filtEnv.set(fa::ms, fd::ms, fs/100, fr::ms); | |
filtEnv.keyOn(1); | |
voiceEnv.keyOn(1); | |
filt.Q(qual); | |
(a+d)::ms + now => time later; | |
while(now < later) | |
{ | |
filtEnv.last()*ffreq => filt.freq; | |
grain::samp => now; | |
if( now > later){ | |
(a+d)::ms => now; | |
voiceEnv.keyOff(1); | |
filtEnv.keyOff(1); | |
} | |
} | |
r*2::ms => now; // wait for tail to finish. | |
// disconnect to clean up | |
vocOscSW =< panObj; | |
vocOscSI =< panObj; | |
vocOscTR =< panObj; | |
vocOscSQ =< panObj; | |
vocOscPS =< panObj; | |
vocOscNS =< panObj; | |
panObj =< dac; | |
} | |
// This is a wrapper fnction for the osc, means I can call a sporked function | |
// without always adding the spork syntax. | |
fun void generate_osc( | |
string osc_type, | |
int note, | |
float pan, | |
float vgain, | |
int adsr[], int fadsr[], | |
int ffreq, float qual) | |
{ | |
spork ~ s_generate_osc(osc_type, note, pan, vgain, adsr, fadsr, ffreq, qual); | |
} | |
// filter sweep: | |
fun int filtSweep(){ | |
4100 => float frange; | |
((freqFilterEnv.last()*3100) + 400.0) $ int => int frequency; // cast to int | |
return frequency; | |
} | |
fun void do_shake(int length){ | |
spork ~ s_do_shake(length); | |
} | |
fun void s_do_shake(int length){ | |
Shakers espi => ADSR shakeEnv => hatVPan; | |
espi.preset(9); | |
espi.objects(1); | |
espi.energy(1.0); | |
espi.noteOn(1.0); | |
shakeEnv.set( 2::ms, length::ms, 0.20, 35::ms ); | |
shakeEnv.keyOn(1); | |
length::ms => now; | |
espi.noteOff(1.0); | |
shakeEnv.keyOff(1); | |
1::second => now; // time for tail. | |
shakeEnv =< hatVPan; | |
espi =< shakeEnv; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment