/* * SamplingGraph.java * * Created on April 28, 2007, 11:00 AM * */ package com.copyrightedsongs.lib; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.geom.Line2D; import java.io.File; import java.io.IOException; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.Vector; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader; /** * * @author guigouz */ class SamplingGraph extends JPanel { // This is the original file AudioInputStream mp3 = null; // This is the decoded file AudioInputStream audioInputStream = null; // We'll cache the lines here Vector lines = new Vector(); double duration, seconds; Color jfcBlue = new Color(204, 204, 255); Color pink = new Color(255, 175, 175); public SamplingGraph() { setBackground(new Color(20, 20, 20)); } public void open(File f) throws UnsupportedAudioFileException, IOException { mp3 = AudioSystem.getAudioInputStream(f); AudioFormat inFormat = mp3.getFormat(); AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, inFormat.getSampleRate(), 16, inFormat.getChannels(), inFormat.getChannels() * 2, inFormat.getSampleRate(), false); audioInputStream = AudioSystem.getAudioInputStream(decodedFormat, mp3); } // This was taken from the JavaSound demo (capture/playback) public void createWaveForm(byte[] audioBytes) { lines.removeAllElements(); // clear the old vector AudioFormat format = audioInputStream.getFormat(); if (audioBytes == null) { try { System.out.println(audioInputStream.getFrameLength() + " length"); audioBytes = new byte[ (int) (audioInputStream.getFrameLength() * format.getFrameSize())]; audioInputStream.read(audioBytes); } catch (Exception ex) { System.out.println(ex.toString()); return; } } Dimension d = getSize(); int w = d.width; int h = d.height-15; int[] audioData = null; if (format.getSampleSizeInBits() == 16) { int nlengthInSamples = audioBytes.length / 2; audioData = new int[nlengthInSamples]; if (format.isBigEndian()) { for (int i = 0; i < nlengthInSamples; i++) { /* First byte is MSB (high order) */ int MSB = (int) audioBytes[2*i]; /* Second byte is LSB (low order) */ int LSB = (int) audioBytes[2*i+1]; audioData[i] = MSB << 8 | (255 & LSB); } } else { for (int i = 0; i < nlengthInSamples; i++) { /* First byte is LSB (low order) */ int LSB = (int) audioBytes[2*i]; /* Second byte is MSB (high order) */ int MSB = (int) audioBytes[2*i+1]; audioData[i] = MSB << 8 | (255 & LSB); } } } else if (format.getSampleSizeInBits() == 8) { int nlengthInSamples = audioBytes.length; audioData = new int[nlengthInSamples]; if (format.getEncoding().toString().startsWith("PCM_SIGN")) { for (int i = 0; i < audioBytes.length; i++) { audioData[i] = audioBytes[i]; } } else { for (int i = 0; i < audioBytes.length; i++) { audioData[i] = audioBytes[i] - 128; } } } int frames_per_pixel = audioBytes.length / format.getFrameSize()/w; byte my_byte = 0; double y_last = 0; int numChannels = format.getChannels(); for (double x = 0; x < w && audioData != null; x++) { int idx = (int) (frames_per_pixel * numChannels * x); if (format.getSampleSizeInBits() == 8) { my_byte = (byte) audioData[idx]; } else { my_byte = (byte) (128 * audioData[idx] / 32768 ); } double y_new = (double) (h * (128 - my_byte) / 256); lines.add(new Line2D.Double(x, y_last, x, y_new)); y_last = y_new; } repaint(); } public void paint(Graphics g) { String errStr = null; Dimension d = getSize(); int w = d.width; int h = d.height; int INFOPAD = 15; Font font10 = new Font("serif", Font.PLAIN, 10); Font font12 = new Font("serif", Font.PLAIN, 12); Graphics2D g2 = (Graphics2D) g; g2.setBackground(getBackground()); g2.clearRect(0, 0, w, h); g2.setColor(Color.white); g2.fillRect(0, h-INFOPAD, w, INFOPAD); if (errStr != null) { g2.setColor(jfcBlue); g2.setFont(new Font("serif", Font.BOLD, 18)); g2.drawString("ERROR", 5, 20); AttributedString as = new AttributedString(errStr); as.addAttribute(TextAttribute.FONT, font12, 0, errStr.length()); AttributedCharacterIterator aci = as.getIterator(); FontRenderContext frc = g2.getFontRenderContext(); LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); float x = 5, y = 25; lbm.setPosition(0); while (lbm.getPosition() < errStr.length()) { TextLayout tl = lbm.nextLayout(w-x-5); if (!tl.isLeftToRight()) { x = w - tl.getAdvance(); } tl.draw(g2, x, y += tl.getAscent()); y += tl.getDescent() + tl.getLeading(); } } else { g2.setColor(Color.black); g2.setFont(font12); g2.drawString("File: " + "FILENAME" + " Length: " + String.valueOf(duration) + " Position: " + String.valueOf(seconds), 3, h-4); if (audioInputStream != null) { // .. render sampling graph .. g2.setColor(jfcBlue); for (int i = 1; i < lines.size(); i++) { g2.draw((Line2D) lines.get(i)); } // .. draw current position .. if (seconds != 0) { double loc = seconds/duration*w; g2.setColor(pink); g2.setStroke(new BasicStroke(3)); g2.draw(new Line2D.Double(loc, 0, loc, h-INFOPAD-2)); } } } } /** * Tests the player */ public static void main(String args[]) { JFrame f = new JFrame(); f.setSize(640,480); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); //f.setLayout(new BorderLayout()); SamplingGraph g = new SamplingGraph(); f.add(g); try { g.open(new File("/Users/guigouz/Music/happy_together.mp3")); g.createWaveForm(null); } catch (UnsupportedAudioFileException ex) { JOptionPane.showMessageDialog(null, "Erro " + ex); } catch (IOException ex) { JOptionPane.showMessageDialog(null, "IO " + ex); } /* Playing works, just commented out try { g.play(); } catch (LineUnavailableException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); }*/ } public void play() throws LineUnavailableException, IOException { byte[] data = new byte[4096]; DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioInputStream.getFormat()); SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info); line.open(audioInputStream.getFormat()); if(line != null) { // Start line.start(); int nBytesRead = 0, nBytesWritten = 0; while (nBytesRead != -1) { nBytesRead = audioInputStream.read(data, 0, data.length); if (nBytesRead != -1) nBytesWritten = line.write(data, 0, nBytesRead); } // Stop line.drain(); line.stop(); line.close(); } } } // End class SamplingGraph