Creating Music Player With Processing Part III (FINAL)
11:35 PM
It's the last section of tutorial creating music player with processing. We will adding metadata function, you can adding author name, song title, duration and other. In addition we will adding repeat button function. I forget to add this on last tutorial, so i will adding there. And we will adding FFT for creating visualization of the music.
I didn't create function for next, prev, and shuffle button. Because i don't adding playlist on my music player. If you want to add playlist, you can search the function what will you need on javadoc of minim. If you already adding playlist, you can share the code there. If i've the source code of playlist i will share there too. Let start write the code step by step
Initialization the fft, fftLog, and AudioMetaData before void setup
FFT fft; FFT fftLog; AudioMetaData meta;
Declarate fft, fftLog with value of bufferSize and sampleRate of the music on player
fft = new FFT(player.bufferSize(), player.sampleRate()); fftLog = new FFT(player.bufferSize(), player.sampleRate());
Adding fft.linAverages and fft.logAverages to get the average of spectrum
fft.linAverages(128); fftLog.logAverages(22, 1);
Set the coordinate calculation from the corner
rectMode(CORNERS);
Load the font we've made on tutorial before
font = (loadFont("Ubuntu-20.vlw")); textMode(SCREEN);
Get metadata of music with this code on void draw
meta=player.getMetaData();
I've tried to adding the script above on void setup, but the metadata not change when we change the music using jfchooser
Write the script below to get the spectrum bar like i want :D. You can try to change the parameter to know the function
fftLog.forward(player.mix); int w = int(fft.specSize()/50); int xoffset = (width - (width/3))/2; for(int i = 0; i < fftLog.avgSize(); i++) { fill(111,110,255,0); rect(xoffset+i*w+4, 85, xoffset+i*w + w+2, 85 - fftLog.getAvg(i)); }
Adding text metadata to show the metadata on screen with this script
textFont(font, 20); text(meta.title(), (bg.width-textWidth(meta.title()))/2, 20); textSize(20); text(meta.author(), (bg.width-textWidth(meta.title()))/2, 40);
You can adding duration of song with this script
int timeLeft = player.position()-player.length(); String timeLeftStr = String.format("%02d:%02d", timeLeft/1000/60, -timeLeft/1000%60); text( timeLeftStr, (bg.width-textWidth(timeLeftStr))/2, 80);
And now, we will adding repeat function. Initialization the repeatOn because it will be replaced the repeat image when repeat function active. You need to initialization the isRepeat variable too. Add this function before void setup
PImage repeatOn; boolean isRepeat;
Declarate repeatOn with load repeat_on image
repeatOn = loadImage("repeat_on.png");
Write this code for set the value of isRepeat variable when mouseClicked
if(mouseX > 210 && mouseX < 210+repeat.width && mouseY > 104 && mouseY < repeat.height + 104){ println("tombol repeat ditekan"); isRepeat = !isRepeat; }
Don't forget to adding this code for replacing repeat image with repeat_on and otherwise
if(isRepeat){ image(repeatOn, 210, 104); }else{ image(repeat, 210, 104); }
And add the function when isRepeat is true, player will be repeat the song after the song end
if(isRepeat){ if(player.position() >= player.length()){ player.rewind(); player.play(); } }
There is my final code of my music player. Im so sorry for my bad english.
import ddf.minim.*; import ddf.minim.signals.*; import ddf.minim.analysis.*; import ddf.minim.effects.*; import javax.swing.*; JFileChooser jfc; PImage bg; PImage seeker; PImage seeker2; PImage closeButton; PImage minimizeButton; PImage prev; PImage play; PImage stop; PImage next; PImage openfile; PImage shuffle; PImage repeat; PImage repeatOn; PImage pause; PFont font; Minim minim; AudioPlayer player; FFT fft; FFT fftLog; double duration; AudioMetaData meta; boolean isPlaying; boolean isRepeat; void setup(){ size(375, 120, P2D); minim = new Minim(this); player = minim.loadFile("forgetjakarta.mp3"); player.play(); duration = player.length(); isPlaying = true; isRepeat = false; fft = new FFT(player.bufferSize(), player.sampleRate()); fft.linAverages(128); fftLog = new FFT(player.bufferSize(), player.sampleRate()); fftLog.logAverages(2, 1); rectMode(CORNERS); font = (loadFont("Ubuntu-20.vlw")); textMode(SCREEN); bg = loadImage("main.png"); seeker = loadImage("seeker.png"); seeker2 = loadImage("seeker2.png"); closeButton = loadImage("closeButton.png"); minimizeButton = loadImage("minimizeButton.png"); prev = loadImage("prev.png"); play = loadImage("play.png"); stop = loadImage("stop.png"); next = loadImage("next.png"); openfile = loadImage("openfile.png"); shuffle = loadImage("shuffle.png"); repeat = loadImage("repeat.png"); pause = loadImage("pause.png"); repeatOn = loadImage("repeat_on.png"); jfc = new JFileChooser(); } void mouseClicked(){ if(mouseX > 15 && mouseX < 15+prev.width && mouseY > 104 && mouseY < 104+prev.width){ println("tombol previous telah ditekan"); } if(mouseX > 35 && mouseX < 35+play.width && mouseY > 104 && mouseY < 104+play.height){ if(isPlaying){ isPlaying = false; player.pause(); }else{ isPlaying = true; player.play(); } } if(mouseX > 55 && mouseX < 55+stop.width && mouseY > 104 && mouseY < 104+stop.width){ if(isPlaying){ isPlaying = false; player.pause(); player.rewind(); } } if(mouseX > 75 && mouseX < 75+next.width && mouseY > 104 && mouseY < 104+next.height){ println("tombol next telah ditekan"); } //repeat if(mouseX > 210 && mouseX < 210+repeat.width && mouseY > 104 && mouseY < repeat.height + 104){ println("tombol repeat ditekan"); isRepeat = !isRepeat; } if(mouseX > 120 && mouseX < 120+openfile.width && mouseY > 104 && mouseY < 104+openfile.width){ println("tombol open file telah ditekan"); int result = jfc.showOpenDialog(this); if( result == jfc.APPROVE_OPTION){ String filename = jfc.getSelectedFile().getAbsolutePath(); println(filename); player.close(); player = minim.loadFile(filename); player.play(); } } } void draw(){ meta=player.getMetaData(); image(bg,0,0); // draw the logarithmic averages fftLog.forward(player.mix); int w = int(fft.specSize()/50); int xoffset = (width - (width/3))/2; for(int i = 0; i < fftLog.avgSize(); i++) { fill(111,110,255,0); rect(xoffset+i*w+4, 85, xoffset+i*w + w+2, 85 - fftLog.getAvg(i)); } fill(255); //seeker bar image(seeker, (int)(player.position()/duration*(bg.width-seeker.width)), 84); image(seeker2, 300,105); //close & minimize image(closeButton, 350, 5); image(minimizeButton, 335,5); //player image(prev, 15, 105); image(play, 35, 105); image(stop, 55, 105); image(next, 75, 105); image(openfile, 120, 105); image(shuffle, 160, 105); image(repeat, 210, 105); //text textFont(font, 20); text(meta.title(), (bg.width-textWidth(meta.title()))/2, 20); textSize(20); text(meta.author(), (bg.width-textWidth(meta.title()))/2, 40); int timeLeft = player.position()-player.length(); String timeLeftStr = String.format("%02d:%02d", timeLeft/1000/60, -timeLeft/1000%60); text( timeLeftStr, (bg.width-textWidth(timeLeftStr))/2, 80); if(isPlaying){ image(pause, 35, 104); }else{ image(play, 35, 104); } if(isRepeat){ image(repeatOn, 210, 104); }else{ image(repeat, 210, 104); } if(isRepeat){ if(player.position() >= player.length()){ player.rewind(); player.play(); } } }
I will upload my file nextweek maybe. Because i have slow internet connection. I hope you can enjoy my tutorial.
10 comments
Hey man. I've done all buttons, like shuffle, add to playlists and others. Look, enjoy =) And we're waitin' for new parts =)
ReplyDeletehttps://www.dropbox.com/s/gx6tfvl4y5szhum/Player.rar
ReplyDeleteWOW! I've downloaded your music player and anything can work. Congratulations dude!
ReplyDeleteIam using Ubuntu, and i getting error when play it because your file is missing or inaccessible. When i saw your source everything is fine, and i try to compare with my music player i found one different with your file. The name of your folder is Data and mine is data. I think on Ubuntu the name is case sensitive, when i change the folder name everything is workThank for share your file ;). Maybe you can share it on openprocessing.org :D
Do it better and share =)
ReplyDeleteTo your comment, processing's code is always sensetive. And Data folder must be like "Data" =)
ReplyDeleteno, in ubuntu the Data folder must be "data" :)
ReplyDeleteAwesome, can I use this for a university project? I won't publish it, I'll just make quite a few additions, change the layout and change the design :)
ReplyDeleteFeel free for use it and publish, dont forget the credits :lol
DeleteHi!great work!But i have one question.I cant find the first part.I mean i get to the page where the first part is but it is empty..Am i doing something wrong? :)
ReplyDeleteUps. iam so sorry. I don't know why the page is empty. i never delete it before. it's the second post that emtpy >.<
ReplyDelete