//pixelstick image generator // //pixelstick playing at 20fps, 400 pixel frame makes a 20 second shot //200 pixels height //notes 36-45 velocities 3-122 //notes vary by 9 //multiply notes movement by 9 = 81 //add 60 import java.io.File; import ddf.minim.*; import java.util.NavigableMap; import java.util.TreeMap; import java.util.Iterator; import java.util.Map; Table table; String audioFileName = "The Son is the One.mp3"; int NOTE_LOW = 36, NOTE_HIGH = 45; int[] notes=new int[NOTE_HIGH+1]; int[] oldnotes=new int[NOTE_HIGH+1]; color[] cols={#FF0000,#FF00BF,#8000FF,#013ADF,#00FFFF,#00FF40,#80FF00,#FFFF00,#FF8000}; int NOTE_SCALE=12,NOTE_OFFSET=60; Minim minim; AudioPlayer audioPlayer; int pw,ph; int ln=200, hn=0, lv= 200, hv=0; boolean loaded=false; PImage sc; class Event { int pitch; int velocity; Event(int p,int v){ pitch=p; velocity=v; } } //NavigableMap> events = new NavigableMap(); NavigableMap events= new TreeMap(); Iterator iterator; ArrayList eventlist; int startTime; int noteTime=0; void setup(){ size(400, 200); sc=createImage(width,height,RGB); table= loadTable("TSITO.csv", "header"); println(table.getRowCount() + " total rows in table"); for (TableRow row : table.rows()) { int pitch = row.getInt("pitch"); int velocity = row.getInt("velocity"); String event = row.getString("event"); int time = (int)(row.getInt("time")*0.55309734513274); //tick to ms if (event.equals("Note_on_c")||event.equals("Note_off_c")){ ArrayList templist; if (!events.containsKey(time)){ templist=new ArrayList(); } else templist=(ArrayList)events.get(time); templist.add(new Event(pitch,velocity)); events.put(time,templist); } //println(event + " " + time+","+pitch); } println("stored "+events.size()+" note events"); for (int i=NOTE_LOW;i //is the number of 'ticks' from the previous event //and is represented as a variable length quantity /* The formula is 60000 / (BPM * PPQ) (milliseconds). Where BPM is the tempo of the track (Beats Per Minute). (i.e. a 120 BPM track would have a MIDI time of (60000 / (120 * 192)) or 2.604 ms for 1 tick. */ //tempo = 530973 //bpm = 127.43352 //ms per tick= 60000 / (113 * 192) ms //2.765486725663717 ms per tick /* apparently logic is 960 ppq (hearsay) ms per tick = 60000 / (113 * 960) = 0.55309734513274 strategy: create a data structure of events with time in ms AT EVERY FRAME check for a new event that has just passed turn on/off notes as necessary map data structure? given a time in millis, need to be able to find note with biggest time less than this time */ background(0); rectMode(CORNER); //noStroke(); colorMode(RGB, 255); frameRate(50); } void draw(){ loadPixels(); for (int x=1;x)eventlist){ notes[e.pitch]=e.velocity; //println(e.velocity+" "+noteTime+" "+e.pitch+" (time now "+trackTime+")"); } if(iterator.hasNext()){ noteTime = (Integer)iterator.next(); } } NavigableMap laternotes = events.tailMap(millis(), true); //println(laternotes.size()+" notes after "+millis()); for(int i = NOTE_LOW; i < NOTE_HIGH; i++){ int notecentre=((i-NOTE_LOW)*NOTE_SCALE)+NOTE_OFFSET; if (notes[i]!=oldnotes[i]){ if (notes[i]>0) { //println("startnote "+i); } else { //println("stopnote "+i); } for (int j=notecentre-(NOTE_SCALE*2);j<=notecentre+(NOTE_SCALE*2);j++){ pixels[(j*width)+(width-1)]=cols[i-NOTE_LOW]; } } else if (notes[i]>0){ //println("note "+i); pixels[((notecentre-(NOTE_SCALE*2))*width)+(width-1)]=cols[i-NOTE_LOW]; pixels[((notecentre+(NOTE_SCALE*2))*width)+(width-1)]=cols[i-NOTE_LOW]; } oldnotes[i]=notes[i]; } updatePixels(); //saveFrame("frames/img####.png"); if (!audioPlayer.isPlaying()) { println("notes "+ln+"-"+hn+" velocities "+lv+"-"+hv); exit(); } } //change rate of drop? //veering?? void keyPressed() { println("notes "+ln+"-"+hn+" velocities "+lv+"-"+hv); }