Update chordProgression

Update chordProgression

modulation added
\>chuck chordProgression
1. send chords out (key/root/type)
2. play chords in Rhodey

class Chord
{
    0=>static int mode;
    0=>int style;
    Chord @ next[];
    int notes[];
    int root;                         //the root key
    int type;                         //major,minor,etc
    float probabilities[][];              //probability for each next state
    Chord @ modulationSequence[][];
    Chord @ modulationChord[];
    int modulationTarget[];
    fun void init(int root, int type, Chord next[], float probabilities[][])
    {
        setRoot(root);
        setType(type);
        setNext(next);
        setProbabilities(probabilities);
        setNotes();
    }
    fun void setRoot(int i)
    {
        i=>root;
    }
    fun void setType(int i)
    {
        i=>type;
    }
    fun void setNext(Chord c[])
    {
        c@=>next;
    }
    fun void setProbabilities(float f[][])
    {
        f@=>probabilities;
    }
    fun Chord getNextChord()
    {
        return getNextChord(mode);
    }
    fun Chord getNextChord(int i)
    {
        Std.rand2f(0, 1)=>float rand;
        0=>float c;
        getProbabilities(i)@=>float p[];
        for (0=>int i; i<p.cap()-1;i++)
        {
            p[i]+=>c;
            if (rand<=c)
                return next[i];
        }
        return next[next.cap()-1];
    }
    fun float[] getProbabilities(int i)
    {
        return probabilities[i];
    }
    fun string toString()
    {
        [["I","i","Idim","Iaug","Isus4","I7"],
         ["bII","bii"],
         ["II","ii"],
         ["bIII","biii"],
         ["III","iii"],
         ["IV","vi"],
         ["bV","bv"],
         ["V","v","Vdim","Vaug","Vsus4","V7"],
         ["bVI","bvi"],
         ["VI","vi","VIdim","VIaug","VIsus4"],
         ["bVII","bvii"],
         ["VII","vii"]]@=>string s[][];
        return s[root][type];
    }
    fun void setNotes()
    {
        if (type==0)
        {
            [root,root+4,root+7]@=>notes;
        }
        if (type==1)
        {
            [root,root+3,root+7]@=>notes;
        }
        if (type==2)
        {
            [root,root+3,root+6]@=>notes;
        }
        if (type==3)
        {
            [root,root+4,root+8]@=>notes;
        }
        if (type==4)
        {
            [root,root+5,root+7]@=>notes;
        }
        if (type==5)
        {
            [root,root+4,root+7,root+10]@=>notes;
        }

    }
    fun int[] getNotesWithin()
    {
        return notes;
    }
    fun void setModulation(Chord modulation[][], int target[], Chord chord[])
    {
        modulation@=>modulationSequence;
        target@=>modulationTarget;
        chord@=>modulationChord;
    }
    fun Chord[][] getModulationSequence()
    {
        return modulationSequence;
    }
    fun int[] getModulationTarget()
    {
        return modulationTarget;
    }
    fun Chord[] getModulationChord()
    {
        return modulationChord;
    }
}

//runing code starts here
OscSend send;
"localhost" => string hostname;
6449 => int port;
send.setHost(hostname,port);
Chord current;
Chord I;
Chord I7;
Chord ii;
Chord II;
Chord iii;
Chord III;
Chord IV;
Chord V;
Chord V7;
Chord vi;
Chord VI;
Chord Isus4;
Chord VIsus4;
I.init(0,0,[I,ii,III,IV,V,vi],[[0.1,0.1,0.1,0.3,0.3,0.1],[0.1,0.1,0.1,0.1,0.1,0.5]]);
I7.init(0,5,[I7],[[1.0],[1.0]]);
ii.init(2,1,[I,iii,III,V,vi],[[0.1,0.1,0.3,0.4,0.1],[0.1,0.4,0.3,0.1,0.1]]);
II.init(2,0,[II],[[1.0],[1.0]]);
iii.init(4,1,[V,IV,vi],[[0.4,0.4,0.2],[0.2,0.3,0.5]]);
III.init(4,0,[IV,vi],[[0.6,0.4],[0.3,0.7]]);
IV.init(5,0,[I,V,III],[[0.3,0.6,0.1],[0.2,0.5,0.3]]);
V.init(7,0,[I,vi,ii,iii,Isus4,V7],[[0.2,0.2,0.1,0.2,0.1,0.2],[0.2,0.1,0.1,0.2,0.2,0.2]]);
V7.init(7,5,[I,vi],[[0.8,0.2],[0.4,0.6]]);
vi.init(9,1,[I,ii,iii,IV,V,vi],[[0.1,0.3,0.1,0.3,0.1,0.1],[0.1,0.2,0.2,0.2,0.2,0.1]]);
Isus4.init(0,4,[I],[[1.0],[1.0]]);
VIsus4.init(9,4,[vi],[[1.0],[1.0]]);
VI.init(9,0,[VI],[[1.0],[1.0]]);
III.setModulation([[VIsus4,VI]],[-3],[I]);
I.setModulation([[VI,II],[I7,IV]],[2,5],[I,I]);
I @=> current;
Rhodey  instruments[4];
for (0=>int i; i < instruments.cap(); i++)
{
    instruments[i]=>dac;
}
0=>int key;
while (true)
{
    <<< "Chord Name: ", current.toString() >>>;
    current.root=>int root;
    current.type=>int type;
    key => send.addInt;
    root => send.addInt;
    type => send.addInt;
    <<< "Sent key: ", key, "root: ", root, ", type: ", type >>>;
    current.getNotesWithin()@=>int notes[];
    for (0=>int j;j<4;j++)
    {
        0.5::second=>now;
        for (0=>int i; i < instruments.cap(); i++)
        {
            Std.mtof(48+(key+notes[i%notes.cap()])%12)=>instruments[i].freq;
            if (j==0)
                0.2=>instruments[i].noteOn;
            else if (Math.random2f(0,1)<0.7)
                0.1=>instruments[i].noteOn;
        }
    }
    if (current.getModulationTarget()!=null&&Math.random2f(0,1)<0.9)
    {

        current.getModulationSequence()@=>Chord sq[][];
        current.getModulationTarget()@=>int keys[];
        current.getModulationChord()@=>Chord chords[];
        Math.random2f(0,sq.cap())  $ int  =>int choice;
        sq[choice]@=>Chord chordSq[];
        keys[choice]=>int keyChange;
        chords[choice]@=>Chord modChord;
        for (0=>int i; i <chordSq.cap();i++)
        {
            chordSq[i]@=>current;
                <<< "Chord Name: ", current.toString() >>>;
            current.root=>int root;
            current.type=>int type;
            key => send.addInt;
            root => send.addInt;
            type => send.addInt;
            <<< "Sent key: ", key, "root: ", root, ", type: ", type >>>;
            current.getNotesWithin()@=>int notes[];
            for (0=>int j;j<4;j++)
            {
                0.5::second=>now;
                for (0=>int i; i < instruments.cap(); i++)
                {
                    Std.mtof(48+(key+notes[i%notes.cap()])%12)=>instruments[i].freq;
                    if (j==0)
                        0.2=>instruments[i].noteOn;
                    else if (Math.random2f(0,1)<0.7)
                        0.1=>instruments[i].noteOn;
                }
            }
        }
        modChord.getNextChord()@=>current;
        (key+keyChange+12)%12=>key;
    }
    else
    {
        current.getNextChord()@=>current;
    }
}

