Maxim maxim; AudioFilePlayer[] drum=new AudioFilePlayer[6]; Synth[] waveform=new Synth[8]; //array of synths for polyphony int[] voiceAge=new int[8]; float[] wavetable = new float[514]; int oct=64; PFont f; String[] message; Word[] words; int wc=0;//word counter int shelfL; //length of shelf int shelfX, shelfY; //shelf starting position int phraseS, phraseP, phraseV, currP; float hotSpot;//the x position to trigger drum sounds int textsize=20; int playhead=0; int currV=0; int age; float vpx, vpy; float fallSpeed=0.6; float spinSpeed=PI/40; int shrink=3; int messnum=0; int maxtsize=300; int bgnow=bginit=0; int hsnow=0; /////////////// Setup void setup() { size(600, 400); vpx=width/2; vpy=height/2; //setup words f = createFont("Arial",300,true); textFont(f); shelfL=width-50-200; phraseS=0; shelfX=200; shelfY=100; phraseP=phraseV=500; hotSpot=width*2/3; // setup alternative texts to drive the synth message=new String[5]; message[0]="The Truth is a Lemon Meringue; but the Truth is not a Banana Cream Pie."; //message[0]="The Truth3 Lemon1 Meringue and 1I Love@ it said @Mr Gum 4444 in$ This Pigeon Pie of my££ Life"; message[1]="B1@a 2a_2 Ebub 3^2r B1@aie 2hha_2 Ebbb 3ei^2r Ba 2a_2 Ebbrrib 3^2abcr B1ui@a 2a_2 Ebbb 3^2r"; message[2]="It is a Truth Universally acknowledged, That a single Man in possession of a Good Fortune, must be in Want of a Wife. "; message[3]="The Quick Brown fox, jumps Over the Lazy Dog. "; message[4]="Jammy Grammy Lammy F'Huppa F'Huppa Berlin Stereo Eo Eo Lebb C'Yepp Nermonica Le Straypek De Grespin De Crespin De Spespin De Vespin De Whoop De Loop De Brunkle Merry Christmas Lenoir "; words=new Word[25]; //create array of words initWords(0); //setup sounds maxim = new Maxim(this); drum[0] = maxim.loadFile("1bd1.wav", 2048); drum[0].setLooping(false); drum[0].volume(0.9); drum[1] = maxim.loadFile("1snare.wav", 2048); drum[1].setLooping(false); drum[1].volume(0.35); drum[2] = maxim.loadFile("1hh1.wav", 2048); drum[2].setLooping(false); drum[2].volume(0.6); drum[3] = maxim.loadFile("1crashb.wav", 2048); drum[3].setLooping(false); drum[3].volume(0.75); drum[4] = maxim.loadFile("1clap.wav", 2048); drum[4].setLooping(false); drum[4].volume(0.5); drum[5] = maxim.loadFile("1pop.wav", 2048); drum[5].setLooping(false); drum[5].volume(0.9); frameRate(24); for (int i = 0; i < 514 + 1 ; i++) { wavetable[i]=((float)i/512)-0.5; // wavetable[i]=sin(radians((float)i/512*360))/2; } for(int i=0;i<8;i++){ waveform[i] = new Synth(); waveform[i].waveTableSize(514); waveform[i].loadWaveTable(wavetable); // waveform[i].setFrequency(mtof[i*2+36]); } for(int i=0;i<8;i++){ waveform[i].play(); waveform[i].ramp(0.,1); } } ////////// end of Setup void initWords(int source){ int x=0; //temp x value String tempWord=""; //temp string holder wc=0; textSize(textsize); int vowels=0; int wordlen=0; char[] letters=message[source].toCharArray(); //create char copy of string in order to compare char type for (int i=0;ibginit){ bgnow=(int)(bgnow/16*15); //fade background to balck } if (hsnow>0){ hsnow=(int)(hsnow/4*3); //fade hot spot bar } } void mousePressed(){ //mouse press changes the string driving the synth messnum++; initWords(messnum%message.length); } void attack(int v, int o, int n) // trigger the synth voice { // println("attack "+v+o+n); waveform[v].setFrequency(mtof[o*12+n+36]); waveform[v].ramp(0.2,1); waveform[v].setFilter(mtof[o*12+n+36]*8,10); waveform[v].filterRamp(mtof[o*12+n+36],2000); } void release(int v) //set release for the synth voice { waveform[v].ramp(0.,3000); } /////////////////////////////////////////////////// // A class to hold a single word and its properties /////////////////////////////////////////////////// class Word { String word; // The object knows its original "home" location float homex,homey; // As well as its current location and width float x,y,a,wwidth; int l=99; int wlen; int numvow; int wordAge=0; int myV; float hyp, adj, opp, theta; float sx,sy; //int tsize=100; int tsize=20; int r,g,b; Word (float x_, float y_, String word_, float width_, int wlen_, int numvow_) { homex = x = x_; homey = y = y_; word = word_; wwidth=width_; a=0; numvow=numvow_; wlen=wlen_; } // Display the word void display() { pushMatrix(); fill(100); stroke(128); strokeWeight(2); textAlign(LEFT); translate(x+phraseP,y); // rotate(radians(a)); text(word,0,0); popMatrix(); } void hotWord(){ //Hot word is the word currently over the hotspot. Similarly hot letter if(x+phrasePhotSpot){ pushMatrix(); fill(255,0,0); stroke(128); textAlign(LEFT); translate(x+phraseP,y); // rotate(radians(a)); text(word,0,0); popMatrix(); float p=0; float s=0; char c; int beat=0; for(int i=0;ihotSpot)){ if(l!=i){ //tests if we have already triggered this as hot letter l=i; //indicates this has already been flagged as hot letter pushMatrix(); fill(0); textAlign(LEFT); textSize(80); translate(ls-10,y-5); text(c,0,0); popMatrix(); textSize(textsize); hsnow=100; // use the letter type to pick a drum sound char[] letter=c.toCharArray(); //create char copy of string in order to compare char type char ch=letter[0]; int d; if ((ch>=33)&&(ch<=47)){d=3;}//non-alphanumeric if ((ch>=48)&&(ch<=57)){d=4;}//digits if ((ch>=58)&&(ch<=64)){d=3;}//non-alphanumeric if ((ch>=65)&&(ch<=90)){d=0;}//Upper case alpha if ((ch>=91)&&(ch<=96)){d=3;}//non-alphanumeric if ((ch>=97)&&(ch<=109)){d=2;}//lower case alpha - lower half if ((ch>=110)&&(ch<=122)){d=5;}//lower case alpha - upper half if ((ch>=123)&&(ch<=126)){d=3;}//non-alphanumeric if (ch==32){;}//space if ((ch==65)||(ch==97)||(ch==69)||(ch==101)||(ch==73)||(ch==105)||(ch==79)||(ch==111)||(ch==85)||(ch==117)){ d=1;}//vowels (upper or lower) drum[d].stop(); drum[d].cue(0); drum[d].play(); break; } } p+=s; } } } boolean isFall(){ //Test if the word is ready to fall off the shelf int note,octave; if((phraseP+wwidth+x255){r=255;} g=(int)random(col-80, col+80); if(g<0){r=0;} if(g>255){r=255;} b=(int)random(col-80, col+80); if(b<0){r=0;} if(b>255){r=255;} //trigger fall sound octave=1;note=1; if(wlen<=3){octave=0;}// word size sets Octave else if (wlen<=6){octave=1;} else {octave=2;} if(wlen-numvow<=1){note=1;}// number of non-vowels sets principle note if(wlen-numvow==2){note=3;} if(wlen-numvow==3){note=5;} if(wlen-numvow==4){note=6;} if(wlen-numvow==5){note=8;} if(wlen-numvow==6){note=10;} if(wlen-numvow>6){note=12;} if(numvow==0){note+=1;}// number of vowels shifts note up or down if(numvow==1){note+=2;} if(numvow==2){note-=1;} if(numvow>=3){note-=2;} if(note<1){note=1;} if(note>12){note=12;} attack(currV,octave,note); wordAge=0; myV=currV; currV++;if (currV>7){currV=0;} return false; }else { return false; } } // Display the falling word void fallDisplay() { pushMatrix(); fill(r,g,b,180); textAlign(LEFT); translate(sx,sy); rotate(a); noStroke(); // render falling text slows down the whole app so temp use of rectangle rect(0,0,tsize,tsize); /* These three lines display falling text but they render too slow in browser textSize(tsize); text(word,0,0); textSize(textsize); */ popMatrix(); } void fall(){ //simulate falling y+=5; if(y>3*height){x=homex;y=homey;} // spiral falling theta+=spinSpeed; hyp-=fallSpeed; float fy=cos(theta)*hyp; float fx=sin(theta)*hyp; if(hyp<5){hyp=5;}//x=homex;y=homey;} fill(100); // rect(vpx-fx,vpy-fy,10,10); sx=vpx-fx;sy=vpy-fy; a+=PI/150; tsize-=shrink; wordAge++; if (wordAge>=8){release(myV);} } void move() { x=x-2; } } int HORIZONTAL = 0; int VERTICAL = 1; int UPWARDS = 2; int DOWNWARDS = 3; class Widget { PVector pos; PVector extents; String name; color inactiveColor = color(60, 60, 100); color activeColor = color(100, 100, 160); color bgColor = inactiveColor; color lineColor = color(255); void setInactiveColor(color c) { inactiveColor = c; bgColor = inactiveColor; } color getInactiveColor() { return inactiveColor; } void setActiveColor(color c) { activeColor = c; } color getActiveColor() { return activeColor; } void setLineColor(color c) { lineColor = c; } color getLineColor() { return lineColor; } String getName() { return name; } void setName(String nm) { name = nm; } Widget(String t, int x, int y, int w, int h) { pos = new PVector(x, y); extents = new PVector (w, h); name = t; //registerMethod("mouseEvent", this); } void display() { } boolean isClicked() { if (mouseX > pos.x && mouseX < pos.x+extents.x && mouseY > pos.y && mouseY < pos.y+extents.y) { return true; } else { return false; } } public void mouseEvent(MouseEvent event) { //if (event.getFlavor() == MouseEvent.PRESS) //{ // mousePressed(); //} } boolean mousePressed() { return isClicked(); } boolean mouseDragged() { return isClicked(); } boolean mouseReleased() { return isClicked(); } } class Button extends Widget { PImage activeImage = null; PImage inactiveImage = null; PImage currentImage = null; color imageTint = color(255); Button(String nm, int x, int y, int w, int h) { super(nm, x, y, w, h); } void setImage(PImage img) { setInactiveImage(img); setActiveImage(img); } void setInactiveImage(PImage img) { if(currentImage == inactiveImage || currentImage == null) { inactiveImage = img; currentImage = inactiveImage; } else { inactiveImage = img; } } void setActiveImage(PImage img) { if(currentImage == activeImage || currentImage == null) { activeImage = img; currentImage = activeImage; } else { activeImage = img; } } void setImageTint(float r, float g, float b) { imageTint = color(r,g,b); } void display() { if(currentImage != null) { //float imgHeight = (extents.x*currentImage.height)/currentImage.width; float imgWidth = (extents.y*currentImage.width)/currentImage.height; pushStyle(); imageMode(CORNER); tint(imageTint); image(currentImage, pos.x, pos.y, imgWidth, extents.y); stroke(bgColor); noFill(); rect(pos.x, pos.y, imgWidth, extents.y); noTint(); popStyle(); } else { pushStyle(); stroke(lineColor); fill(bgColor); rect(pos.x, pos.y, extents.x, extents.y); fill(lineColor); textAlign(CENTER, CENTER); text(name, pos.x + 0.5*extents.x, pos.y + 0.5* extents.y); popStyle(); } } boolean mousePressed() { if (super.mousePressed()) { bgColor = activeColor; if(activeImage != null) currentImage = activeImage; return true; } return false; } boolean mouseReleased() { if (super.mouseReleased()) { bgColor = inactiveColor; if(inactiveImage != null) currentImage = inactiveImage; return true; } return false; } } class Toggle extends Button { boolean on = false; Toggle(String nm, int x, int y, int w, int h) { super(nm, x, y, w, h); } boolean get() { return on; } void set(boolean val) { on = val; if (on) { bgColor = activeColor; if(activeImage != null) currentImage = activeImage; } else { bgColor = inactiveColor; if(inactiveImage != null) currentImage = inactiveImage; } } void toggle() { set(!on); } boolean mousePressed() { return super.isClicked(); } boolean mouseReleased() { if (super.mouseReleased()) { toggle(); return true; } return false; } } class RadioButtons extends Widget { public Toggle [] buttons; RadioButtons (int numButtons, int x, int y, int w, int h, int orientation) { super("", x, y, w*numButtons, h); buttons = new Toggle[numButtons]; for (int i = 0; i < buttons.length; i++) { int bx, by; if(orientation == HORIZONTAL) { bx = x+i*(w+5); by = y; } else { bx = x; by = y+i*(h+5); } buttons[i] = new Toggle("", bx, by, w, h); } } void setNames(String [] names) { for (int i = 0; i < buttons.length; i++) { if(i >= names.length) break; buttons[i].setName(names[i]); } } void setImage(int i, PImage img) { setInactiveImage(i, img); setActiveImage(i, img); } void setAllImages(PImage img) { setAllInactiveImages(img); setAllActiveImages(img); } void setInactiveImage(int i, PImage img) { buttons[i].setInactiveImage(img); } void setAllInactiveImages(PImage img) { for (int i = 0; i < buttons.length; i++) { buttons[i].setInactiveImage(img); } } void setActiveImage(int i, PImage img) { buttons[i].setActiveImage(img); } void setAllActiveImages(PImage img) { for (int i = 0; i < buttons.length; i++) { buttons[i].setActiveImage(img); } } void set(String buttonName) { for (int i = 0; i < buttons.length; i++) { if(buttons[i].getName().equals(buttonName)) { buttons[i].set(true); } else { buttons[i].set(false); } } } int get() { for (int i = 0; i < buttons.length; i++) { if(buttons[i].get()) { return i; } } return -1; } String getString() { for (int i = 0; i < buttons.length; i++) { if(buttons[i].get()) { return buttons[i].getName(); } } return ""; } void display() { for (int i = 0; i < buttons.length; i++) { buttons[i].display(); } } boolean mousePressed() { for (int i = 0; i < buttons.length; i++) { if(buttons[i].mousePressed()) { return true; } } return false; } boolean mouseDragged() { for (int i = 0; i < buttons.length; i++) { if(buttons[i].mouseDragged()) { return true; } } return false; } boolean mouseReleased() { for (int i = 0; i < buttons.length; i++) { if(buttons[i].mouseReleased()) { for(int j = 0; j < buttons.length; j++) { if(i != j) buttons[j].set(false); } //buttons[i].set(true); return true; } } return false; } } class Slider extends Widget { float minimum; float maximum; float val; int textWidth = 60; int orientation = HORIZONTAL; Slider(String nm, float v, float min, float max, int x, int y, int w, int h, int ori) { super(nm, x, y, w, h); val = v; minimum = min; maximum = max; orientation = ori; if(orientation == HORIZONTAL) textWidth = 60; else textWidth = 20; } float get() { return val; } void set(float v) { val = v; val = constrain(val, minimum, maximum); } void display() { float textW = textWidth; if(name == "") textW = 0; pushStyle(); textAlign(LEFT, TOP); fill(lineColor); text(name, pos.x, pos.y); stroke(lineColor); noFill(); if(orientation == HORIZONTAL){ rect(pos.x+textW, pos.y, extents.x-textWidth, extents.y); } else { rect(pos.x, pos.y+textW, extents.x, extents.y-textW); } noStroke(); fill(bgColor); float sliderPos; if(orientation == HORIZONTAL){ sliderPos = map(val, minimum, maximum, 0, extents.x-textW-4); rect(pos.x+textW+2, pos.y+2, sliderPos, extents.y-4); } else if(orientation == VERTICAL || orientation == DOWNWARDS){ sliderPos = map(val, minimum, maximum, 0, extents.y-textW-4); rect(pos.x+2, pos.y+textW+2, extents.x-4, sliderPos); } else if(orientation == UPWARDS){ sliderPos = map(val, minimum, maximum, 0, extents.y-textW-4); rect(pos.x+2, pos.y+textW+2 + (extents.y-textW-4-sliderPos), extents.x-4, sliderPos); }; popStyle(); } boolean mouseDragged() { if (super.mouseDragged()) { float textW = textWidth; if(name == "") textW = 0; if(orientation == HORIZONTAL){ set(map(mouseX, pos.x+textW, pos.x+extents.x-4, minimum, maximum)); } else if(orientation == VERTICAL || orientation == DOWNWARDS){ set(map(mouseY, pos.y+textW, pos.y+extents.y-4, minimum, maximum)); } else if(orientation == UPWARDS){ set(map(mouseY, pos.y+textW, pos.y+extents.y-4, maximum, minimum)); }; return true; } return false; } boolean mouseReleased() { if (super.mouseReleased()) { float textW = textWidth; if(name == "") textW = 0; if(orientation == HORIZONTAL){ set(map(mouseX, pos.x+textW, pos.x+extents.x-10, minimum, maximum)); } else if(orientation == VERTICAL || orientation == DOWNWARDS){ set(map(mouseY, pos.y+textW, pos.y+extents.y-10, minimum, maximum)); } else if(orientation == UPWARDS){ set(map(mouseY, pos.y+textW, pos.y+extents.y-10, maximum, minimum)); }; return true; } return false; } } class MultiSlider extends Widget { Slider [] sliders; /* MultiSlider(String [] nm, float min, float max, int x, int y, int w, int h, int orientation) { super(nm[0], x, y, w, h*nm.length); sliders = new Slider[nm.length]; for (int i = 0; i < sliders.length; i++) { int bx, by; if(orientation == HORIZONTAL) { bx = x; by = y+i*h; } else { bx = x+i*w; by = y; } sliders[i] = new Slider(nm[i], 0, min, max, bx, by, w, h, orientation); } } */ MultiSlider(int numSliders, float min, float max, int x, int y, int w, int h, int orientation) { super("", x, y, w, h*numSliders); sliders = new Slider[numSliders]; for (int i = 0; i < sliders.length; i++) { int bx, by; if(orientation == HORIZONTAL) { bx = x; by = y+i*h; } else { bx = x+i*w; by = y; } sliders[i] = new Slider("", 0, min, max, bx, by, w, h, orientation); } } void setNames(String [] names) { for (int i = 0; i < sliders.length; i++) { if(i >= names.length) break; sliders[i].setName(names[i]); } } void set(int i, float v) { if(i >= 0 && i < sliders.length) { sliders[i].set(v); } } float get(int i) { if(i >= 0 && i < sliders.length) { return sliders[i].get(); } else { return -1; } } void display() { for (int i = 0; i < sliders.length; i++) { sliders[i].display(); } } boolean mouseDragged() { for (int i = 0; i < sliders.length; i++) { if(sliders[i].mouseDragged()) { return true; } } return false; } boolean mouseReleased() { for (int i = 0; i < sliders.length; i++) { if(sliders[i].mouseReleased()) { return true; } } return false; } }