package me.Blackburn.JMP; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Map; import java.util.Random; import javax.sound.sampled.AudioFileFormat; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.swing.BorderFactory; import org.tritonus.share.sampled.file.TAudioFileFormat; import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; public class MP3SPI { static SourceDataLine line; static AudioInputStream din; private static JMediaPlayer jmp; private static boolean stop = false; private static boolean pause = false; private static float equalizer[] = new float[31]; static byte[] data; static Thread mp3, fft; public MP3SPI(JMediaPlayer instance) { MP3SPI.jmp = instance; } public static void testPlay(String filename) { try { File file = new File(filename); final AudioInputStream in= AudioSystem.getAudioInputStream(file); din = null; AudioFormat baseFormat = in.getFormat(); AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(file); final AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16, baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false); if (baseFileFormat instanceof TAudioFileFormat) { @SuppressWarnings("rawtypes") Map properties = ((TAudioFileFormat)baseFileFormat).properties(); // String key = "author"; // String val = (String) properties.get(key); // key = "duration"; String title = (String) properties.get("title"); String author = (String) properties.get("author"); String album = (String) properties.get("album"); javax.swing.JPanel infos = new javax.swing.JPanel(new java.awt.GridLayout(3,1)); infos.add(new javax.swing.JPanel(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER)).add(new javax.swing.JLabel(title))); infos.add(new javax.swing.JPanel(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER)).add(new javax.swing.JLabel(author))); infos.add(new javax.swing.JPanel(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER)).add(new javax.swing.JLabel(album))); UI.showSlideout(infos,1, 200, false); long length = (Long)properties.get("duration"); UI.seek.setMaximum((int)length); } din = AudioSystem.getAudioInputStream(decodedFormat, in); UI.seek.setValue(0); System.out.println("Playing: "+file.getAbsolutePath()); UI.play.setText("Pause"); // Play now. mp3 = new Thread(new Runnable(){ public void run() { try { stop = false; rawplay(decodedFormat); in.close(); if(!stop) { Thread.sleep(300); nextTrackWithNoStop(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (LineUnavailableException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}); mp3.start(); } catch (Exception e) { //Handle exception. } } public static void nextTrack() { if(UI.files.getSelectedIndex() != -1 && (UI.files.getSelectedIndex() + 1) < UI.lm.getSize()) { jmp.spi.stopPlayer(); while(mp3 !=null && mp3.isAlive()){try{Thread.sleep(10);} catch (InterruptedException e){}}; MP3SPI.testPlay(UI.music.get(UI.files.getSelectedIndex()+1).getFilepath()); //MP3SPI.testPlay(UI.dir + File.separator + UI.lm.elementAt(UI.files.getSelectedIndex()+1)); if(!UI.random.isSelected()) { UI.files.setSelectedIndex(UI.files.getSelectedIndex() + 1); } else { Random random = new Random(); int ran = random.nextInt(UI.lm.getSize()); UI.files.setSelectedIndex(ran-1); } } } public static void nextTrackWithNoStop() { if(UI.files.getSelectedIndex() != -1 && (UI.files.getSelectedIndex() + 1) < UI.lm.getSize()) { MP3SPI.testPlay(UI.music.get(UI.files.getSelectedIndex()+1).getFilepath()); //MP3SPI.testPlay(UI.dir + File.separator + UI.lm.elementAt(UI.files.getSelectedIndex()+1)); if(!UI.random.isSelected()) { UI.files.setSelectedIndex(UI.files.getSelectedIndex() + 1); } else { Random random = new Random(); int ran = random.nextInt(UI.lm.getSize()); UI.files.setSelectedIndex(ran); } } } public boolean isStopped() { return stop; } public boolean isPaused() { return pause; } public void pauseTrack(boolean val) { MP3SPI.pause = val; } private static void rawplay(AudioFormat targetFormat) throws IOException, LineUnavailableException { data = new byte[8192]; line = getLine(targetFormat); if (line != null) { if( din instanceof javazoom.spi.PropertiesContainer ) { Map properties = ((javazoom.spi.PropertiesContainer)din).properties(); float[] eq = (float[])properties.get("mp3.equalizer"); eq = equalizer; } // Start line.start(); int nBytesRead = 0, nBytesWritten = 0; int cnt = 0; while (nBytesRead != -1 && !stop) { while(pause){try { Thread.sleep(50); } catch (InterruptedException e) { }}; try{ nBytesRead = din.read(data, 0, data.length); UI.seek.setBorder(BorderFactory.createTitledBorder(Long.toString(line.getMicrosecondPosition()/1000000))); cnt++; fft = new Thread(new Runnable(){ public void run() { int winSize = 4096; //FloatFFT_1D test = new FloatFFT_1D(8); DoubleFFT_1D blah = new DoubleFFT_1D(winSize); double[] fl = toDoubles(data); for (int i = 0; i < winSize; i++) { double multiplier = 0.5 * (1 - Math.cos(2*Math.PI*i/(winSize-1))); fl[i] = multiplier * fl[i]; } blah.realForward(fl); for(int i = 0; i<UI.eq.length; i++) { double real = fl[(2*i)]; double img = fl[(2*i+1)]; //double img = fl[(2*i+1)*2]; //int value = (int) (20*Math.log10(Math.sqrt((((real*real)+(img*img)))))); int value = (int) Math.sqrt((real*real)+(img*img)); //if(value > UI.eq[i/2].getValue()) { UI.eq[i].setValue((int)(20*Math.log10(value)));//10*Math.log10 } //else if(UI.eq[i/2].getValue() > 1) { //UI.eq[i/2].setValue(UI.eq[i/2].getValue() - 1); //UI.eq[i-1].setValue(UI.eq[i-1].getMinimum()); } } } }); //System.out.println(targetFormat.getSampleSizeInBits()); //System.out.println(targetFormat.getFrameRate()); if(cnt == targetFormat.getSampleSizeInBits()/3) { if(!fft.isAlive()) fft.start(); cnt = 0; } /*float[] fArr = floatMe(shortMe(data)); FloatFFT_1D test = new FloatFFT_1D(7); test.complexForward(fArr); //System.out.println(fArr.length); for(int i = 0; i<32;i++) { int val = Math.abs((int)fArr[i]); if(val <= 31) { UI.eq[0].setValue(val); //System.out.println("Bass low "+val); } else if(val > 31 && val <= 62) { UI.eq[1].setValue(val); } else if(val > 62 && val <= 125) { UI.eq[2].setValue(val); } else if(val > 125 && val <= 250) { UI.eq[3].setValue(val); } else if(val > 250 && val <= 500) { UI.eq[4].setValue(val); } else if(val > 500 && val <= 1000) { UI.eq[5].setValue(val); } else if(val >= 1000 && val <=2000) { UI.eq[6].setValue(val); } }*/ } catch (NullPointerException n){return;} // if (nBytesRead != -1) nBytesWritten = line.write(data, 0, nBytesRead); if(nBytesRead != -1) { nBytesWritten = line.write(data, 0, nBytesRead); UI.seek.setValue((int)line.getMicrosecondPosition()); /*int rms = calculateRMSLevel(data); if(rms < 53 && rms > 50) { UI.eq[0].setValue(rms); UI.eq[1].setValue(UI.eq[1].getValue()-1); UI.eq[2].setValue(UI.eq[2].getValue()-1); UI.eq[3].setValue(UI.eq[3].getValue()-1); UI.eq[4].setValue(UI.eq[4].getValue()-1); UI.eq[5].setValue(UI.eq[5].getValue()-1); UI.eq[6].setValue(UI.eq[6].getValue()-1); } else if(rms >= 53 && rms < 57) { UI.eq[1].setValue(rms); UI.eq[5].setValue(UI.eq[5].getValue()-1); UI.eq[0].setValue(UI.eq[0].getValue()-1); UI.eq[2].setValue(UI.eq[2].getValue()-1); UI.eq[3].setValue(UI.eq[3].getValue()-1); UI.eq[4].setValue(UI.eq[4].getValue()-1); UI.eq[6].setValue(UI.eq[6].getValue()-1); } else if(rms >= 57 && rms < 61) { UI.eq[2].setValue(rms); UI.eq[5].setValue(UI.eq[5].getValue()-1); UI.eq[4].setValue(UI.eq[4].getValue()-1); UI.eq[3].setValue(UI.eq[3].getValue()-1); UI.eq[1].setValue(UI.eq[1].getValue()-1); UI.eq[0].setValue(UI.eq[0].getValue()-1); UI.eq[6].setValue(UI.eq[6].getValue()-1); } else if(rms >= 61 && rms < 65) { UI.eq[3].setValue(rms); UI.eq[5].setValue(UI.eq[5].getValue()-1); UI.eq[4].setValue(UI.eq[4].getValue()-1); UI.eq[2].setValue(UI.eq[2].getValue()-1); UI.eq[1].setValue(UI.eq[1].getValue()-1); UI.eq[0].setValue(UI.eq[0].getValue()-1); UI.eq[6].setValue(UI.eq[6].getValue()-1); } else if(rms >= 65 && rms < 69) { UI.eq[4].setValue(rms); UI.eq[5].setValue(UI.eq[5].getValue()-1); UI.eq[3].setValue(UI.eq[3].getValue()-1); UI.eq[2].setValue(UI.eq[2].getValue()-1); UI.eq[1].setValue(UI.eq[1].getValue()-1); UI.eq[0].setValue(UI.eq[0].getValue()-1); UI.eq[6].setValue(UI.eq[6].getValue()-1); } else if(rms >= 69 && rms < 73) { UI.eq[5].setValue(rms); UI.eq[4].setValue(UI.eq[4].getValue()-1); UI.eq[3].setValue(UI.eq[3].getValue()-1); UI.eq[2].setValue(UI.eq[2].getValue()-1); UI.eq[1].setValue(UI.eq[1].getValue()-1); UI.eq[0].setValue(UI.eq[0].getValue()-1); UI.eq[6].setValue(UI.eq[6].getValue()-1); } else if(rms >= 73) { UI.eq[6].setValue(rms); UI.eq[4].setValue(UI.eq[4].getValue()-1); UI.eq[3].setValue(UI.eq[3].getValue()-1); UI.eq[2].setValue(UI.eq[2].getValue()-1); UI.eq[1].setValue(UI.eq[1].getValue()-1); UI.eq[0].setValue(UI.eq[0].getValue()-1); UI.eq[5].setValue(UI.eq[5].getValue()-1); }*/ } } // Stop UI.play.setText("Play"); line.drain(); line.stop(); line.close(); din.close(); } } public static int calculateRMSLevel(byte[] audioData) { // audioData might be buffered data read from a data line long lSum = 0; for (int i = 0; i < audioData.length; i++) { lSum = lSum + audioData[i]; } double dAvg = lSum / audioData.length; double sumMeanSquare = 0d; for (int j = 0; j < audioData.length; j++) { sumMeanSquare = sumMeanSquare + Math.pow(audioData[j] - dAvg, 2d); } double averageMeanSquare = sumMeanSquare / audioData.length; return (int) (Math.pow(averageMeanSquare, 0.5d) + 0.5); } public void stopPlayer() { stop = true; UI.play.setText("Play"); } private static SourceDataLine getLine(AudioFormat audioFormat) throws LineUnavailableException { SourceDataLine res = null; DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); res = (SourceDataLine) AudioSystem.getLine(info); res.open(audioFormat); return res; } public static float[] getEqualizer() { return equalizer; } public static void setEqualizer(float equalizer[]) { MP3SPI.equalizer = equalizer; } public static short[] shortMe(byte[] bytes) { short[] out = new short[bytes.length / 2]; // will drop last byte if odd number ByteBuffer bb = ByteBuffer.wrap(bytes); for (int i = 0; i < out.length; i++) { out[i] = bb.getShort(); } return out; } public static float[] floatMe(short[] pcms) { float[] floaters = new float[pcms.length]; for (int i = 0; i < pcms.length; i++) { floaters[i] = pcms[i]; } return floaters; } public static double[] toDoubles(byte[] bytes) { double[] fl = new double[bytes.length]; for(int i = 0; i<fl.length;i++) { fl[i] = (double)bytes[i]; } return fl; } }