class Chord
{
    0=>int style;
    Chord @ next[];
    int root;                         //the root key
    int type;                         //major,minor,etc
    float probabilities[][];              //probability for each next state
    fun void init(int root, int type, Chord next[], float probabilities[][])
    {
        setRoot(root);
        setType(type);
        setNext(next);
        setProbabilities(probabilities);
    }
    fun void setRoot(int i)
    {
        i=>root;
    }
    fun void setType(int i)
    {
        i=>type;
    }
    fun void setNext(Chord c[])
    {
        c@=>next;
    }
    fun void setProbabilities(float f[][])
    {
        f@=>probabilities;
    }
    fun Chord getNextChord()
    {
        return getNextChord(0);
    }
    fun Chord getNextChord(int i)
    {
        Std.rand2f(0, 1)=>float rand;
        0=>float c;
        getProbabilities(i)@=>float p[];
        for (0=>int i; i<p.cap();i++)
        {
            p[i]+=>c;
            if (rand<=c)
                return next[i];
        }
        return this;
    }
    fun float[] getProbabilities(int i)
    {
        return probabilities[i];
    }
    fun string toString()
    {
        [["I","i"],
         ["bII","bii"],
         ["II","ii"],
         ["bIII","biii"],
         ["III","iii"],
         ["IV","vi"],
         ["bV","bv"],
         ["V","v"],
         ["bVI","bvi"],
         ["VI","vi"],
         ["bVII","bvii"],
         ["VII","vii"]]@=>string s[][];
        return s[root][type];
    }
    fun int[] getNotesWithin()
    {
        if (type==0)
        {
            return [root,root+4,root+7];
        }
        if (type==1)
        {
            return [root,root+3,root+7];
        }
        if (type==2)
        {
            return [root,root+3,root+6];
        }
        return null;
    }
}

//runing code starts here
OscSend send;
"localhost" => string hostname;
6449 => int port;
send.setHost(hostname,port);
Chord previous;
Chord current;
Chord I;
Chord ii;
Chord iii;
Chord III;
Chord IV;
Chord V;
Chord V7;
Chord vi;
I.init(0,0,[I,ii,III,IV,V,vi],[[0.1,0.1,0.1,0.3,0.3,0.1],[0.1,0.1,0.1,0.1,0.1,0.5]]);
ii.init(2,1,[I,iii,III,V,vi],[[0.1,0.1,0.3,0.4,0.1],[0.1,0.4,0.3,0.1,0.1]]);
iii.init(4,1,[V,IV,vi],[[0.4,0.4,0.2],[0.2,0.3,0.5]]);
III.init(4,0,[IV,vi],[[0.6,0.4],[0.3,0.7]]);
IV.init(5,0,[I,V,III],[[0.3,0.6,0.1],[0.2,0.5,0.3]]);
V.init(7,0,[I,vi,ii,iii],[[0.5,0.2,0.1,0.2],[0.3,0.4,0.1,0.2]]);
vi.init(9,1,[I,ii,iii,IV,V,vi],[[0.1,0.3,0.1,0.3,0.1,0.1],[0.1,0.2,0.2,0.2,0.2,0.1]]);
I @=> current;
Rhodey  instruments[4];
for (0=>int i; i < instruments.cap(); i++)
{
    instruments[i]=>dac;
}
while (true)
{
    <<< "Chord Name: ", current.toString() >>>;
    0=>int key;
    current.root=>int root;
    current.type=>int type;
    key => send.addInt;
    root => send.addInt;
    type => send.addInt;
    <<< "Sent key: ", key, "root: ", root, ", type: ", type >>>;
    current.getNotesWithin()@=>int notes[];
    for (0=>int j;j<4;j++)
    {
        0.7::second=>now;
        for (0=>int i; i < instruments.cap(); i++)
        {
            Std.mtof(48+key+(notes[i%notes.cap()])%12)=>instruments[i].freq;
            if (j==0)
                0.2=>instruments[i].noteOn;
            else if (Math.random2f(0,1)<0.7)
                0.1=>instruments[i].noteOn;
        }
    }
    current.getNextChord(1)@=>Chord temp;
    while (temp==previous)
    {
        current.getNextChord(1)@=>temp;
    }
    current @=> previous;
    temp @=> current;
}


Update common_functions.ck

Update common_functions.ck

