| author | plurSKI <black.gavin@gmail.com> | 2010-10-25 01:41:11 (GMT) |
|---|---|---|
| committer | plurSKI <black.gavin@gmail.com> | 2010-10-25 01:41:11 (GMT) |
| commit | d2c00fb78d0effeafbae38f9d987c9cee03277c4 (patch) | |
| tree | a0c15e438bf013c1e01ca2e1f5ab376c1e76d9ca | |
| download | wolframAutomata-master.zip wolframAutomata-master.tar.gz | |
Initial Commitmaster
| -rw-r--r-- | README | 19 | ||||
| -rw-r--r-- | wolframKeyboardInput.pde | 146 | ||||
| -rw-r--r-- | wolframMusicInput.pde | 171 |
3 files changed, 336 insertions, 0 deletions
@@ -0,0 +1,19 @@ +USAGE INSTRUCTIONS +------------------- + * wolframKeyboardInput.pde -- The simple version that takes mouse and keyboard events. Usage: + o Mouse click: Inverts ruleset for as long as depressed + o r: Toggles random generation on new iteration. If off it uses the old pattern + o Enter: Starts a new generation early. A new generation starts automatically when the screen is filled + o Space: Randomize ruleset + o 0 to 9: Set the corresponding rule (0-9) to what's currently in the buffer, defined below. + o a: Set the buffer to 0 (Off) + o s: Set the buffer to 1 (Blue) + o d: Set the buffer to 2 (Green) + o f: Set the buffer to 3 (Red) + o Example, change rule 2 to be red: f 2 + o Note: That if you have a way to see stdout, then every keypress will spit out the buffer and whether random generation is on or off + + * wolframMusicInput.pde -- There are two variables you need to set at the top. + o filename: contains the path to an mp3 file. + o tolerance: is used to set song pace. The faster paced the song the higher the tolerance should be to get good results. For reference, I was using 10 for the 'Frost Waltz' video and 4 for the 'Ghost Procession' video. + diff --git a/wolframKeyboardInput.pde b/wolframKeyboardInput.pde new file mode 100644 index 0000000..5391af2 --- a/dev/null +++ b/wolframKeyboardInput.pde @@ -0,0 +1,146 @@ +CA ca; +int curVal = 1; +boolean randomize = true; + +void setup() { + size(860, 860, P2D); + frameRate(30); + background(0); + int[] ruleset = {0,0,0,0,0,0,0,0,0,0}; + ca = new CA(ruleset); + ca.randomize(); +} + +void draw() +{ + ca.render(); + ca.generate(); + if (ca.finished()) newRun(); +} + +// If return is pressed restart early +void keyPressed() +{ + if(key == '\n') newRun(); + if(key == 'r') randomize = !randomize; + if ( key >= '0' && key <= '9') ca.changeRule((int)(key - '0'), curVal); + if(key == 'a') curVal = 0; + if(key == 's') curVal = 1; + if(key == 'd') curVal = 2; + if(key == 'f') curVal = 3; + if(key == ' ') ca.randomize(); + print("Current Value is: " + curVal + "\n"); + print("Randomize(" + randomize + ")\n"); +} + + +void newRun() +{ + background(0); + if(randomize) ca.randomize(); + ca.restart(); +} + + + +class CA { + int[] cells; // An array of 0s and 1s + int generation; // How many generations? + int scl; // How many pixels wide/high is each cell? + + int[] rules; // An array to store the ruleset, for example {0,1,1,0,1,1,0,1} + + CA(int[] r) { + rules = r; + scl = 1; + cells = new int[width/scl]; + restart(); + } + + CA() { + scl = 1; + cells = new int[width/scl]; + randomize(); + restart(); + } + + // Set the rules of the CA + void setRules(int[] r) { + rules = r; + } + + // Make a random ruleset + void randomize() { + for (int i = 0; i < rules.length; i++) { + rules[i] = int(random(4)); + } + } + + // Reset to generation 0 + void restart() { + for (int i = 0; i < cells.length; i++) { + cells[i] = 0; + } + cells[cells.length/2] = 1; // We arbitrarily start with just the middle cell having a state of "1" + generation = 0; + } + + // The process of creating the new generation + void generate() { + // First we create an empty array for the new values + int[] nextgen = new int[cells.length]; + // For every spot, determine new state by examing current state, and neighbor states + // Ignore edges that only have one neighor + for (int i = 1; i < cells.length-1; i++) { + int left = cells[i-1]; // Left neighbor state + int me = cells[i]; // Current state + int right = cells[i+1]; // Right neighbor staten + nextgen[i] = rules(left,me,right); // Compute next generation state based on ruleset + } + // Copy the array into current value + cells = (int[]) nextgen.clone(); + generation++; + } + + void changeRule(int i, int value) + { + rules[i] = value; + } + + // This is the easy part, just draw the cells, fill 255 for '1', fill 0 for '0' + void render() { + for (int i = 0; i < cells.length; i++) { + if (cells[i] == 1) fill(0,0,255); + else if (cells[i] == 2) fill(0,255, 0); + else if (cells[i] == 3) fill(255, 0, 0); + else fill(0); + noStroke(); + + // Radiate from the center + rect(i*scl,height/2 + (generation*scl), scl,scl); + rect(i*scl,height/2 - (generation*scl), scl,scl); + rect(height/2 + (generation*scl),i*scl, scl,scl); + rect(height/2 - (generation*scl),i*scl, scl,scl); + } + } + + // Implementing the Wolfram rules + // Could be improved and made more concise, but here we can explicitly see what is going on for each case + int rules (int a, int b, int c) { + // 0 == Off + // 1 == Blue + // 2 == Green + int retIndex = a+b+c; + if(mousePressed) retIndex = rules[rules.length - retIndex - 1]; + return rules[retIndex]; + } + + // The CA is done if it reaches the bottom of the screen + boolean finished() { + if (generation > height/scl/2) { + return true; + } else { + return false; + } + } +} diff --git a/wolframMusicInput.pde b/wolframMusicInput.pde new file mode 100644 index 0000000..b689ee5 --- a/dev/null +++ b/wolframMusicInput.pde @@ -0,0 +1,171 @@ +import ddf.minim.analysis.*; +import ddf.minim.*; + +// Change the following variables for a each song +String filename = "/path/to/ghost.mp3"; +int tolerance = 4; + + +Minim minim; +AudioPlayer jingle; +FFT fft; +CA ca; // An instance object to describe the Wolfram basic Cellular Automata +int[] prevValues = { 1, 2, 3, 1, 2, 3, 1, 2, 3, 0 }; +int[] values = { 1, 2, 3, 1, 2, 3, 1, 2, 3, 0 }; + +void setup() { + size(860, 860, P2D); + frameRate(30); + minim = new Minim(this); + + jingle = minim.loadFile(filename, 2048); + jingle.loop(); + fft = new FFT(jingle.bufferSize(), jingle.sampleRate()); + fft.linAverages(24); + background(0); + int[] ruleset = {0,0,0,0,0,0,0,0,0,0}; // An initial rule system + ca = new CA(ruleset); // Initialize CA +} + +void draw() { + ca.render(); // Draw the CA + ca.generate(); // Generate the next level + fft.forward(jingle.mix); + + // Step through the averages of the sound levels + for(int i = 0; i < 10; i++) + { + // Find the delta between previous values and current + int newVal = (int)(fft.getAvg(i) * (10*i + 1)); + int tmp = newVal - prevValues[i]; // Need to delay by one iteration to help sync sound and visuals + int curVal = values[i]; + prevValues[i] = newVal; + if( tmp < -tolerance ) newVal = values[i] - 1; + else if (tmp > tolerance) newVal = values[i] + 1; + else newVal = values[i]; + if(newVal < 0 ) newVal = 0; + if(newVal > 3) newVal = 3; + values[i] = newVal; + ca.changeRule(i, curVal); + } + + // Restart when at the end + if (ca.finished()) { + background(0); + ca.randomize(); + ca.restart(); + } +} + +// If return is pressed restart early +void keyPressed() { + if(key == '\n') + { + background(0); + ca.randomize(); + ca.restart(); + } +} + +class CA { + int[] cells; // An array of 0s and 1s + int generation; // How many generations? + int scl; // How many pixels wide/high is each cell? + + int[] rules; // An array to store the ruleset, for example {0,1,1,0,1,1,0,1} + + CA(int[] r) { + rules = r; + scl = 1; + cells = new int[width/scl]; + restart(); + } + + CA() { + scl = 1; + cells = new int[width/scl]; + randomize(); + restart(); + } + + // Set the rules of the CA + void setRules(int[] r) { + rules = r; + } + + // Make a random ruleset + void randomize() { + for (int i = 0; i < rules.length; i++) { + rules[i] = int(random(4)); + } + } + + // Reset to generation 0 + void restart() { + for (int i = 0; i < cells.length; i++) { + cells[i] = 0; + } + cells[cells.length/2] = 1; // We arbitrarily start with just the middle cell having a state of "1" + generation = 0; + } + + // The process of creating the new generation + void generate() { + // First we create an empty array for the new values + int[] nextgen = new int[cells.length]; + // For every spot, determine new state by examing current state, and neighbor states + // Ignore edges that only have one neighor + for (int i = 1; i < cells.length-1; i++) { + int left = cells[i-1]; // Left neighbor state + int me = cells[i]; // Current state + int right = cells[i+1]; // Right neighbor staten + nextgen[i] = rules(left,me,right); // Compute next generation state based on ruleset + } + // Copy the array into current value + cells = (int[]) nextgen.clone(); + generation++; + } + + void changeRule(int i, int value) + { + rules[i] = value; + } + + // This is the easy part, just draw the cells, fill 255 for '1', fill 0 for '0' + void render() { + for (int i = 0; i < cells.length; i++) { + if (cells[i] == 1) fill(0,0,255); + else if (cells[i] == 2) fill(0,255, 0); + else if (cells[i] == 3) fill(255, 0, 0); + else fill(0); + noStroke(); + + // Radiate from the center + rect(i*scl,height/2 + (generation*scl), scl,scl); + rect(i*scl,height/2 - (generation*scl), scl,scl); + rect(height/2 + (generation*scl),i*scl, scl,scl); + rect(height/2 - (generation*scl),i*scl, scl,scl); + } + } + + // Implementing the Wolfram rules + // Could be improved and made more concise, but here we can explicitly see what is going on for each case + int rules (int a, int b, int c) { + // 0 == Off + // 1 == Blue + // 2 == Green + int retIndex = a+b+c; + if(mousePressed) retIndex = rules[rules.length - retIndex - 1]; + return rules[retIndex]; + } + + // The CA is done if it reaches the bottom of the screen + boolean finished() { + if (generation > height/scl/2) { + return true; + } else { + return false; + } + } +} + |
