10 => int SIZE; // actual size is SIZE - 2 5::second => dur GEN_TIME; // time of a single generation int board[SIZE][SIZE]; 0.125 :: second => dur tempo; // 120 BPM //---------------------------------PARAMS--------------------------------// //Copies one array to another. fun void copy(int array1[][], int array2[][]) { for(0 => int j; j < SIZE; j++) { for(0 => int i; i < SIZE; i++) { array1[j][i] => array2[j][i]; } } } //The life function is the most important function in the program. //It counts the number of cells surrounding the center cell, and //determines whether it lives, dies, or stays the same. fun void life(int array[][]) { //Copies the main array to a temp array so changes can be entered into a grid //without effecting the other cells and the calculations being performed on them. int temp[SIZE][SIZE]; copy(array, temp); for(1 => int j; j < (SIZE - 1); j++) { for(1 => int i; i < (SIZE - 1); i++) { //The Moore neighborhood checks all 8 cells //surrounding the current cell in the array. 0 => int count; array[j-1][i] + array[j-1][i-1] + array[j][i-1] + array[j+1][i-1] + array[j+1][i] + array[j+1][i+1] + array[j][i+1] + array[j-1][i+1] => count; //The cell dies. if(count < 2 || count > 3) 0 => temp[j][i]; //The cell stays the same. if(count == 2) array[j][i] => temp[j][i]; //The cell either stays alive, or is "born". if(count == 3) 1 => temp[j][i]; } } copy(temp, array); } //This function prints the part of the array, since that's the only //portion of the array that we're really interested in. A live cell is marked //by a '*', and a dead or vacant cell by a ' '. fun void print(int array[][]) { <<< array[1][1],array[1][2],array[1][3],array[1][4],array[1][5], array[1][6],array[1][7],array[1][8]>>>; <<< array[2][1],array[2][2],array[2][3],array[2][4],array[2][5], array[2][6],array[2][7],array[2][8]>>>; <<< array[3][1],array[3][2],array[3][3],array[3][4],array[3][5], array[3][6],array[3][7],array[3][8]>>>; <<< array[4][1],array[4][2],array[4][3],array[4][4],array[4][5], array[4][6],array[4][7],array[4][8]>>>; <<< array[5][1],array[5][2],array[5][3],array[5][4],array[5][5], array[5][6],array[5][7],array[5][8]>>>; <<< array[6][1],array[6][2],array[6][3],array[6][4],array[6][5], array[6][6],array[6][7],array[6][8]>>>; <<< array[7][1],array[7][2],array[7][3],array[7][4],array[7][5], array[7][6],array[7][7],array[7][8]>>>; <<< array[8][1],array[8][2],array[8][3],array[8][4],array[8][5], array[8][6],array[8][7],array[8][8]>>>; <<< "-------", "-------">>>; } fun void glider(int array[][]) { 1 => array[3][2]; 1 => array[3][3]; 1 => array[3][4]; 1 => array[2][4]; 1 => array[1][3]; } fun void populate(int array[][]) { for(1 => int j; j < (SIZE - 1); j++) { for(1 => int i; i < (SIZE - 1); i++) { Math.random2(0,1) => array[j][i]; } } } //---------------------------------LIFE----------------------------------// // Keyboard Hid kb; // Hid message HidMsg msg; if( !kb.openKeyboard( 0 ) ) me.exit(); // Key costants 21 => int R_KEY; 10 => int G_KEY; //---------------------------------KEYBOARD------------------------------// 16 => int STEPS; 4 => int SOUNDS; SndBuf kick => dac; SndBuf clap => dac; SndBuf snare => dac; SndBuf hihat => dac; clap => Delay drumdL => dac.left; drumdL => Gain ddaL => drumdL; clap => Delay drumdR => dac.right; drumdR => Gain ddaR => drumdR; hihat => drumdL; hihat => drumdR; snare => drumdL; snare => drumdR; 0.2 => drumdR.gain; 0.3 => drumdL.gain; .5 => ddaL.gain; .2 => ddaR.gain; 750::ms => drumdL.max => drumdL.delay; 500::ms => drumdR.max => drumdR.delay; 0 => kick.gain => hihat.gain => clap.gain => snare.gain; // load up some samples of those me.dir()+"/audio/bd.wav" => kick.read; me.dir()+"/audio/cl.wav" => clap.read; me.dir()+"/audio/hh.wav" => hihat.read; me.dir()+"/audio/sd.wav" => snare.read; // virtual sequencer to tell drums when to play int Hits[STEPS*SOUNDS]; // loop fun void play() { while( true ) { 0 => int beat; while (beat < 16) { // play kick drum on based on array value if (Hits[beat]) { 0 => kick.pos; } if (Hits[beat+16]) { 0 => hihat.pos; } if (Hits[beat+32]) { 0 => clap.pos; } if (Hits[beat+48]) { 0 => snare.pos; } tempo => now; beat++; } } } fun void initialize() { 1.2 => kick.gain; 0.7 => hihat.gain; 0.7 => clap.gain; 1 => snare.gain; } // kit is the sound number // 0 = kick, 1 = hi-hat, 2 = clap, 3 = snare fun void clearSeq(int kit) { for( kit * 16 => int i; i < (16 + kit * 16); i++ ) { 0 => Hits[i]; } } // addr is the step number to modify, // kit is the sound number // 0 = kick, 1 = hi-hat, 2 = clap, 3 = snare fun void updateSeq(int addr, int kit) { Std.abs((Hits[addr+(kit*16)]) - 1) => Hits[addr+(kit*16)]; } //---------------------------------DRUMS---------------------------------// SawOsc a => Delay dL => NRev rL => LPF vcfL => dac.left; dL => Gain aL => dL; a => Delay dR => NRev rR => LPF vcfR => dac.right; dR => Gain aR => dR; SawOsc b => dL; b => dR; SawOsc c => dL; c => dR; Noise n => dL; n => dR; 0 => a.gain => b.gain => c.gain => n.gain; Std.mtof(42) => a.freq; Std.mtof(57) => b.freq; 200 => vcfL.freq => vcfR.freq; .3 => rL.mix => rR.mix; .7 => aL.gain; .8 => aR.gain; 500::ms => dL.max => dL.delay; 750::ms => dR.max => dR.delay; fun void playMelody() { while( true ) { 0.15 => a.gain => b.gain; 0.02 => c.gain; 0.04 => n.gain; tempo * 8 => now; 0 => a.gain => b.gain => c.gain => n.gain; tempo * 32 => now; } } //---------------------------------MELODY--------------------------------// TriOsc pluck => Delay dpL => NRev rpL => LPF vcfpL => dac.left; dpL => Gain apL => dpL; pluck => Delay dpR => NRev rpR => LPF vcfpR => dac.right; dpR => Gain apR => dpR; 2000 => vcfpL.freq => vcfpR.freq; .12 => rpL.mix => rpR.mix; .9 => apL.gain; .82 => dpR.gain; [66, 71, 73] @=> int notes[]; Std.mtof(66) => pluck.freq; 250::ms => dpL.max => dpL.delay; 500::ms => dpR.max => dpR.delay; 0 => pluck.gain; tempo * 64 => dur pluck_interval; 0 => int pluck_on; fun void playPluck() { while( true ) { Math.random2(0,2) => int i; Std.mtof(notes[i]) => pluck.freq; if (pluck_on == 1) 0.2 => pluck.gain; tempo * 8 => now; 0 => pluck.gain; pluck_interval => now; } } //---------------------------------PLUCK---------------------------------// fun void updateDelay(int lifeCount) { if (lifeCount == 0) { 0.1 => drumdR.gain; 0.03 => drumdL.gain; } else if (lifeCount < 2) { 0.2 => drumdR.gain; 0.3 => drumdL.gain; } else if (lifeCount < 5) { 0.4 => drumdR.gain; 0.5 => drumdL.gain; } else { 0.65 => drumdR.gain; 0.7 => drumdL.gain; } } fun void updateInterval(int lifeCount) { if (lifeCount == 0) { 0 => pluck_on; } else if (lifeCount < 3) { 1 => pluck_on; tempo * 64 => pluck_interval; } else if (lifeCount < 5) { 1 => pluck_on; tempo * 32 => pluck_interval; } else { 1 => pluck_on; tempo * 16 => pluck_interval; } } fun void updateReverb(int lifeCount) { if (lifeCount < 3) { .2 => rL.mix => rR.mix; } else if (lifeCount < 6) { .4 => rL.mix => rR.mix; } else { .65 => rL.mix => rR.mix; } } fun void updateFilter(int lifeCount) { if (lifeCount < 3) { 200 => vcfL.freq => vcfR.freq; } else if (lifeCount < 5) { 450 => vcfL.freq => vcfR.freq; } else { 800 => vcfL.freq => vcfR.freq; } } fun void updateKick(int lifeCount) { if (lifeCount == 0) { clearSeq(0); } else if (lifeCount < 3) { clearSeq(0); updateSeq(0, 0); } else if (lifeCount < 6) { clearSeq(0); updateSeq(0, 0); updateSeq(8, 0); } else { clearSeq(0); updateSeq(0, 0); updateSeq(4, 0); updateSeq(8, 0); updateSeq(12, 0); } } fun void updateSnare(int lifeCount) { if (lifeCount == 0) { clearSeq(3); } else if (lifeCount < 3) { clearSeq(3); updateSeq(4, 3); } else if (lifeCount < 6) { clearSeq(3); updateSeq(4, 3); updateSeq(15, 3); } else { clearSeq(3); updateSeq(4, 3); updateSeq(12, 3); updateSeq(15, 3); } } fun void updateClap(int lifeCount) { if (lifeCount == 0) { clearSeq(2); } else if (lifeCount < 3) { clearSeq(2); updateSeq(6, 2); } else if (lifeCount < 6) { clearSeq(2); updateSeq(6, 2); updateSeq(12, 2); } else { clearSeq(2); updateSeq(2, 2); updateSeq(6, 2); updateSeq(10, 2); updateSeq(12, 2); } } fun void updateHH(int lifeCount) { if (lifeCount == 0) { clearSeq(1); } else if (lifeCount < 3) { clearSeq(1); updateSeq(2, 1); updateSeq(10, 1); } else if (lifeCount < 6) { clearSeq(1); updateSeq(2, 1); updateSeq(6, 1); updateSeq(10, 1); updateSeq(14, 1); } else { clearSeq(1); updateSeq(0, 1); updateSeq(2, 1); updateSeq(4, 1); updateSeq(6, 1); updateSeq(8, 1); updateSeq(10, 1); updateSeq(12, 1); updateSeq(14, 1); } } fun void sequencing() { 0 => int firstRowSum; for(1 => int i; i < (SIZE - 1); i++) { firstRowSum + board[1][i] => firstRowSum; } updateDelay(firstRowSum); 0 => int secondRowSum; for(1 => int i; i < (SIZE - 1); i++) { secondRowSum + board[2][i] => secondRowSum; } updateInterval(secondRowSum); 0 => int thirdRowSum; for(1 => int i; i < (SIZE - 1); i++) { thirdRowSum + board[3][i] => thirdRowSum; } updateReverb(thirdRowSum); 0 => int fourthRowSum; for(1 => int i; i < (SIZE - 1); i++) { fourthRowSum + board[4][i] => fourthRowSum; } updateFilter(fourthRowSum); 0 => int fifthRowSum; for(1 => int i; i < (SIZE - 1); i++) { fifthRowSum + board[5][i] => fifthRowSum; } updateKick(fifthRowSum); 0 => int sixthRowSum; for(1 => int i; i < (SIZE - 1); i++) { sixthRowSum + board[6][i] => sixthRowSum; } updateSnare(sixthRowSum); 0 => int seventhRowSum; for(1 => int i; i < (SIZE - 1); i++) { seventhRowSum + board[7][i] => seventhRowSum; } updateClap(seventhRowSum); 0 => int eighthRowSum; for(1 => int i; i < (SIZE - 1); i++) { eighthRowSum + board[8][i] => eighthRowSum; } updateHH(eighthRowSum); } //-----------------------------SEQUENCING--------------------------------// //populate(board); 1::second => now; //wait for bufs initialize(); // the drum machine spork ~play(); // the drum machine spork ~playMelody(); spork ~playPluck(); fun void run_life() { while (true) { print(board); sequencing(); life(board); GEN_TIME => now; } } spork ~run_life(); while( true ) { while( kb.recv( msg ) ) { if( msg.which > 256 ) continue; if( msg.isButtonDown() ) { //<<< msg.which >>>; //for testing if( msg.which == R_KEY) { populate(board); } if( msg.which == G_KEY) { glider(board); } } } 10::ms => now; }