haha, changing array references tripped me up.

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_string_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] join_int_arrays(int arr1[], int arr2[]){}
    fun int[] set_from(int arr[]){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[] expand_scale(int scale[], int start_stop[]){
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] join_int_arrays(int arr1[], int arr2[]){
    [arr1, arr2] @=> int arr[][];
    int new_arr[0];
    for(0 => int j; j<arr.cap(); j++){

        for(0 => int i; i<arr[j].cap(); i++){
            new_arr << arr[j][i];
        }
    }
    return new_arr;
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun int[] expand_scale(int scale[], int start_stop[]){

    // assumes we start somewhere above 0
    start_stop[0] => int start;
    start_stop[1] => int end;

    int expand_array[0];
    -1 => int last;
    int current;
    for(start => int i; i < end; i++){
        for(0 => int n; n<scale.cap(); n++){
            // avoids doubles, if the incoming scale ends an
            // octave above the first note
            scale[n] + (i*12) => current;
            if (!(current == last)){
                expand_array << current;
                current => last;
            }
        }
    }
    return expand_array;
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_string_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}

fun int[] set_from(int arr[]){
    // no order guaranteed
    // requires  inArray() to be present.
    int new_arr[0];
    new_arr << arr[0];

    for(1 => int i; i<arr.cap(); i++){
        if (inArray(arr[i], new_arr) == 0){
            new_arr << arr[i];
        }
    }
    return new_arr;
}

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_string_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] join_int_arrays(int arr1[], int arr2[]){}
    fun int[] set_from(int arr[]){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[] expand_scale(int scale[], int start_stop[]){
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] join_int_arrays(int arr1[], int arr2[]){
    for(0 => int i; i<arr2.cap(); i++){
        arr1 << arr2[i];
    }
    return arr1;
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun int[] expand_scale(int scale[], int start_stop[]){

    // assumes we start somewhere above 0
    start_stop[0] => int start;
    start_stop[1] => int end;

    int expand_array[0];
    -1 => int last;
    int current;
    for(start => int i; i < end; i++){
        for(0 => int n; n<scale.cap(); n++){
            // avoids doubles, if the incoming scale ends an
            // octave above the first note
            scale[n] + (i*12) => current;
            if (!(current == last)){
                expand_array << current;
                current => last;
            }
        }
    }
    return expand_array;
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_string_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}

fun int[] set_from(int arr[]){
    // no order guaranteed
    // requires  inArray() to be present.
    int new_arr[0];
    new_arr << arr[0];

    for(1 => int i; i<arr.cap(); i++){
        if (inArray(arr[i], new_arr) == 0){
            new_arr << arr[i];
        }
    }
    return new_arr;
}


Update common_functions.ck

Update common_functions.ck

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_int_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[] expand_scale(int scale[], int start_stop[]){
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun int[] expand_scale(int scale[], int start_stop[]){

    // assumes we start somewhere above 0
    start_stop[0] => int start;
    start_stop[1] => int end;

    int expand_array[0];
    -1 => int last;
    int current;
    for(start => int i; i < end; i++){
        for(0 => int n; n<scale.cap(); n++){
            // avoids doubles, if the incoming scale ends an
            // octave above the first note
            scale[n] + (i*12) => current;
            if (!(current == last)){
                expand_array << current;
                current => last;
            }
        }
    }
    return expand_array;
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_int_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_int_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_int_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}


Update bassdrum_electronic_deepboom.ck

Update bassdrum_electronic_deepboom.ck

// Assignment 7 drumCircleDSP
public class KickSynC{

    0.0 => float mgain;
    Gain bdmast;
    bdmast.gain(mgain);

    fun void trigger(float volume){
        this.bdmast.gain(volume);
        spork ~ s_do_kick();
    }

    fun void s_do_kick(){

        CurveTable c;
        [0., 310, -.98,  1.0,50,-.6, 11.0, 1.] => c.coefs;

        // frequency curve
        ADSR e => blackhole;
        e.set( 0::ms, 621::ms, 0.0, 135::ms );  //a, d, s, r
        e.keyOn(1);

        // simple adsr
        ADSR volE;
        volE.set( 0::ms, 181::ms, 0.0, 65::ms );  //a, d, s, r
        volE.keyOn();

        // routing.
        c => blackhole;
        SinOsc form => volE => LPF boom => PoleZero dc => bdmast;
        dc.blockZero(0.992);
        70 => boom.freq;

        // set

        now => time start;
        // ready
        while (true)
        {
            c.lookup(1/e.value()) $ int => form.freq;
            boom.Q(1.3);
            41::samp => now;

            // advance time
            if (now > (start + 170::ms)){
                e.keyOff();
                volE.keyOff();
                break;
            }
        }

        1::second => now;
    }

}

KickSynC kick1;

kick1.bdmast => dac;
kick1.trigger(1.3);

1::second => now;

// Assignment 7 drumCircleDSP

public class KickSynC{

    Gain bdmaster2 => dac;
    bdmaster2.gain(0.02);

    fun void trigger(float volume){
        /* this makes it possible to trigger
        the bassdrum in a new thread */
        spork ~ s_do_kick(volume);
    }

    fun void s_do_kick(float volume){

        3850 => float frequency;

        SinOsc bd_osc =>
        Gain preAmp => HPF bf => ADSR volEnv =>
        PoleZero dc => LPF highs => bdmaster2;

        dc.blockZero(0.99);
        bf.freq(50);
        bf.Q(4.1);
        highs.freq(332);

        volEnv.set( 1::ms, 181::ms, 0.3, 35::ms );
        bdmaster2.gain(volume);

        1 => int fa;
        44 => int fd;
        50 => int fs;
        120 => int fr;

        44100/frequency => float grain;

        Step s5 => ADSR pitchEnv => blackhole;
        pitchEnv.set(fa::ms, (fd/1.2)::ms, fs/100, fr::ms);
        pitchEnv.keyOn(1);
        volEnv.keyOn(1);
        (140)::ms + now => time later;
        while(now < later)
        {
            850 => int min_freq;
            51 => int bass_freq;
            ((pitchEnv.last()*220) + min_freq) $ int => int pitch_curve;
            Math.max(pitch_curve, bass_freq) - 800.0 => float debug_freq => bd_osc.freq;

            grain::samp => now;

            if( now > later){
                (120)::ms => now;
                volEnv.keyOff(1);
                pitchEnv.keyOff(1);
            }
        }

        1.5::second => now;
        bd_osc =< preAmp;

    }

}

KickSynC kick1;

kick1.trigger(0.5);

1::second => now;


Update common_functions.ck

Update common_functions.ck

added   `fun int[] set_from(int arr[])`

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_string_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] set_from(int arr[]){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[] expand_scale(int scale[], int start_stop[]){
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun int[] expand_scale(int scale[], int start_stop[]){

    // assumes we start somewhere above 0
    start_stop[0] => int start;
    start_stop[1] => int end;

    int expand_array[0];
    -1 => int last;
    int current;
    for(start => int i; i < end; i++){
        for(0 => int n; n<scale.cap(); n++){
            // avoids doubles, if the incoming scale ends an
            // octave above the first note
            scale[n] + (i*12) => current;
            if (!(current == last)){
                expand_array << current;
                current => last;
            }
        }
    }
    return expand_array;
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_string_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}

fun int[] set_from(int arr[]){
    // no order guaranteed
    // requires  inArray() to be present.
    int new_arr[0];
    new_arr << arr[0];

    for(1 => int i; i<arr.cap(); i++){
        if (inArray(arr[i], new_arr) == 0){
            new_arr << arr[i];
        }
    }
    return new_arr;
}

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_string_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[] expand_scale(int scale[], int start_stop[]){
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun int[] expand_scale(int scale[], int start_stop[]){

    // assumes we start somewhere above 0
    start_stop[0] => int start;
    start_stop[1] => int end;

    int expand_array[0];
    -1 => int last;
    int current;
    for(start => int i; i < end; i++){
        for(0 => int n; n<scale.cap(); n++){
            // avoids doubles, if the incoming scale ends an
            // octave above the first note
            scale[n] + (i*12) => current;
            if (!(current == last)){
                expand_array << current;
                current => last;
            }
        }
    }
    return expand_array;
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_string_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}


added meaningful comments

added meaningful comments

//WindChime.ck

public class WindChime {

    0.995 => float block_value;
    PoleZero dcCorrector; dcCorrector.blockZero(block_value);

    Mix2 mout;
    NRev rvb => dcCorrector => mout;
    rvb.mix(0.12);
    mout.gain(0.133);

    dur a, d, s, r;
    float s_level;

    float midint;
    0.02 => float chime_vol; // default
    rvb => DelayA td => rvb;
    td.delay(70::ms);
    td.max(70::ms);
    td.gain(0.33);

    fun void set_chime_vol(float chime_vol){
        chime_vol => this.chime_vol;
    }

    fun void set_adsr(dur a, dur d, dur s, float s_level, dur r){
        a => this.a;
        d => this.d;
        s => this.s;
        s_level => this.s_level;
        r => this.r;
    }

    fun void s_play_note(){
        SinOsc s => ADSR env => rvb;
        SinOsc s2 => env;
        SinOsc s3 => env;
        SinOsc s0 => env;
        SinOsc m => s;

        env => Pan2 p;
        Math.random2f( 0.8, -0.8 ) => p.pan;
        NRev rvs[2];

        p.left => rvs[0] => mout.left;
        p.right => rvs[1] => mout.right;
        for(0 => int i; i<rvs.cap(); i++){
            rvs[i].mix(0.19);
        }

        s.sync(2);
        s.gain(chime_vol);
        midint => Std.mtof => float gfreq => s.freq;
        s2.freq((gfreq*2) + 0.012);
        s2.freq() * Math.random2f(.922, 1.052) => s2.freq;
        s2.gain(chime_vol*0.8);
        s3.freq(gfreq*0.5);
        s3.freq() * Math.random2f(.988, 1.022) => s3.freq;
        s3.gain(chime_vol*.22);
        s0.freq(gfreq*4/(midint/17.65));
        s0.freq() * Math.random2f(.992, 1.022) => s0.freq;
        s0.gain(chime_vol*.052);
        m.freq(2 * gfreq);
        m.gain(3000);

        // Envelope config
        // maybe these should be randomized too
        env.set( a, d, s_level, r );
        env.keyOn();
        (this.a + this.d + this.s) => now;
        env.keyOff();
        this.r => now;
    }

    fun void play_note(float midint){
        midint => this.midint;
        spork ~ s_play_note();
    }

    // this sets a default, incase i forget to
    set_adsr( 3::ms, 291::ms, 31::ms, .620, 335::ms );  //a, d, s, r

}

WindChime wc;
wc.set_chime_vol(0.37);

// this enforces the overal loudness of the patch, else it would
// tend to go into a feedback gain. I didn't investigate why
ADSR sound_sculpt[2];
wc.mout.left => sound_sculpt[0] => dac.left;
wc.mout.right => sound_sculpt[1] => dac.right;

sound_sculpt[0].set( 0::ms, 0::ms, 1.0, 3235::ms );  //a, d, s, r
sound_sculpt[1].set( 0::ms, 0::ms, 1.0, 3235::ms );  //a, d, s, r
sound_sculpt[0].keyOn();
sound_sculpt[1].keyOn();

36 => int num_chimes;
120.0 => float start_note;
1 / 1.4 => float rate;  // speed at which this traverses the chime

// simulate fingers traveling along chimes.
for(0 => int i; i<num_chimes; i++){
    wc.play_note(start_note-(i*0.6));
    (Math.random2f(0.139, 0.142) * rate) ::second =>now;
}

sound_sculpt[0].keyOff();
sound_sculpt[1].keyOff();

// prevent clicks
7::second => now;

//WindChime.ck

public class WindChime {

    0.995 => float block_value;
    PoleZero dcCorrector; dcCorrector.blockZero(block_value);

    Mix2 mout;
    NRev rvb => dcCorrector => mout;
    rvb.mix(0.12);
    mout.gain(0.133);

    dur a, d, s, r;
    float s_level;

    float midint;
    0.02 => float chime_vol; // default
    rvb => DelayA td => rvb;
    td.delay(70::ms);
    td.max(70::ms);
    td.gain(0.33);

    fun void set_chime_vol(float chime_vol){
        chime_vol => this.chime_vol;
    }

    fun void set_adsr(dur a, dur d, dur s, float s_level, dur r){
        a => this.a;
        d => this.d;
        s => this.s;
        s_level => this.s_level;
        r => this.r;
    }

    fun void s_play_note(){
        SinOsc s => ADSR env => rvb;
        SinOsc s2 => env;
        SinOsc s3 => env;
        SinOsc s0 => env;
        SinOsc m => s;

        env => Pan2 p;
        Math.random2f( 0.8, -0.8 ) => p.pan;
        NRev rvs[2];

        p.left => rvs[0] => mout.left;
        p.right => rvs[1] => mout.right;
        for(0 => int i; i<rvs.cap(); i++){
            rvs[i].mix(0.19);
        }

        s.sync(2);
        s.gain(chime_vol);
        midint => Std.mtof => float gfreq => s.freq;
        s2.freq((gfreq*2) + 0.012);
        s2.freq() * Math.random2f(.922, 1.052) => s2.freq;
        s2.gain(chime_vol*0.8);
        s3.freq(gfreq*0.5);
        s3.freq() * Math.random2f(.988, 1.022) => s3.freq;
        s3.gain(chime_vol*.22);
        s0.freq(gfreq*4/(midint/17.65));
        s0.freq() * Math.random2f(.992, 1.022) => s0.freq;
        s0.gain(chime_vol*.052);
        m.freq(2 * gfreq);
        m.gain(3000);

        // Envelope config
        // maybe these should be randomized too
        env.set( a, d, s_level, r );
        env.keyOn();
        (this.a + this.d + this.s) => now;
        env.keyOff();
        this.r => now;
    }

    fun void play_note(float midint){
        midint => this.midint;
        spork ~ s_play_note();
    }

    // this sets a default, incase i forget to
    set_adsr( 2::ms, 291::ms, 31::ms, .620, 335::ms );  //a, d, s, r

}

WindChime wc;
ADSR sound_sculpt[2];
36 => int num_chimes;
wc.mout.left => sound_sculpt[0] => dac.left;
wc.mout.right => sound_sculpt[1] => dac.right;
sound_sculpt[0].set( 0::ms, 0::ms, 1.0, 3235::ms );  //a, d, s, r
sound_sculpt[1].set( 0::ms, 0::ms, 1.0, 3235::ms );  //a, d, s, r
wc.set_chime_vol(0.37);
sound_sculpt[0].keyOn();
sound_sculpt[1].keyOn();
120.0 => float start_note;
1 / 1.4 => float rate;
for(0 => int i; i<num_chimes; i++){
    wc.play_note(start_note-(i*0.6));
    (Math.random2f(0.139, 0.142) * rate) ::second =>now;
}
sound_sculpt[0].keyOff();
sound_sculpt[1].keyOff();
// prevent clicks
7::second => now;


sounds better

sounds better

this way

//WindChime.ck

public class WindChime {

    Mix2 mout;
    NRev rvb => mout;
    rvb.mix(0.22);
    mout.gain(0.3);
    dur a;
    dur d;
    dur s;
    float s_level;
    dur r;
    float midint;
    0.02 => float chime_vol; // default

    fun void set_chime_vol(float chime_vol){
        chime_vol => this.chime_vol;
    }

    fun void set_adsr(dur a, dur d, dur s, float s_level, dur r){
        a => this.a;
        d => this.d;
        s => this.s;
        s_level => this.s_level;
        r => this.r;
    }

    fun void s_play_note(){
        SinOsc s => ADSR env => rvb;
        SinOsc m => s;
        s.sync(2);
        s.gain(chime_vol);
        midint => Std.mtof => float gfreq => s.freq;
        m.freq(2 * gfreq);
        m.gain(3000);

        // Envelope config
        env.set( a, d, s_level, r );
        env.keyOn();
        (this.a + this.d + this.s) => now;
        env.keyOff();
        this.r => now;
    }

    fun void play_note(float midint){
        midint => this.midint;
        spork ~ s_play_note();
    }

    // this sets a defult, incase i forget to
    set_adsr( 2::ms, 281::ms, 191::ms, .590, 35::ms );  //a, d, s, r

}

WindChime wc;
wc.mout => dac;
wc.set_chime_vol(0.08);

120.0 => float start_note;
for(0 => int i; i<25; i++){
    wc.play_note(start_note-(i*0.6));
    .11::second =>now;
}

// prevent clicks
2::second => now;

//WindChime.ck

public class WindChime {

    Mix2 mout;
    NRev rvb => mout;
    rvb.mix(0.02);
    mout.gain(0.3);
    dur a;
    dur d;
    dur s;
    float s_level;
    dur r;
    float midint;
    0.02 => float chime_vol; // default

    fun void set_chime_vol(float chime_vol){
        chime_vol => this.chime_vol;
    }

    fun void set_adsr(dur a, dur d, dur s, float s_level, dur r){
        a => this.a;
        d => this.d;
        s => this.s;
        s_level => this.s_level;
        r => this.r;
    }

    fun void s_play_note(){
        SinOsc s => ADSR env => rvb;
        SinOsc m => s;
        s.sync(2);
        s.gain(chime_vol);
        midint => Std.mtof => float gfreq => s.freq;
        m.freq(2 * gfreq);
        m.gain(3000);

        // Envelope config
        env.set( a, d, s_level, r );
        env.keyOn();
        (this.a + this.d + this.s) => now;
        env.keyOff();
        r => now;
    }

    fun void play_note(float midint){
        midint => this.midint;
        spork ~ s_play_note();
    }

    // this sets a defult, incase i forget to
    set_adsr( 2::ms, 61::ms, 311::ms, .50, 235::ms );  //a, d, s, r

}

WindChime wc;
wc.mout => dac;
wc.set_chime_vol(0.08);

90.0 => float start_note;
for(0 => int i; i<25; i++){
    wc.play_note(start_note-(i*0.6));
    .12::second =>now;
}

// prevent clicks
2::second => now;


haha more accurate

haha more accurate

listening to tonebender.

//WindChime.ck

public class WindChime {

    Mix2 mout;
    NRev rvb => mout;
    rvb.mix(0.22);
    mout.gain(0.3);
    dur a;
    dur d;
    dur s;
    float s_level;
    dur r;
    float midint;
    0.02 => float chime_vol; // default

    fun void set_chime_vol(float chime_vol){
        chime_vol => this.chime_vol;
    }

    fun void set_adsr(dur a, dur d, dur s, float s_level, dur r){
        a => this.a;
        d => this.d;
        s => this.s;
        s_level => this.s_level;
        r => this.r;
    }

    fun void s_play_note(){
        SinOsc s => ADSR env => rvb;
        SinOsc s2 => env;
        SinOsc m => s;

        env => Pan2 p;
        Math.random2f( 0.8, -0.8 ) => p.pan;
        NRev rvs[2];

        p.left => rvs[0] => mout.left;
        p.right => rvs[1] => mout.right;
        for(0 => int i; i<rvs.cap(); i++){
            rvs[i].mix(0.19);
        }

        s.sync(2);
        s.gain(chime_vol);
        midint => Std.mtof => float gfreq => s.freq;
        s2.freq(gfreq + 0.012);
        s2.gain(chime_vol);
        m.freq(2 * gfreq);
        m.gain(3000);

        // Envelope config
        env.set( a, d, s_level, r );
        env.keyOn();
        (this.a + this.d + this.s) => now;
        env.keyOff();
        this.r => now;
    }

    fun void play_note(float midint){
        midint => this.midint;
        spork ~ s_play_note();
    }

    // this sets a defult, incase i forget to
    set_adsr( 2::ms, 151::ms, 121::ms, .890, 35::ms );  //a, d, s, r

}

WindChime wc;
wc.mout => dac;
wc.set_chime_vol(0.18);

120.0 => float start_note;
for(0 => int i; i<25; i++){
    wc.play_note(start_note-(i*0.6));
    (0.12 )::second =>now;
}

// prevent clicks
2::second => now;

//WindChime.ck

public class WindChime {

    Mix2 mout;
    NRev rvb => mout;
    rvb.mix(0.22);
    mout.gain(0.3);
    dur a;
    dur d;
    dur s;
    float s_level;
    dur r;
    float midint;
    0.02 => float chime_vol; // default

    fun void set_chime_vol(float chime_vol){
        chime_vol => this.chime_vol;
    }

    fun void set_adsr(dur a, dur d, dur s, float s_level, dur r){
        a => this.a;
        d => this.d;
        s => this.s;
        s_level => this.s_level;
        r => this.r;
    }

    fun void s_play_note(){
        SinOsc s => ADSR env => rvb;
        SinOsc m => s;
        s.sync(2);
        s.gain(chime_vol);
        midint => Std.mtof => float gfreq => s.freq;
        m.freq(2 * gfreq);
        m.gain(3000);

        // Envelope config
        env.set( a, d, s_level, r );
        env.keyOn();
        (this.a + this.d + this.s) => now;
        env.keyOff();
        this.r => now;
    }

    fun void play_note(float midint){
        midint => this.midint;
        spork ~ s_play_note();
    }

    // this sets a defult, incase i forget to
    set_adsr( 2::ms, 281::ms, 191::ms, .590, 35::ms );  //a, d, s, r

}

WindChime wc;
wc.mout => dac;
wc.set_chime_vol(0.08);

120.0 => float start_note;
for(0 => int i; i<25; i++){
    wc.play_note(start_note-(i*0.6));
    .11::second =>now;
}

// prevent clicks
2::second => now;


Update common_functions.ck

Update common_functions.ck

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_string_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] join_int_arrays(int arr1[], int arr2[]){}
    fun int[] repeat_int_array(int arr[], int num_times){}
    fun int[] set_from(int arr[]){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[] expand_scale(int scale[], int start_stop[]){
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] join_int_arrays(int arr1[], int arr2[]){
    [arr1, arr2] @=> int arr[][];
    int new_arr[0];
    for(0 => int j; j<arr.cap(); j++){

        for(0 => int i; i<arr[j].cap(); i++){
            new_arr << arr[j][i];
        }
    }
    return new_arr;
}

fun int[] repeat_int_array(int arr[], int num_times){
    int new_arr[0];
    for(0 => int j; j<num_times; j++){
        for(0 => int i; i<arr.cap(); i++){
            new_arr << arr[i];
        }
    }
    return new_arr;
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun int[] expand_scale(int scale[], int start_stop[]){

    // assumes we start somewhere above 0
    start_stop[0] => int start;
    start_stop[1] => int end;

    int expand_array[0];
    -1 => int last;
    int current;
    for(start => int i; i < end; i++){
        for(0 => int n; n<scale.cap(); n++){
            // avoids doubles, if the incoming scale ends an
            // octave above the first note
            scale[n] + (i*12) => current;
            if (!(current == last)){
                expand_array << current;
                current => last;
            }
        }
    }
    return expand_array;
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_string_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}

fun int[] set_from(int arr[]){
    // no order guaranteed
    // requires  inArray() to be present.
    int new_arr[0];
    new_arr << arr[0];

    for(1 => int i; i<arr.cap(); i++){
        if (inArray(arr[i], new_arr) == 0){
            new_arr << arr[i];
        }
    }
    return new_arr;
}

// Machine.add("utilities.ck");

/*
    definitions

    fun void repr_int_array(int arr[]){}
    fun void repr_string_array(string arr[]){}

    fun int random_from(int arr[]){}
    fun int inArray(int token, int arr[]){}
    fun int indexOfClosest(int ival, int arr[]){}
    fun int to_note(string str){}
    fun int[] join_int_arrays(int arr1[], int arr2[]){}
    fun int[] set_from(int arr[]){}
    fun int[] randomArray_from(int arr[], int length){}
    fun int[] range(int start, int end){}
    fun int[] narray(int start, int next, int up_to){}
    fun int[] expand_scale(int scale[], int start_stop[]){
    fun int[][] stepify(string sequence_data[]){}

    fun float average(int arr[]){}

    fun string repr(int arr[]){}
    fun string repr(string arr[]){}
    fun string[] split(string arr, string token){}

    fun SndBuf load_sample(string wavname){}

    https://gist.github.com/anonymous/7206152

*/

fun string[] split_str(string str, string token){

    string collect[0];
    int pos;
    int pos2;
    while( str.find(token) >0){
        str.find(token) => pos2;
        collect << str.substring(pos, pos2);
        str.substring(pos2+1) => str;
    }
    collect << str;
    return collect;
}

fun int random_from(int arr[]){
    return arr[Math.random2(0, arr.cap()-1)];
}

fun int[] join_int_arrays(int arr1[], int arr2[]){
    [arr1, arr2] @=> int arr[][];
    int new_arr[0];
    for(0 => int j; j<arr.cap(); j++){

        for(0 => int i; i<arr[j].cap(); i++){
            new_arr << arr[j][i];
        }
    }
    return new_arr;
}

fun int[] randomArray_from(int arr[], int length){
    // return new array of capacity length chosing elements from arr
    int generated_arr[0];
    for(0 => int i; i<length; i++){
        generated_arr << random_from(arr); // append element
    }
    return generated_arr;
}

fun int[] range(int start, int end){
    // includes start and end
    int arr[0];
    for(start => int i; i<=end; i++) arr << i;
    return arr;
}

fun int[] narray(int start, int next, int up_to){
    // (start, end..up_to)  (inclusive)
    int arr[0];
    start => int cval;
    next - start => int jump;
    for(cval; cval<=up_to; jump +=> cval){
        arr << cval;
    }
    return arr;  // matey!
}

fun int[] expand_scale(int scale[], int start_stop[]){

    // assumes we start somewhere above 0
    start_stop[0] => int start;
    start_stop[1] => int end;

    int expand_array[0];
    -1 => int last;
    int current;
    for(start => int i; i < end; i++){
        for(0 => int n; n<scale.cap(); n++){
            // avoids doubles, if the incoming scale ends an
            // octave above the first note
            scale[n] + (i*12) => current;
            if (!(current == last)){
                expand_array << current;
                current => last;
            }
        }
    }
    return expand_array;
}

fun string repr(int arr[]){
    /*
    this returns a string representation of an int array,
    useful for debug printing.
    */
    "[" + Std.itoa(arr[0]) => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + Std.itoa(arr[i]) +=> s;
    }
    return s + "]";
}

fun string repr(string arr[]){

    //this returns a string representation of a string array,
    //useful for debug printing.

    "[" + arr[0] => string s;
    for (1 => int i; i < arr.cap(); i++){
        "," + arr[i] +=> s;
    }
    return s + "]";
}

fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun void repr_string_array(string arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "]";
    chout <= IO.newline();
}

fun int inArray(int token, int arr[]){
    /*
    tests membership of an array
    */
    for(0 => int i; i<arr.cap(); i++){
        if (arr[i]==token) return 1;
    }
    return 0;
}

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 int[][] stepify(string sequence_data[]){
    /*
    this function converts a string array to an int array,
    it accepts fuzzy formatting:
    "1..1..1..1.." becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    "1..1.   .1..1.." also becomes [1,0,0,1,0,0,1,0,0,1,0,0]
    */

    sequence_data.cap() => int parts;
    32 => int steps;  // hard code for now
    <<< parts, steps >>>;

    int data_store[parts][steps];
    for(0 => int i; i<sequence_data.cap(); i++){

        sequence_data[i] => string seq_string;
        int part_data[0];
        int trigger;
        //<<< seq_string >>>;
        for(0 => int j; j < seq_string.length(); j++){
            seq_string.substring(j,1) => string token; // crazy

            if (token == " ") continue;
            if (token == ".") 0 => trigger;
            else if (token == "1") 1 => trigger;

            part_data << trigger;
        }
        //<<< repr_int_array(part_data)>>>;
        part_data @=> data_store[i];
    }
    return data_store;
}

fun SndBuf load_sample(string wavname){

    // usage
    // load_sample("kick_02") @=> SndBuf kick => dac;

    // turn incoming wavname into   path/wavename.wav
    // return a reference to a new buffer object.
    SndBuf temp_buff;
    me.dir() + "/audio/" + wavname  + ".wav" => temp_buff.read;

    // set to end, and set gain, then return the object
    temp_buff.samples() => temp_buff.pos;
    0.8 => temp_buff.gain;
    return temp_buff;
}

fun float average(int arr[]){
    int sum;
    arr.cap() => int num_items;
    for(0 => int i; i < num_items; i++){
        arr[i] +=> sum;
    }
    sum $ float => float fsum;
    num_items $ float => float fcap;
    return fsum / fcap;
}

fun int indexOfClosest(int ival, int arr[]){
    // will find the closest value to ival in arr
    // if there are multiple, it will return the first.
    Math.INT_MAX => int min_distance;
    0 => int diff;
    -1 => int idx_tracker;

    for(0 => int i; i<arr.cap(); i++)
    {
        Math.abs(arr[i] - ival) => diff;
        if (diff < min_distance)
        {
            diff => min_distance;
            i => idx_tracker;
        }
    }
    return idx_tracker;

}

fun int[] set_from(int arr[]){
    // no order guaranteed
    // requires  inArray() to be present.
    int new_arr[0];
    new_arr << arr[0];

    for(1 => int i; i<arr.cap(); i++){
        if (inArray(arr[i], new_arr) == 0){
            new_arr << arr[i];
        }
    }
    return new_arr;
}


button press messages now floats

button press messages now floats

the current version of osculator sends the A and B button presses as
floats, while the old one sent them as ints.

OscRecv           wm;
Launchpad         lp;
OscBank oscBank;

false    =>   int prompt;
50::samp =>   dur gainResolution;
0.0016   => float releaseDecay;
0.00001  => float sustainDecay;
0.00001  => float sostenutoDecay;
0.01     => float pressAttack;
0.80     => float maxNoteGain;
0.0      => float wiiAccel;
0        =>   int currentTone;
false    =>   int sustain;
              int sustainStatus[8][8];
false    =>   int sostenuto;
              int sostenutoStatus[8][8];
0        =>   int lpChannel;

LaunchpadColor.green => int keyOnColor;
LaunchpadColor.red => int keySustainColor;
LaunchpadColor.orange => int keySostenutoColor;
LaunchpadColor.red => int toneChoiceColor;

fun void setup()
{
    OscBank.OscBank(8, 8, 1, 5, 82.4068867, 12.0) @=> oscBank;

    if(prompt) {
        intPrompt("Enter Midi Channel for Launchpad input: ") => lpChannel;
        Launchpad.Launchpad(lpChannel) @=> lp;
    } else {
        Launchpad.Launchpad(0) @=> lp;
    }

    me.yield();
    lp.clear();
    lp.setGridLight(8, currentTone, toneChoiceColor);

    spork ~ launchpadListener();
    spork ~ wiiListener();
    spork ~ updateGains();
}

OscSend           toUI;
toUI.setHost("localhost", 9000);

fun void sendOsc(string path, int val) {
    toUI.startMsg(path, "i");
    val => toUI.addInt;
}

fun void setTone(int toneChoice)
{
    if(toneChoice == currentTone) { return; }
    else if(toneChoice == 0)      { oscBank.setPatch("SinOsc"); }
    else if(toneChoice == 1)      { oscBank.setPatch("SqrOsc"); }
    else if(toneChoice == 2)      { oscBank.setPatch("SawOsc"); }
    else if(toneChoice == 3)      { oscBank.setPatch("TriOsc"); }
    else                          { return; }

    lp.setGridLight(8, currentTone, 0);
    lp.setGridLight(8, toneChoice, toneChoiceColor);
    toneChoice => currentTone;
}

fun void setSostenuto(int enabled) {
    enabled => sostenuto;
    for(0 => int x; x < 8; x++) {
        for(0 => int y; y < 8; y++) {
            lp.keyDown[x][y] && enabled => sostenutoStatus[x][y];
            if(!enabled && !lp.keyDown[x][y] && !sustainStatus[x][y]) {
                lp.setGridLight(x, y, 0);
                sendOsc("/grid/noteOff", y * 8 + x);
            }
        }
    }
}

fun void setSustain(int enabled) {
    enabled => sustain;
    for(0 => int x; x < 8; x++) {
        for(0 => int y; y < 8; y++) {
            lp.keyDown[x][y] => int down;
            down && enabled => sustainStatus[x][y];
            if(!down && !sostenutoStatus[x][y]) {
                lp.setGridLight(x, y, 0);
                sendOsc("/grid/noteOff", y * 8 + x);
            }
        }
    }
}

fun void release(int column, int row)
{
    Math.max(oscBank.gains[column][row].gain() - releaseDecay, 0.00)
        => oscBank.gains[column][row].gain;
}

fun void updateSustain(int column, int row, float targetGain)
{
    if(sustain && sustainStatus[column][row])
    {
        Math.max(oscBank.gains[column][row].gain() - sustainDecay, 0.00)
            => oscBank.gains[column][row].gain;
    }
    else
    {
        release(column, row);
    }
}

fun void updateSostenuto(int column, int row, float targetGain)
{
    if(sostenuto && sostenutoStatus[column][row])
    {
        Math.max(oscBank.gains[column][row].gain() - sostenutoDecay, 0.00)
            => oscBank.gains[column][row].gain;
    }
    else
    {
        updateSustain(column, row, targetGain);
    }
}

fun void update(int column, int row, float targetGain)
{
    if(lp.keyDown[column][row] && targetGain > oscBank.gains[column][row].gain())
    {
        Math.min(oscBank.gains[column][row].gain() + pressAttack, maxNoteGain)
            => oscBank.gains[column][row].gain;
    }
    else
    {
        updateSostenuto(column, row, targetGain);
    }
}

fun void updateGains()
{
    float targetGain;
    while(true) {
        // Math.max(0.0, (wiiAccel - 32) / 95.0) => targetGain;
        wiiAccel => targetGain;

        for(0 => int i; i < 8; i++) {
            for(0 => int j; j < 8; j++) {
                update(i, j, targetGain);
            }
        }

        gainResolution => now;
    }
}

fun int intPrompt(string msg)
{
    int in;
    ConsoleInput cin;
    StringTokenizer tok;
    cin.prompt(msg) => now;
    while(cin.more())
    {
        tok.set(cin.getLine());
        while(tok.more())
        {
            Std.atoi(tok.next()) => in;
        }
    }
    return in;
}

fun void launchpadListener()
{
    while(true)
    {
        lp.e => now;

        // ignore button presses that are not on the grid
        if(lp.e.column < 0 || lp.e.column > 8) continue;
        if(lp.e.row < 0 || lp.e.row > 7) continue;

        if(lp.e.column == 8)
        {
            if(lp.e.velocity == 127)
            {
                setTone(lp.e.row);
            }
        }
        else if(lp.e.velocity == 127)
        {
            if(sustain)
            {
                true => sustainStatus[lp.e.column][lp.e.row];
            }
            lp.setGridLight(lp.e.column, lp.e.row, keyOnColor);
            1 => oscBank.bank[lp.e.column][lp.e.row].op;
            sendOsc("/grid/noteOn", lp.e.row * 8 + lp.e.column);
        }
        else if(sostenuto && sostenutoStatus[lp.e.column][lp.e.row])
        {
            lp.setGridLight(lp.e.column, lp.e.row, keySostenutoColor);
        }
        else if(sustain && sustainStatus[lp.e.column][lp.e.row])
        {
            lp.setGridLight(lp.e.column, lp.e.row, keySustainColor);
        }
        else
        {
            lp.setGridLight(lp.e.column, lp.e.row, 0);
            sendOsc("/grid/noteOff", lp.e.row * 8 + lp.e.column);
        }
    }
}

fun void sustainListener() {
    wm.event("/wii/1/button/B,f") @=> OscEvent e;
    while(true) {
        e => now;
        while(e.nextMsg() != 0) {
            setSustain(e.getFloat() != 0);
        }
    }
}

fun void sostenutoListener()
{
    wm.event("/wii/1/button/A,f") @=> OscEvent e;
    while(true) {
        e => now;
        while(e.nextMsg() != 0) {
            setSostenuto(e.getFloat() != 0);
        }
    }
}

fun void accelListener()
{
    wm.event("/wii/1/accel/pry/3,f") @=> OscEvent e;
    while(true) {
        e => now;
        while(e.nextMsg() != 0) {
            Math.max(0.0, e.getFloat() - 0.22) => wiiAccel;
            // chout <= wiiAccel <= IO.newline();
        }
    }
}

fun void wiiListener()
{
    6449 => wm.port;
    // 8000 => wm.port;
    wm.listen();
    spork ~ sustainListener();
    spork ~ sostenutoListener();
    spork ~ accelListener();
    while(true) { 1::second => now; }
}

setup();
while(true) { 100::ms => now; }

OscRecv           wm;
Launchpad         lp;
OscBank oscBank;

false    =>   int prompt;
50::samp =>   dur gainResolution;
0.0016   => float releaseDecay;
0.00001  => float sustainDecay;
0.00001  => float sostenutoDecay;
0.01     => float pressAttack;
0.80     => float maxNoteGain;
0.0      => float wiiAccel;
0        =>   int currentTone;
false    =>   int sustain;
              int sustainStatus[8][8];
false    =>   int sostenuto;
              int sostenutoStatus[8][8];
0        =>   int lpChannel;

LaunchpadColor.green => int keyOnColor;
LaunchpadColor.red => int keySustainColor;
LaunchpadColor.orange => int keySostenutoColor;
LaunchpadColor.red => int toneChoiceColor;

fun void setup()
{
    OscBank.OscBank(8, 8, 1, 5, 82.4068867, 12.0) @=> oscBank;

    if(prompt) {
        intPrompt("Enter Midi Channel for Launchpad input: ") => lpChannel;
        Launchpad.Launchpad(lpChannel) @=> lp;
    } else {
        Launchpad.Launchpad(0) @=> lp;
    }

    me.yield();
    lp.clear();
    lp.setGridLight(8, currentTone, toneChoiceColor);

    spork ~ launchpadListener();
    spork ~ wiiListener();
    spork ~ updateGains();
}

OscSend           toUI;
toUI.setHost("localhost", 9000);

fun void sendOsc(string path, int val) {
    toUI.startMsg(path, "i");
    val => toUI.addInt;
    <<< val >>>;
}

fun void setTone(int toneChoice)
{
    if(toneChoice == currentTone) { return; }
    else if(toneChoice == 0)      { oscBank.setPatch("SinOsc"); }
    else if(toneChoice == 1)      { oscBank.setPatch("SqrOsc"); }
    else if(toneChoice == 2)      { oscBank.setPatch("SawOsc"); }
    else if(toneChoice == 3)      { oscBank.setPatch("TriOsc"); }
    else                          { return; }

    lp.setGridLight(8, currentTone, 0);
    lp.setGridLight(8, toneChoice, toneChoiceColor);
    toneChoice => currentTone;
}

fun void setSostenuto(int enabled) {
    enabled => sostenuto;
    for(0 => int x; x < 8; x++) {
        for(0 => int y; y < 8; y++) {
            lp.keyDown[x][y] && enabled => sostenutoStatus[x][y];
            if(!enabled && !lp.keyDown[x][y] && !sustainStatus[x][y]) {
                lp.setGridLight(x, y, 0);
                sendOsc("/grid/noteOff", y * 8 + x);
            }
        }
    }
}

fun void setSustain(int enabled) {
    enabled => sustain;
    for(0 => int x; x < 8; x++) {
        for(0 => int y; y < 8; y++) {
            lp.keyDown[x][y] => int down;
            down && enabled => sustainStatus[x][y];
            if(!down && !sostenutoStatus[x][y]) {
                lp.setGridLight(x, y, 0);
                sendOsc("/grid/noteOff", y * 8 + x);
            }
        }
    }
}

fun void release(int column, int row)
{
    Math.max(oscBank.gains[column][row].gain() - releaseDecay, 0.00)
        => oscBank.gains[column][row].gain;
}

fun void updateSustain(int column, int row, float targetGain)
{
    if(sustain && sustainStatus[column][row])
    {
        Math.max(oscBank.gains[column][row].gain() - sustainDecay, 0.00)
            => oscBank.gains[column][row].gain;
    }
    else
    {
        release(column, row);
    }
}

fun void updateSostenuto(int column, int row, float targetGain)
{
    if(sostenuto && sostenutoStatus[column][row])
    {
        Math.max(oscBank.gains[column][row].gain() - sostenutoDecay, 0.00)
            => oscBank.gains[column][row].gain;
    }
    else
    {
        updateSustain(column, row, targetGain);
    }
}

fun void update(int column, int row, float targetGain)
{
    if(lp.keyDown[column][row] && targetGain > oscBank.gains[column][row].gain())
    {
        Math.min(oscBank.gains[column][row].gain() + pressAttack, maxNoteGain)
            => oscBank.gains[column][row].gain;
    }
    else
    {
        updateSostenuto(column, row, targetGain);
    }
}

fun void updateGains()
{
    float targetGain;
    while(true) {
        // Math.max(0.0, (wiiAccel - 32) / 95.0) => targetGain;
        wiiAccel => targetGain;

        for(0 => int i; i < 8; i++) {
            for(0 => int j; j < 8; j++) {
                update(i, j, targetGain);
            }
        }

        gainResolution => now;
    }
}

fun int intPrompt(string msg)
{
    int in;
    ConsoleInput cin;
    StringTokenizer tok;
    cin.prompt(msg) => now;
    while(cin.more())
    {
        tok.set(cin.getLine());
        while(tok.more())
        {
            Std.atoi(tok.next()) => in;
        }
    }
    return in;
}

fun void launchpadListener()
{
    while(true)
    {
        lp.e => now;

        // ignore button presses that are not on the grid
        if(lp.e.column < 0 || lp.e.column > 8) continue;
        if(lp.e.row < 0 || lp.e.row > 7) continue;

        if(lp.e.column == 8)
        {
            if(lp.e.velocity == 127)
            {
                setTone(lp.e.row);
            }
        }
        else if(lp.e.velocity == 127)
        {
            if(sustain)
            {
                true => sustainStatus[lp.e.column][lp.e.row];
            }
            lp.setGridLight(lp.e.column, lp.e.row, keyOnColor);
            1 => oscBank.bank[lp.e.column][lp.e.row].op;
            sendOsc("/grid/noteOn", lp.e.row * 8 + lp.e.column);
        }
        else if(sostenuto && sostenutoStatus[lp.e.column][lp.e.row])
        {
            lp.setGridLight(lp.e.column, lp.e.row, keySostenutoColor);
        }
        else if(sustain && sustainStatus[lp.e.column][lp.e.row])
        {
            lp.setGridLight(lp.e.column, lp.e.row, keySustainColor);
        }
        else
        {
            lp.setGridLight(lp.e.column, lp.e.row, 0);
            sendOsc("/grid/noteOff", lp.e.row * 8 + lp.e.column);
        }
    }
}

fun void sustainListener() {
    wm.event("/wii/1/button/B,i") @=> OscEvent e;
    while(true) {
        e => now;
        while(e.nextMsg() != 0) {
            setSustain(e.getInt() != 0);
        }
    }
}

fun void sostenutoListener()
{
    wm.event("/wii/1/button/A,i") @=> OscEvent e;
    while(true) {
        e => now;
        while(e.nextMsg() != 0) {
            setSostenuto(e.getInt() != 0);
        }
    }
}

fun void accelListener()
{
    wm.event("/wii/1/accel/pry/3,f") @=> OscEvent e;
    while(true) {
        e => now;
        while(e.nextMsg() != 0) {
            Math.max(0.0, e.getFloat() - 0.22) => wiiAccel;
            chout <= wiiAccel <= IO.newline();
        }
    }
}

fun void wiiListener()
{
    6449 => wm.port;
    // 8000 => wm.port;
    wm.listen();
    spork ~ sustainListener();
    spork ~ sostenutoListener();
    spork ~ accelListener();
    while(true) { 1::second => now; }
}

setup();
while(true) { 100::ms => now; }


Update to_stereo_wav_with_gainParams.ck

Update to_stereo_wav_with_gainParams.ck

//me.arg(0) => string filename;
//if( filename.length() == 0 ) "foo.wav" => filename;

dac => Mix2 regulator => WvOut2 w => blackhole;
//"data/session" => w.autoPrefix;

regulator.gain(1.0);
"woooot.wav" => w.wavFilename;
1 => w.record;
3::second => now;

// everything in between gets recorded.

0 => w.record;
w.fileClose();


Update bassdrum_electronic_deepboom3.ck

Update bassdrum_electronic_deepboom3.ck

public class KickSynC{

    0.0 => float mgain;
    Gain bdmast;
    bdmast.gain(mgain);

    fun void trigger(float volume){
        this.bdmast.gain(volume/3.3);
        spork ~ s_do_kick();
    }

    fun void s_do_kick(){

        CurveTable c;
        [0., 1590, -7.98,
        0.05, 240, -.98,
        .17, 114, 0,
        .61, 54, 0,
        1.8, 41.] => c.coefs;

        // frequency curve
        ADSR e => blackhole;
        e.set( 0::ms, 740::ms, 0.0, 125::ms );  //a, d, s, r
        e.keyOn(1);

        // simple adsr
        ADSR volE;
        volE.set( 0::ms, 281::ms, 0.0, 65::ms );  //a, d, s, r
        volE.keyOn();

        // routing.
        c => blackhole;
        Dyno comp => bdmast;
        comp.compress();
        SinOsc form => volE => LPF boom => PoleZero dc => comp;
        dc.blockZero(0.994);
        432 => boom.freq;

        // set

        now => time start;
        // ready
        while (true)
        {
            c.lookup(1/e.value()) $ int => form.freq;
            boom.Q(.26);
            21::samp => now;

            // advance time
            if (now > (start + 280::ms)){
                e.keyOff();
                volE.keyOff();
                break;
            }
        }

        1::second => now;
    }

}

/*
    Usage docs

    KickSynC kick1;

    kick1.bdmast => dac;
    kick1.bdmast => NRev blunk => dac;
    blunk.gain(0.01);
    blunk.mix(0.2);

    for(0 => int i; i<5; i++){
        kick1.trigger(4.4);
        0.5::second => now;
    }
*/

// with some example how to wire it up.

public class KickSynC{

    0.0 => float mgain;
    Gain bdmast;
    bdmast.gain(mgain);

    fun void trigger(float volume){
        this.bdmast.gain(volume/3.3);
        spork ~ s_do_kick();
    }

    fun void s_do_kick(){

        CurveTable c;
        [0., 1590, -7.98,
        0.05, 240, -.98,
        .17, 114, 0,
        .61, 54, 0,
        1.8, 41.] => c.coefs;

        // frequency curve
        ADSR e => blackhole;
        e.set( 0::ms, 740::ms, 0.0, 125::ms );  //a, d, s, r
        e.keyOn(1);

        // simple adsr
        ADSR volE;
        volE.set( 0::ms, 281::ms, 0.0, 65::ms );  //a, d, s, r
        volE.keyOn();

        // routing.
        c => blackhole;
        Dyno comp => bdmast;
        comp.compress();
        SinOsc form => volE => LPF boom => PoleZero dc => comp;
        dc.blockZero(0.994);
        432 => boom.freq;

        // set

        now => time start;
        // ready
        while (true)
        {
            c.lookup(1/e.value()) $ int => form.freq;
            boom.Q(.26);
            21::samp => now;

            // advance time
            if (now > (start + 280::ms)){
                e.keyOff();
                volE.keyOff();
                break;
            }
        }

        1::second => now;
    }

}

KickSynC kick1;

kick1.bdmast => dac;
kick1.bdmast => NRev blunk => dac;
blunk.gain(0.01);
blunk.mix(0.2);

for(0 => int i; i<5; i++){
    kick1.trigger(4.4);
    0.5::second => now;
}


test files names changed

test files names changed

Stammer stm => dac;
2.0 => stm.set_freq;
spork ~ stm.local_loop();

SndBuf buf_1;
SndBuf buf_2;
me.dir() + "/../sounds/test_sound_01.wav" => buf_1.read;
me.dir() + "/../sounds/test_sound_02.wav" => buf_2.read;

buf_2 => stm;
10::second => now;

buf_2 =< stm;
buf_1 => stm;
10::second => now;

buf_2 => stm;
10::second => now;

Stammer stm => dac;
2.0 => stm.set_freq;
spork ~ stm.local_loop();

SndBuf buf_1;
SndBuf buf_2;
me.dir() + "/../sounds/ptaszek.wav"  => buf_1.read;
me.dir() + "/../sounds/c1_atlas.wav" => buf_2.read;

buf_2 => stm;
10::second => now;

buf_2 =< stm;
buf_1 => stm;
10::second => now;

buf_2 => stm;
10::second => now;


Update chuck_midi_in_to_notes_array.ck

Update chuck_midi_in_to_notes_array.ck

// MidiIn min;
// MidiMsg msg;

// // open midi receiver, exit on fail
// if ( !min.open(0) ) me.exit();

// while( true )
// {
//     // wait on midi event
//     min => now;

//     // receive midimsg(s)
//     while( min.recv( msg ) )
//     {
//         // print content
//         <<< msg.data1, msg.data2, msg.data3 >>>;
//     }
// }

MidiIn min;
MidiMsg msg;

// open midi receiver, exit on fail
if ( !min.open(0) ) me.exit();

int notes[0];
while( true )
{
    // wait on midi event
    min => now;

    // receive midimsg(s)
    while( min.recv( msg ) )
    {
        // print content
        msg.data1 => int mode;
        msg.data2 => int note;
        msg.data3 => int volume;

        if (mode == 128) notes << note;
        //else { [] @=> notes; }
    }
    if (notes.cap() > 0) {
        repr_int_array(notes);
    }
    int a[0] @=> notes;
}

//  array
fun void repr_int_array(int arr[])
{
    arr.cap() => int num_items;
    chout <= "[";
    for(0 => int i; i<num_items; i++){
        if (i>0) chout <= ",";
        chout <= arr[i];
    }
    chout <= "] @=> int notes[];";
    chout <= IO.newline();
}


Update to_stereo_wav.ck

Update to_stereo_wav.ck

//me.arg(0) => string filename;
//if( filename.length() == 0 ) "foo.wav" => filename;

dac => WvOut2 w => blackhole;
//"data/session" => w.autoPrefix;
"woooot.wav" => w.wavFilename;
1 => w.record;
3::second => now;

// everything in between

0 => w.record;

//me.arg(0) => string filename;
//if( filename.length() == 0 ) "foo.wav" => filename;

dac => Gain g => WvOut2 w => blackhole;
//"data/session" => w.autoPrefix;
"woooot.wav" => w.wavFilename;
1 => w.record;
3::second => now;

// everything in between

0 => w.record;


local chuck

local chuck