-
-
Save zeffii/7506312 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
// event driven tracker. | |
[ | |
["0.228", "note 1"], | |
["0.252", "chord 1"], | |
["0.084", "note 1"], | |
["0.249", "chord 1"], | |
["0.097", "note 1"], | |
["0.289", "chord 1"], | |
["0.079", "note 1"], | |
["0.243", "chord 1"], | |
["0.086", "note 1"], | |
["0.247", "chord 1"], | |
["0.105", "note 2"], | |
["0.143", "note 2"], | |
["0.241", "chord 2"], | |
["0.104", "note 2"], | |
["0.293", "chord 2"], | |
["0.257", "note 3"], | |
["0.283", "chord 3"], | |
["0.109", "note 3"], | |
["0.336", "chord 3"], | |
["0.238", "note 4"], | |
["0.236", "chord 4a"], | |
["0.095", "note 4"], | |
["0.241", "chord 4a"], | |
["0.093", "note 4"], | |
["0.239", "chord 4b"], | |
["0.125", "note 4"], | |
["0.245", "chord 4b"], | |
["0.114", "note 4"], | |
["0.213", "chord 4b"], | |
["0.234", "note 4"], | |
["0.251", "chord 4a"], | |
["0.103", "note 4"], | |
["0.249", "chord 4a"], | |
["0.118", "note 4"], | |
["0.096", "chord 4b"], | |
["0.229", "chord 4b"], | |
["0.263", "chord 4b"], | |
["0.099", "note 4"], | |
["0.239", "chord 4b"], | |
["0.239", "note 4" ], | |
["0.245", "chord 4a"], | |
["0.105", "note 4"], | |
["0.253", "chord 4a"], | |
["0.100", "note 4"], | |
["0.258", "chord 4b"], | |
["0.113", "note 4"], | |
["0.228", "chord 4b"], | |
["0.104", "note 4"], | |
["0.236", "chord 4b"], | |
["0.232", "note 4"], | |
["0.250", "chord 4a"], | |
["0.103", "note 4"], | |
["0.230", "chord 4a"], | |
["0.111", "note 4"], | |
["0.114", "chord 4c"], | |
["0.212", "chord 4c"], | |
["0.249", "chord 4c"], | |
["0.097", "note 4"], | |
["0.253", "chord 4c"]] @=> string durations[][]; | |
fun float midicpt(int midi_index){ | |
return Std.mtof(midi_index + 60); | |
} | |
[ "note 1", "chord 1", "note 2", "chord 2", | |
"note 3", "chord 3", "note 4", "chord 4a", | |
"chord 4b", "chord 4c" | |
] @=> string trigger_names[]; | |
// multi-dimensional array of midi notes. | |
trigger_names.cap() => int num_triggers; | |
int note_array_midis[num_triggers][4]; | |
// associative array | |
string note_array[0]; | |
"D-4 ... ... ..." => note_array["note 1"]; | |
"... A-4 C#5 E-5" => note_array["chord 1"]; | |
"C-4 ... ... ..." => note_array["note 2"]; | |
"... D-5 B-4 G-4" => note_array["chord 2"]; | |
"A-3 ... ... ..." => note_array["note 3"]; | |
"... E-5 C#5 A-4" => note_array["chord 3"]; | |
"E-4 ... ... ..." => note_array["note 4"]; | |
"... D-5 B-4 G-4" => note_array["chord 4a"]; | |
"... D-5 G-4 C-5" => note_array["chord 4b"]; | |
"G-4 C-5 D-5 G-5" => note_array["chord 4c"]; | |
// store midi arrays | |
for(0 => int t; t<num_triggers; t++){ | |
trigger_names[t] => string trigger_name; | |
note_array[trigger_name] => string keys; | |
toMidi(keys) @=> note_array_midis[t]; | |
} | |
0.5 => dac.gain; | |
4 => int polyphony; | |
Gain master => dac; | |
ADSR pEnv[polyphony]; | |
SawOsc pOsc[polyphony]; | |
Pan2 pPan[polyphony]; | |
for(0 => int n; n<polyphony; n++){ | |
pOsc[n] => pEnv[n] => pPan[n]=> dac; | |
(((n%2)*2)-1) * 0.3 => pPan[n].pan; | |
pOsc[n].gain(0.11); | |
} | |
fun void set_notes_and_triggers(int midi_notes[], float timing){ | |
for(0 => int j; j<midi_notes.cap(); j++){ | |
midi_notes[j] => int trigger_value; | |
// no real error checking for now | |
// ( possible values to handle are -1..-5 ) | |
if (trigger_value >= 0) { | |
Std.mtof(trigger_value) => float f; | |
pOsc[j].gain(0.21); | |
f => pOsc[j].freq; | |
pEnv[j].set(16::ms, (timing*1.12)::second, 0.2, 20::ms); | |
pEnv[j].keyOff(); | |
pEnv[j].keyOn(); | |
// cycle pans around a little | |
Math.random2(0,1) => int offset; | |
((((j + offset)%2)*2)-1) * 0.2 => pPan[j].pan; | |
}; | |
if (trigger_value < -1){ | |
pEnv[j].keyOff(); | |
} | |
} | |
} | |
int active[polyphony]; | |
int midi_notes[]; | |
4 => int repeats; | |
string keys; | |
for(0 => int rep; rep<repeats; rep++){ | |
//int midi_notes[]; | |
for(0 => int t; t<durations.cap(); t++){ | |
durations[t][1] => string trigger; | |
find(trigger, trigger_names) => int index; | |
note_array_midis[index] @=> int midi_notes[]; | |
<<< note_array[trigger] >>>; | |
// note-on, rests, and note-offs are dealt with by | |
// set_notes_and_triggers() | |
durations[t][0] => Std.atof => float timing; | |
set_notes_and_triggers(midi_notes, timing); | |
timing::second => now; | |
} | |
} | |
// UTLITY FUNCTIONS | |
fun int to_note(string str){ | |
if (str == "...") return -1; | |
if (str == "OFF") return -2; | |
if (str == "===") return -3; | |
// check if within supported range | |
str.substring(2) => Std.atoi => int oct; | |
if (oct < 0 || oct > 10) return -4; | |
str.substring(0,2) => str; | |
[ "C-","C#","D-","D#","E-","F-", | |
"F#","G-","G#","A-","A#","B-" | |
] @=> string notes_list[]; | |
// note must be in this list, else return -3 at the end | |
for (0 => int i; i < notes_list.cap(); i++){ | |
if (str == notes_list[i]){ | |
return (i + oct * 12); | |
} | |
} | |
return -5; | |
} | |
fun string[] split(string arr, string token){ | |
// you trim arr before feeding it to this function | |
string return_array[0]; | |
string collect; | |
string ch; | |
// a slightly unintuitive approach, but it works. | |
// if you'd like me to explain this function let me know. | |
for(0 => int i; i<arr.length(); i++){ | |
arr.substring(i, 1) => ch; | |
if (ch == token){ | |
return_array << collect.substring(0); | |
"" => collect; | |
} | |
else { ch +=> collect; } | |
} | |
return_array << collect; | |
return return_array; | |
} | |
fun int[] charArrayToMidi(string key_characters[]){ | |
// start with empty array | |
int midi_values[0]; | |
// key_characters might look like: | |
// ["G-4", "C-5", "D-5", "G-5"] | |
for(0 => int i; i<key_characters.cap(); i++){ | |
// to_note is used to convert | |
// "C-5" (string) to 60 (int) | |
to_note(key_characters[i]) => int key; | |
// add this value to the array | |
midi_values << key; | |
} | |
// seems this went ok, return the array. | |
return midi_values; | |
} | |
fun int[] toMidi(string keys){ | |
// "G-4 C-5 D-5 G-5" (input string will be formatted so) | |
// split the string on spaces, hence " " | |
split(keys, " ") @=> string key_characters[]; | |
// ["G-4", "C-5", "D-5", "G-5"] (key_characters will look like this) | |
// this converts that string array inti an int array of midi notes | |
// ..something like [55,60,62,67] .. good we can work with those! | |
charArrayToMidi(key_characters) @=> int key_values[]; | |
return key_values; | |
} | |
fun string repr(int arr[]){ | |
/* | |
this returns a string representation of an int array, | |
usage: repr([12,23,24,25]) or repr(some_array) | |
result: "[12,23,24,25]"" | |
*/ | |
"[" + Std.itoa(arr[0]) => string s; | |
for (1 => int i; i < arr.cap(); i++){ | |
"," + Std.itoa(arr[i]) +=> s; | |
} | |
return s + "]"; | |
} | |
fun int inArray(string item, string arr[]){ | |
for(0 => int i; i<arr.cap(); i++){ | |
if (arr[i] == item) return 1; | |
} | |
return 0; | |
} | |
fun int find(string item, string arr[]){ | |
for(0 => int i; i<arr.cap(); i++){ | |
if (arr[i] == item) return i; | |
} | |
return -1; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment