String axiom = "F-F-F-F"; String rules[][] = { {"F", "FF[-F-F-F]F"} }; String current; float len; float songLength = 150f; // seconds int startOctave = 7; void setup() { size(400, 400); smooth(); noLoop(); current = axiom; len = width - 1; println("f 1 0 512 10 1"); } void draw() { //println("\n" + current); background(0); stroke(255); for (int i = 0; i < current.length(); i++) { switch (current.charAt(i)) { case 'F': line(0, 0, len, 0); translate(len, 0); break; case '-': rotate(PI/2); break; case '[': pushMatrix(); break; case ']': popMatrix(); break; } } if (!online) { writeScore(current); } } void mousePressed() { String next = ""; boolean matched = false; for (int i = 0; i < current.length(); i++) { for (int j = 0; j < rules.length; j++) { if (current.charAt(i) == rules[j][0].charAt(0)) { next += rules[j][1]; matched = true; } } if (!matched) { next += current.charAt(i); } matched = false; } current = next; len *= 0.3333; redraw(); } void writeScore(String in) { int fcount = 0; for (int i = 0; i < in.length(); i++) { if (in.charAt(i) == 'F') { fcount++; } } float noteLength = songLength / fcount; float currentTime = 0; ArrayList stack = new ArrayList(); PitchClass currentNote = new PitchClass(); for (int i = 0; i < in.length(); i++) { switch (in.charAt(i)) { case 'F': println("i 1 " + currentTime + " " + noteLength + " " + currentNote.toString()); currentTime += noteLength; break; case '-': currentNote.moveUp(); break; case '[': stack.add(new PitchClass(currentNote)); break; case ']': currentNote = (PitchClass)stack.remove(stack.size()-1); break; } } } class PitchClass { int niceScale[] = { 0, 4, 5, 7, 9, 11 }; int octave = 7; int noteIndex = 0; PitchClass() { } PitchClass(PitchClass c) { octave = c.octave; noteIndex = c.noteIndex; } void moveUp() { noteIndex++; if (noteIndex > niceScale.length - 1) { octave++; noteIndex = 0; } } String toString() { return String.valueOf(octave + (niceScale[noteIndex]/100f)); } }