Hackfest 10011 Mortem

by graham

26 January 2006

What we did tonight:
Grant – reviewed EvWar code – Java vs. ObjC
Vinny – *wink* "Made funny faces."
Luke – Working with Sisc. Brainstormed ideas for user space filesystems. Revisionist File System, or SchemeFS.
Stephen – Learned ChucK.
Mike – Worked on a paper.
Graham – Demo’ed ChucK and experimented.

6 Responses to “Hackfest 10011 Mortem”

  1. Anonymous says:

    Here it is… my first foray into ChucK.  The idea is you have a bank of oscillators set to a given frequency.  They are either initially on or off.  Here I turn the middle one on.  You then use 1D cellular automata rules to change their state over time.  I’ll likely want to change the dummy frequencies below to notes or at least logarithmically scale them.

    You can widen the arrays for a richer sound.  The most interesting parameter is rule which lets you alter the way the state changes.  Check out here for more rules.  30 is probably the best.

    Ultimately this will become some generator with parameters you can change at runtime, but it’s a start.  Put this in your spork and shred it!

    10 => int CELL_COUNT;        // "constants"
    10.0 => float CELL_COUNTF;
    100 => int B;
    50 => int M;

    int cell[CELL_COUNT];        // cells and banks
    int cell_next[CELL_COUNT];
    sinosc banks[CELL_COUNT];

    0 => int neighborhood;        // automaton state vars
    1 => int rule_bit;
    30 => int rule;

    (1.0/CELL_COUNTF) => float bank_gain;    // scale banks

    1 => cell[cell.cap()/2];     // initialize middle cell

    for( 0 => int i; i < cell.cap(); i++ ) {

        if( cell[i] ) {
            (i*M + B) => banks[i].freq;
        }
        else {
            0 => banks[i].freq;
        }

        bank_gain => banks[i].gain;

        banks[i] => dac;

    }

    while( true ) {

        300::ms => now;    // play the sound

        // apply the rule
        (cell.cap()-1)=>int i;
        0=>int j;
        1=>int k;
        while( j < cell.cap() ) {
           
            // compute cell neighborhood

            ( cell[i%cell.cap()] * 4 + cell[j] * 2 + cell[k%cell.cap()] + 1 ) => neighborhood;

            1 => rule_bit;
            for( 1 => int m; m < neighborhood; m++ ) {
                2 *=> rule_bit;
            }

            if(rule & rule_bit) {
                1 => cell_next[j];
                (i*M + B) => banks[j].freq;
            }
            else {
                0 => cell_next[j];
                0 => banks[j].freq;
            }

            i++;j++;k++;
        }

        for( 0 => i; i < cell.cap(); i++ ) {
            cell_next[i] => cell[i];
        }
    }

    By the way, how does one properly post code?  Code tags were useless.

  2. Graham says:

    I think the graphical editor is mangling the code tags.

    Nice job. It’s nice to be able to hear the patterns.

    Here’s my version, with these modifications:
    1) it switches between the first 255 patterns
    2) it uses some of the STK instruments

    below:
    10 => int CELL_COUNT;        // "constants"
    10.0 => float CELL_COUNTF;
    100 => int B;
    100 => int M;

    int cell[CELL_COUNT];        // cells and banks
    int cell_next[CELL_COUNT];
    StifKarp banks[CELL_COUNT];
    Shakers sh => dac;

    0 => int neighborhood;        // automaton state vars
    1 => int rule_bit;
    1 => int rule;

    30 => int count;            //musical process
    1 => int c;                 //which rep
    255 => int nrules;

    (1.0/CELL_COUNTF) => float bank_gain;    // scale banks

    1 => cell[cell.cap()/2];     // initialize middle cell

    for( 0 => int i; i < cell.cap(); i++ ) {

        (i*M + B) => banks[i].freq; //init all freqs
        0.6 => banks[i].gain;  //uniform gain
        banks[i] => dac;        //hook to output
    }

    while( true ) {

        300::ms => now;    // play the sound

        //change the rule every so often
        1 +=> c;
        if ( c % count == 0 ) {
            (rule+1) % nrules => rule;
            1 => cell[cell.cap()/2];         //reinit

            //shake, shake, shake
            sh.which( std.rand2(0, 22) );
            for ( 0 => int i; i < 20; i++ ) {
                sh.noteOn( 0.8 );
                std.rand2( 40, 200 ) * 1::ms => now;
            }
        }

        // apply the rule
        (cell.cap()-1)=>int i;
        0=>int j;
        1=>int k;
        while( j < cell.cap() ) {
          
            // compute cell neighborhood

            ( cell[i%cell.cap()] * 4 + cell[j] * 2 + cell[k%cell.cap()] + 1 ) => neighborhood;

            1 => rule_bit;
            for( 1 => int m; m < neighborhood; m++ ) {
                2 *=> rule_bit;
            }

            if(rule & rule_bit) {
                1 => cell_next[j];
                banks[j].pluck(1);
            }
            else {
                0 => cell_next[j];
            }

            i++;j++;k++;
        }

        for( 0 => i; i < cell.cap(); i++ ) {
            cell_next[i] => cell[i];
        }
    }

    Graham

  3. Anonymous says:

    When I run your program in Audicle and go to the Shredder (thread visualization), the spheres rotate in pleasing circles.

    Graham

  4. Stephen says:

    I love it!  It sounds like something they would play in a shrine dedicated to primitive computation.

    This could go in a lot of directions.  Next thursday I’ll play a bit more.  My sparse matrix homework calls!

    Happy Chinese New Year, by the way.

  5. Graham says:

    Happy Chinese New Year!

    I added numbers to label each section, and reinitialized the grid for each new rule. You can hear the new mp3 on my blog. I’ll try to clean up the code and post it here soon.

  6. Anonymous says:

    I gathered the spoken digits from this page at columbia

    <code>10 => int CELL_COUNT;        // "constants"
    10.0 => float CELL_COUNTF;
    100 => int B;
    100 => int M;

    int cell[CELL_COUNT];        // cells and banks
    int cell_next[CELL_COUNT];
    StifKarp banks[CELL_COUNT];
    Shakers sh => dac;

    0 => int neighborhood;        // automaton state vars
    1 => int rule_bit;
    1 => int rule;

    30 => int count;            //musical process
    1 => int c;                 //which rep
    256 => int nrules;

    ["digits/MAE_ZA.wav", "digits/MAE_1A.wav", "digits/MAE_2A.wav",
    "digits/MAE_3A.wav", "digits/MAE_4A.wav", "digits/MAE_5A.wav",
    "digits/MAE_6A.wav", "digits/MAE_7A.wav", "digits/MAE_8A.wav",
    "digits/MAE_9A.wav"] @=> string digits[10];

    sndbuf r1, r2, r3 => dac; //use these buffers to speak the numbers
    2.5 => r1.gain => r2.gain => r3.gain; //these are quiet digits

    1 => cell[cell.cap()/2];     // initialize middle cell

    for( 0 => int i; i < cell.cap(); i++ ) {
        (i*M + B) => banks[i].freq; //init all freqs
        0.5 => banks[i].gain;  //uniform gain
        banks[i] => dac;        //hook to output
    }

    fun void shake() {
      sh.which( std.rand2(0, 22) );
      for ( 0 => int i; i < 20; i++ ) {
        sh.noteOn( 0.8 );
        std.rand2( 40, 200 ) * 1::ms => now;
      }
    }

    fun void readnum(int rnum) {
      rnum => int a;
      a % 10 => int d1; //low digit
      a / 10 => a;
      a % 10 => int d2; //med digit
      a / 10 => int d3; //high digit

      if ( d3 != 0 ) {
        digits[d3] => r1.read;
        0 => r1.pos;
        1 => r1.play;
        500::ms => now;
      }

      if ( d2 != 0 || d3 != 0 ) {
        digits[d2] => r2.read;
        0 => r2.pos;
        1 => r2.play;
        500::ms => now;
      }

      digits[d1] => r3.read;
      0 => r3.pos;
      1 => r3.play;
      200::ms => now;
    }

    while( true ) {

        300::ms => now;    // play the sound

        //change the rule every so often
        1 +=> c;
        if ( c % count == 0 ) {
            (rule+1) => rule;
        if ( rule == nrules ) {
              10::second => now;
          me.exit();
        }

        for( 0 => int i; i < cell.cap(); i++ ) {
          0 => cell[i];
        }
            1 => cell[cell.cap()/2];         //reinit

        //read the number
        spork ~ readnum( rule );
        }

        // apply the rule
        (cell.cap()-1)=>int i;
        0=>int j;
        1=>int k;
        while( j < cell.cap() ) {
         
            // compute cell neighborhood
            ( cell[i%cell.cap()] * 4 + cell[j] * 2 + cell[k%cell.cap()] + 1 ) => neighborhood;

            1 => rule_bit;
            for( 1 => int m; m < neighborhood; m++ ) {
                2 *=> rule_bit;
            }

        //play the current cell
        if ( cell[j] ) banks[j].pluck(1);

        //this computes next cell
            if(rule & rule_bit) {
                1 => cell_next[j];
            }
            else {
                0 => cell_next[j];
            }

            i++;j++;k++;
        }

        for( 0 => i; i < cell.cap(); i++ ) {
            cell_next[i] => cell[i];
        }
    }</code>

    Graham

Leave a Reply