import ddf.minim.*; String songname = "Maps.mp3"; Minim minim; AudioPlayer player; PGraphics songProfile; float msPerPixel; // number of song milliseconds per horizontal pixel int panel; // height for each panel void setup() { size(displayWidth, displayHeight); panel = displayHeight / 3; strokeWeight(2); background(0); minim = new Minim(this); // start with full AudioSample to build profile picture AudioSample song = minim.loadSample(songname, 512); songProfile = createGraphics(width, panel); graphSong(song, songProfile); // now create an AudioPlayer for better control of playback player = minim.loadFile(songname, 1024); } void graphSong(AudioSample song, PGraphics pg) { int mid = pg.height/2; pg.beginDraw(); pg.background(255); float[] left = song.getChannel(AudioSample.LEFT); float[] right = song.getChannel(AudioSample.RIGHT); // determine number of samples per horizontal pixel int cluster = left.length/pg.width; msPerPixel = 1000 * cluster/44100.0; for (int x=0; x < pg.width; x++) { // compute average abs value within cluster float avg = 0.0; for (int s=cluster*x; s < cluster*(x+1); s++) { avg += abs(left[s]); avg += abs(right[s]); } avg /= 2*cluster; float h = panel * avg; pg.line(x, mid-h/2, x, mid+h/2); } pg.endDraw(); } void keyPressed() { if (key == CODED) { if (keyCode == LEFT) { player.skip(-5000); // five seconds earlier } else if (keyCode == RIGHT) { player.skip(5000); // five seconds later } } else if (key == ' ') { if (player.isPlaying()) { player.pause(); } else { player.play(); } } } void mouseClicked() { if (mouseY <= panel) { player.cue(int(msPerPixel * mouseX)); } } void draw() { if (player.isPlaying()) { drawWaveforms(); } // draw overall song profile and progress bar image(songProfile, 0, 0); float x = player.position()/msPerPixel; stroke(255, 0, 0); line(x, 0, x, panel); fill(255,0,0); int sign; if (x > width/2) { textAlign(RIGHT,TOP); sign = -1; } else { textAlign(LEFT,TOP); sign = 1; } int minutes = player.position()/60000; float seconds = (player.position()%60000)/1000.0; String label = minutes + ":" + nf(seconds,2,2); text(label,x+10*sign,20); // panel dividers stroke(255); line(0, panel, width, panel); } void drawWaveforms() { // black background stroke(0); fill(0); rect(0, panel, width, 2*panel); // compute average magnitude of left channel within buffer float avg = 0.0; for (int i=0; i < player.bufferSize(); i++) { avg += abs(player.left.get(i)); } avg /= player.bufferSize(); fill(2*255*avg, 0, 0); rect(0,panel,width,panel); // count zero-crossings of right channel within buffer int crossings = 0; for (int i=0; i < player.bufferSize() - 1; i++) { if (player.right.get(i) < 0.1 && player.right.get(i+1) >= 0.1) { crossings++; } } float crossingsPerSample = crossings / float(player.bufferSize()-1); fill(0, 10 * crossingsPerSample * 255, 0); rect(0,2*panel,width,panel); // draw the left and right channel waveforms stroke(255); noFill(); for (int i=0; i < player.bufferSize() - 1; i++) { float x1 = map(i, 0, player.bufferSize(), 0, width); float x2 = map(i+1, 0, player.bufferSize(), 0, width); line(x1, 3*panel/2 - player.left.get(i)*panel/2, x2, 3*panel/2 - player.left.get(i+1)*panel/2); line(x1, 5*panel/2 - player.right.get(i)*panel/2, x2, 5*panel/2 - player.right.get(i+1)*panel/2); } }