-
-
Save zeffii/8021115 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
tb = [54, 0,55,54,61, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
66, 0,64,66,61, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0, | |
54, 0,55,54,61, 0,66, 0,64] | |
expander = lambda i: [i, 300] if i > 0 else [0,0] | |
tkm = [expander(i) for i in tb] | |
print(tkm) |
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
Machine.add(me.dir() + "/WaveformMixerMono.ck"); | |
Machine.add(me.dir() + "/PolyWaveForm.ck"); | |
Machine.add(me.dir() + "/PolySynth.ck"); | |
Machine.add(me.dir() + "/ModCarp.ck"); | |
Machine.add(me.dir() + "/score.ck"); | |
12::second => now; | |
// gist -m |
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
public class ModCarp { | |
Mix2 out; | |
Chorus manCh_left => out.left; | |
Chorus manCh_right => out.right; | |
manCh_left.modDepth(0.04); | |
manCh_left.modFreq(.42); | |
manCh_right.modDepth(0.08); | |
manCh_right.modFreq(0.64); | |
int note, attack, decay; | |
float vol; | |
fun void play(int note, float vol, int attack, int decay){ | |
note => this.note; | |
vol => this.vol; | |
decay => this.decay; | |
attack => this.attack; | |
spork ~ splay(); | |
} | |
fun void splay(){ | |
// new object for each note? are we wasteful or what? :) | |
StifKarp arper => LPF knight => | |
ADSR madsr => manCh_left; | |
madsr => manCh_right; | |
Step s => ADSR filterEnv => blackhole; | |
arper.noteOn(vol); | |
filterEnv.keyOn(); | |
filterEnv.set( attack::ms, (decay*1.2)::ms, 0.0, 0::ms ); //a, d, s, r | |
madsr.keyOn(); | |
madsr.set( attack::ms, (decay*1.02)::ms, 0.00, 0::ms ); //a, d, s, r | |
note -12 => Std.mtof => float note_freq => arper.freq; | |
knight.Q(.827); | |
now => time start; | |
while(now < start + (attack+decay)::ms){ | |
filterEnv.last() * 2699 + 799 => knight.freq; | |
20::ms => now; | |
} | |
} | |
} |
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
public class PolySynth{ | |
// use this to hook up to externally. | |
Mix2 out; | |
float max_filter, max_q; | |
float continual; | |
int notes[]; | |
// some default values for these envelope params. | |
2 => int volume_attack; | |
300 => int volume_decay; | |
2 => int filter_attack; | |
300 => int filter_decay; | |
// for big changes | |
fun void set_envelopes(int va, int vd, int fa, int fd){ | |
va => this.volume_attack; | |
vd => this.volume_decay; | |
fa => this.filter_attack; | |
fd => this.filter_decay; | |
} | |
fun void play_synth(int notes[], float max_filter, float max_q, float continual){ | |
notes @=> this.notes; | |
max_filter => this.max_filter; | |
max_q => this.max_q; | |
continual => this.continual; | |
spork ~ splay_synth(); | |
} | |
fun void splay_synth(){ | |
PolyWaveForm synth; | |
synth.set_gain(0.21); | |
LPF lpf1[2]; | |
synth.sum_waveforms.left => lpf1[0]; | |
synth.sum_waveforms.right => lpf1[1]; | |
ADSR vEnv[2]; | |
lpf1[0] => vEnv[0] => out.left; | |
lpf1[1] => vEnv[1] => out.right; | |
for(0 => int i; i<2; i++){ | |
// yeah, there's no consideration for sustain in this machine | |
vEnv[i].set( volume_attack::ms, volume_decay::ms, 0.0, 0::ms ); //a, d, s, r | |
vEnv[i].keyOn(); | |
} | |
now => time start; | |
volume_attack::ms + volume_decay::ms => dur attack_decay; | |
(start + attack_decay) => time end; | |
// frequency filter envelope | |
Step s => ADSR fEnv => blackhole; | |
fEnv.set( filter_attack::ms, filter_decay::ms, 0.0, 0::ms ); | |
fEnv.keyOn(); | |
synth.play_chord(notes, continual); | |
// filter envelope, this loop passes time and adjusts the | |
// filter frequency every iteration using the value of fEnv.last() | |
// at that time. | |
float real_filter; | |
while (now <= end){ | |
for(0 => int i; i<2; i++){ | |
fEnv.last() * max_filter => real_filter; | |
real_filter => lpf1[i].freq; | |
max_q => lpf1[i].Q; | |
} | |
2::ms => now; | |
} | |
fEnv.keyOff(); | |
for(0 => int i; i<2; i++){ | |
vEnv[i].keyOff(); | |
} | |
} | |
} |
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
public class PolyWaveForm{ | |
// this will act as the master out gain control | |
.4 => float max_gain; | |
Mix2 sum_waveforms; | |
sum_waveforms.gain(max_gain); | |
// defaults to a mono synth. | |
1 => int polyphony; | |
max_gain / polyphony => float voice_volume; | |
WaveformMixerMono bloop[polyphony]; | |
Pan2 pan_array[polyphony]; | |
fun void set_gain(float mgain){ | |
mgain => this.max_gain; | |
sum_waveforms.gain(mgain); | |
} | |
// sets all the waveforms at once, | |
// it might be nice to offer the option to set them indivually | |
fun void waveform_mix(float continual){ | |
for(0 => int i; i<this.polyphony; i++){ | |
this.bloop[i].mixer2(continual); | |
} | |
} | |
fun void play_chord(int notes[], float continual){ | |
// check if number of notes has change, an rewire if it has | |
if (!(notes.cap() == polyphony)){ | |
set_polyphony(notes); | |
} | |
waveform_mix(continual); | |
set_voice_volume(notes.cap()); | |
for(0 => int n; n<notes.cap(); n++){ | |
notes[n] => Std.mtof => this.bloop[n].freq; | |
} | |
} | |
fun void set_voice_volume(int polyphony){ | |
this.max_gain / this.polyphony => this.voice_volume; | |
} | |
fun void set_polyphony(int notes[]){ | |
if (notes.cap() <= 1) 1 => this.polyphony; | |
else notes.cap() => this.polyphony; | |
// this could be optimized by only adding elements if polyphony increases | |
// and .clear() on the array and build a new one if polyphony decreases | |
WaveformMixerMono bloop[this.polyphony] @=> this.bloop; | |
Pan2 pan_array[this.polyphony] @=> this.pan_array; | |
for(0 => int n; n<notes.cap(); n++){ | |
this.bloop[n].mixer2(2.3); | |
this.bloop[n].final => this.pan_array[n] => this.sum_waveforms; | |
this.bloop[n].final.gain(this.voice_volume); | |
((((n%2)*2)-1)*0.9) => this.pan_array[n].pan; | |
} | |
} | |
} | |
// gist -m | |
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
PolySynth polysynBass; | |
PolySynth polysynArp; | |
PolySynth polysynLead; | |
ModCarp carper; | |
carper.out => dac; | |
NRev reverb_bass[2]; | |
reverb_bass[0].mix(0.013); | |
reverb_bass[1].mix(0.013); | |
polysynBass.out.gain(1.5); | |
polysynBass.out.left => DelayA bassD => reverb_bass[0] => dac.left; | |
polysynBass.out.right => reverb_bass[1] => dac.right; | |
123::samp => bassD.delay => bassD.max; | |
NRev reverb_arp[2]; | |
reverb_arp[0].mix(0.07); | |
reverb_arp[1].mix(0.07); | |
polysynArp.out.gain(.31); | |
polysynArp.out.left => reverb_arp[0] => dac.left; | |
polysynArp.out.right => DelayA arpD => reverb_arp[1] => dac.right; | |
223::samp => arpD.delay => arpD.max; | |
NRev reverb_lead[2]; | |
reverb_lead[0].mix(0.21); | |
reverb_lead[1].mix(0.21); | |
polysynLead.out.gain(.41); | |
reverb_lead[0].gain(0.11); | |
reverb_lead[1].gain(0.11); | |
polysynLead.out => Mix2 leadgain => dac; | |
leadgain.gain(0.6); | |
Chorus pads[2]; | |
polysynLead.out.left => pads[0] => reverb_lead[0] => dac.left; | |
polysynLead.out.right => pads[1] => DelayA leadD => reverb_lead[1] => dac.right; | |
143::samp => leadD.delay => leadD.max; | |
for(0 => int i; i<pads.cap(); i++){ | |
pads[i].gain(21.2); | |
pads[i].modFreq(0.25 + i*0.032); | |
pads[i].modDepth(.052 + i*0.014); | |
} | |
[1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, | |
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0] @=> int pseq[]; | |
[0, 52, 54, 55] @=> int arp_1_notes[]; | |
[0, 50, 52, 53] @=> int arp_2_notes[]; | |
[2,0,3,2,2,3,2,2,3,2,2,2,1,2,2,3,2,0,3,2,2,3,2,2,3,2,2,2,1,2,2] @=> int arp_1_triggers[]; | |
[42, 40, 43] @=> int bass_notes[]; | |
// this is mighty ugly, but it allows each note to have a unique decay length. | |
[[54, 500], [0, 0], [55, 300], [54, 300], [61, 2300], | |
[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], | |
[66, 600], [0, 0], [64, 500], [66, 200], [61, 3100], | |
[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], | |
[54, 350], [0, 0], [55, 300], [54, 360], [61, 370], [0, 0], [66, 300], [0, 0], [64, 5300] | |
] @=> int lead_notes_1[][]; | |
[[54, 500], [0, 0], [55, 300], [54, 300], [61, 2300], | |
[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], | |
[66, 600], [0, 0], [64, 500], [66, 200], [61, 3100], | |
[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], | |
[54, 350], [0, 0], [55, 300], [54, 360], [61, 370], [0, 0], [66, 300], [0, 0], [67, 5300] | |
] @=> int lead_notes_2[][]; | |
// INTRO | |
repeat(1){ | |
polysynArp.set_envelopes(2, 217, 2, 1410); | |
spork ~ play_lead(lead_notes_1); | |
spork ~ play_arp(arp_1_notes, arp_1_triggers); | |
spork ~ play_bassline(bass_notes[0], pseq, 0, 32); | |
advance_time(32); | |
spork ~ play_arp(arp_2_notes, arp_1_triggers); | |
spork ~ play_bassline(bass_notes[1], pseq, 0, 32); | |
advance_time(32); | |
spork ~ play_lead(lead_notes_2); | |
spork ~ play_arp(arp_1_notes, arp_1_triggers); | |
spork ~ play_bassline(bass_notes[0], pseq, 0, 32); | |
advance_time(32); | |
spork ~ play_arp(arp_1_notes, arp_1_triggers); | |
spork ~ play_bassline(bass_notes[2], pseq, 0, 32); | |
advance_time(32); | |
} | |
fun int to_int(float input){ | |
input $ int => int output; | |
return output; | |
} | |
// lead | |
fun void play_lead(int sequence[][]){ | |
int tnote; | |
for(0 => int i; i<sequence.cap(); i++){ | |
sequence[i][0] => int tval; | |
if (tval > 0) { | |
tval + 12 => tnote; | |
sequence[i][1] => int decay; | |
polysynLead.set_envelopes(42, decay, 22, to_int(decay*1.3)); | |
polysynLead.play_synth([tnote, tnote], 7500.0, 2.9, 2.1); | |
} | |
advance_time(); | |
} | |
advance_time(25); | |
} | |
fun void play_bassline(int note, int triggers[], int start, int end){ | |
// extra insurance | |
if (end > triggers.cap()) triggers.cap() => end; | |
for(start => int i; i<end; i++){ | |
if ( triggers[i] == 1){ | |
polysynBass.play_synth([note, note], 1500.0, 2.9, 1.2); | |
} | |
advance_time(); | |
} | |
} | |
fun void play_arp(int notes[], int triggers[]){ | |
for(0 => int i; i<triggers.cap(); i++){ | |
triggers[i] => int trigval; | |
if (trigval > 0) { | |
notes[trigval] + 12 => int note_val; | |
(notes[trigval] * 90) => float filter_from_freq; | |
polysynArp.play_synth([note_val,note_val], filter_from_freq+1100.0, 5.2, 2.4); | |
carper.play(note_val, 0.5, 2, 140); | |
} | |
advance_time(); | |
} | |
} | |
// overloading, careful. | |
fun void advance_time(int num_units){ | |
(0.13::second * num_units) => now; | |
} | |
fun void advance_time(){ | |
0.13::second => now; | |
} | |
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
public class WaveformMixerMono{ | |
SinOsc vsin => Gain final; | |
SawOsc vsaw => final; | |
TriOsc vtri => final; | |
PulseOsc vpls => final; | |
Noise vnse => final; | |
440 => float frequency; | |
fun void pwidth(float pw){ | |
pw => this.vpls.width; | |
} | |
fun void freq(float frequency){ | |
frequency => this.frequency; | |
vsin.freq(frequency); | |
vsaw.freq(frequency); | |
vtri.freq(frequency); | |
vpls.freq(frequency); | |
} | |
fun void mixer(float components[], float mgain){ | |
mixer(components); | |
mgain => this.final.gain; | |
} | |
fun void mixer2(float continual){ | |
// continual range is 0.0 to 8.0 | |
// goes from (sin, saw, tri, pulse to noise) | |
float mix_comp[]; | |
if (continual >= 7.9996) [0.0, 0.0, 0.0, 0.0, 1.0] @=> mix_comp; | |
else if (continual <= 0.0001) [1.0, 0.0, 0.0, 0.0, 0.0] @=> mix_comp; | |
else { | |
continual => float j; | |
Math.floor(j/2.0) $ int => int k; | |
k*2 => int k2; | |
((j - k2) / 2.0) => float n; | |
mix_arrays(k, n) @=> mix_comp; | |
} | |
mixer(mix_comp); | |
} | |
fun void mixer(float components[]){ | |
// set defautls, just in case -- make it a SinOsc | |
if (!(components.cap() == 5)) { | |
[1.0, 0.0, 0.0, 0.0, 0.0] @=> components; | |
} | |
float summer; | |
for(0 => int i; i<components.cap(); i++){ | |
components[i] +=> summer; | |
} | |
if (summer <= 0.0) { | |
<<< "no sound!" >>>; | |
0.0 => this.vsin.gain; | |
0.0 => this.vsaw.gain; | |
0.0 => this.vtri.gain; | |
0.0 => this.vpls.gain; | |
0.0 => this.vnse.gain; | |
} | |
else{ | |
components[0] / summer => this.vsin.gain; | |
components[1] / summer => this.vsaw.gain; | |
components[2] / summer => this.vtri.gain; | |
components[3] / summer => this.vpls.gain; | |
components[4] / summer => this.vnse.gain; | |
} | |
} | |
fun float fixmin(float fin){ | |
if (fin < 0.0001) return 0.0; | |
else return fin; | |
} | |
fun float[] mix_arrays(int idx, float amount){ | |
[0.0, 0.0, 0.0, 0.0, 0.0] @=> float final_mix[]; | |
(1-amount) => fixmin => final_mix[idx]; | |
(amount) => fixmin => final_mix[idx+1]; | |
return final_mix; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment