Author: bpoussin Date: 2012-09-05 01:44:49 +0200 (Wed, 05 Sep 2012) New Revision: 521 Url: http://forge.codelutin.com/repositories/revision/sammoa/521 Log: Composant de lecture audio et fenetre de test de l'audio Pas de compression (speex ou flac ne fonctionne pas pour l'instant :() ps: vraiment pas la bonne place, mais je prefere commit et laisser florian le deplacer la ou il faut. Added: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/AudioTest.java trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/SoundPlayer.java Added: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/AudioTest.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/AudioTest.java (rev 0) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/AudioTest.java 2012-09-04 23:44:49 UTC (rev 521) @@ -0,0 +1,330 @@ +package fr.ulr.sammoa.application.device.audio; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import javax.media.CannotRealizeException; +import javax.media.NoPlayerException; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Petite application de test de l'audio. Elle permet de choisir differente + * configuration audio. De faire des enregistrements et de relire le fichier + * enregistre. + * <p> + * La configuration choisi est inscrite et permet de la copier dans le fichier + * de configuration + * <p> + * Si la machine ne supporte pas deux enregistrement simultane, delay est mis + * a 0. + * + * Created: 27 aout 2012 + * + * @author Benjamin POUSSIN <poussin@codelutin.com> + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class AudioTest extends JFrame { + + private static final Logger logger = LoggerFactory.getLogger(AudioTest.class); + + protected SammoaAudioRecorder recorder; + /** delay par defaut de chevauchement d'enregistrement */ + protected int delay = 0; + + protected JTextField filenameField = new JTextField("/tmp/junkk.wav"); + protected JTextArea informationArea = new JTextArea(); + + protected JButton captureBtn = new JButton("Capture"); + protected JButton stopBtn = new JButton("Stop"); + protected JButton loadBtn = new JButton("Load"); + protected SoundPlayer playerPanel = new SoundPlayer(); + + protected JPanel btnPanelSampleRate = new JPanel(); + protected ButtonGroup btnGroupSampleRate = new ButtonGroup(); + JRadioButton[] btnSampleRate = new JRadioButton[]{ + new JRadioButton("8000",true), + new JRadioButton("11025"), + new JRadioButton("16000"), + new JRadioButton("22050"), + new JRadioButton("44100") + }; + + protected JPanel btnPanelSampleSizeInBits = new JPanel(); + protected ButtonGroup btnGroupSampleSizeInBits = new ButtonGroup(); + JRadioButton[] btnSampleSizeInBits = new JRadioButton[]{ + new JRadioButton("8"), + new JRadioButton("16",true) + }; + + public AudioTest(){//constructor + initUI(); + testMultiRecord(); + } + + protected void initUI () { + Box buttons = Box.createHorizontalBox(); + buttons.add(captureBtn); + buttons.add(stopBtn); + + Box box = Box.createVerticalBox(); + box.add(filenameField); + box.add(buttons); + + for (JRadioButton b : btnSampleRate) { + //Include the radio buttons in a group + btnGroupSampleRate.add(b); + //Add the radio buttons to the JPanel + btnPanelSampleRate.add(b); + b.addActionListener( + new ActionListener(){ + public void actionPerformed( + ActionEvent e){ + updateConfigInfo(); + } + }); + } + + //Put the JPanel in the JFrame + box.add(btnPanelSampleRate); + + for (JRadioButton b : btnSampleSizeInBits) { + //Include the radio buttons in a group + btnGroupSampleSizeInBits.add(b); + //Add the radio buttons to the JPanel + btnPanelSampleSizeInBits.add(b); + b.addActionListener( + new ActionListener(){ + public void actionPerformed( + ActionEvent e){ + updateConfigInfo(); + } + }); + } + + //Put the JPanel in the JFrame + box.add(btnPanelSampleSizeInBits); + + informationArea.setBorder(BorderFactory.createRaisedBevelBorder()); + informationArea.setLineWrap(true); + box.add(informationArea); + box.add(loadBtn); + box.add(playerPanel); + + //Finish the GUI and make visible + setTitle("Sound Test"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + getContentPane().add(box, "Center"); + pack(); + setVisible(true); + + captureBtn.setEnabled(true); + stopBtn.setEnabled(false); + + // ADD LISTENER + + //Register anonymous listeners + captureBtn.addActionListener( + new ActionListener(){ + public void actionPerformed( + ActionEvent e){ + captureBtn.setEnabled(false); + stopBtn.setEnabled(true); + captureAudio(); + } + }); + + stopBtn.addActionListener( + new ActionListener(){ + public void actionPerformed( + ActionEvent e){ + captureBtn.setEnabled(true); + stopBtn.setEnabled(false); + recorder.stop(); + } + }); + + loadBtn.addActionListener( + new ActionListener(){ + public void actionPerformed( + ActionEvent e){ + File file = new File(filenameField.getText()); + playerPanel.loadFile(file); + } + }); + } + + protected void captureAudio(){ + try{ + File file = new File(filenameField.getText()); + recorder = new SammoaAudioRecorder(getSampleRate(), getSampleSizeInBits(), 0); + recorder.record(file, true); + }catch (Exception eee) { + logger.error("Can't capture audio", eee); + } + } + + protected float getSampleRate() { + float result = 44100; + for (JRadioButton b : btnSampleRate) { + if (b.isSelected()) { + result = Float.parseFloat(b.getText()); + } + } + return result; + } + + protected int getSampleSizeInBits() { + int result = 44100; + for (JRadioButton b : btnSampleSizeInBits) { + if (b.isSelected()) { + result = Integer.parseInt(b.getText()); + } + } + return result; + } + + protected void updateConfigInfo() { + informationArea.setText(String.format( + "sammoa.audio.recordDelayInSeconds=%s\n" + + "sammoa.audio.sampleRate=%s\n" + + "sammoa.audio.sampleSizeInBits=%s\n", + delay, getSampleRate(), getSampleSizeInBits())); + } + + protected void testMultiRecord() { + try { + File f1 = File.createTempFile("sammoa-test-", ".wav"); + f1.deleteOnExit(); + File f2 = File.createTempFile("sammoa-test-", ".wav"); + f2.deleteOnExit(); + + SammoaAudioRecorder r1 = new SammoaAudioRecorder(8000, 16, 2); + r1.record(f1, true); + + SammoaAudioRecorder r2 = new SammoaAudioRecorder(8000, 16, 2); + r2.record(f2, true); + + r2.stop(); + r1.stop(); + delay = 5; + } catch(Exception eee) { + logger.error("Can't record multiple file in same time", eee); + delay = 0; + } + updateConfigInfo(); + } + + + public static void main( String args[]) + throws LineUnavailableException, UnsupportedAudioFileException, IOException, NoPlayerException, CannotRealizeException{ + new AudioTest(); + +// float sampleRate = 8000; // 8000,11025,16000,22050,44100 +// int sampleSizeInBits = 16; // 8,16 +// +// int channels = 1; // 1,2 +// boolean signed = true; //true,false +// boolean bigEndian = false; //true,false +// +// AudioFormat audioFormat = new AudioFormat( +// sampleRate, +// sampleSizeInBits, +// channels, +// signed, +// bigEndian); +// +// DataLine.Info dataLineInfo = new DataLine.Info( +// TargetDataLine.class, audioFormat); +// { +// TargetDataLine l1 = (TargetDataLine)AudioSystem.getLine(dataLineInfo); +// System.out.println("Line: " + l1); +// System.out.println("Line: " + l1.getLineInfo()); +// l1.open(audioFormat); +// l1.start(); +// +// TargetDataLine l2 = (TargetDataLine)AudioSystem.getLine(dataLineInfo); +// System.out.println("Line: " + l2); +// System.out.println("Line: " + l2.getLineInfo()); +// l2.open(audioFormat); +// l1.start(); +// } +// { +// AudioFileFormat aff = AudioSystem.getAudioFileFormat(new File("/tmp/junkk.wav")); +// System.out.println("File: "+ aff.toString()); +// AudioInputStream sourceAis = AudioSystem.getAudioInputStream(new File("/tmp/junkk.wav")); +// +// DataLine.Info clipInfo = new DataLine.Info(Clip.class, audioFormat); +// Clip clip = (Clip)AudioSystem.getLine(clipInfo); +// +// AudioInputStream ais = AudioSystem.getAudioInputStream(audioFormat, sourceAis); +//// clip.open(ais); +//// clip.start(); +// } +// { +// File f = new File("/tmp/junkk.wav"); +// Player p = Manager.createRealizedPlayer(f.toURI().toURL()); +// p.start(); +//// p.set +// } +// +// System.out.println("#############################################"); +// Line.Info[] sources = AudioSystem.getSourceLineInfo(new Line.Info(SourceDataLine.class)); +// Line.Info[] target = AudioSystem.getTargetLineInfo(new Line.Info(TargetDataLine.class)); +// +// System.out.println("AudioFileTypes:" + Arrays.toString(AudioSystem.getAudioFileTypes())); +// +// System.out.println("mixer:" + Arrays.toString(AudioSystem.getMixerInfo())); +// for(Mixer.Info i : AudioSystem.getMixerInfo()) { +// Mixer mixer = AudioSystem.getMixer(i); +// System.out.println("-----"); +// System.out.println("mixer:" + mixer + "("+mixer.isLineSupported(Port.Info.MICROPHONE)+")"); +// try { +// mixer.open(); +// } catch (LineUnavailableException eee) { +// System.out.println("Can't open mixer"); +// } +// System.out.println("mixer:" + mixer + "("+mixer.isLineSupported(Port.Info.MICROPHONE)+")"); +// +// System.out.println("mixer info: " + mixer.getLineInfo()); +// System.out.println("max line: " + mixer.getMaxLines(mixer.getLineInfo())); +// +// for (Line.Info li : mixer.getSourceLineInfo()) { +// System.out.println("s line info: " + li + "("+mixer.getMaxLines(li)+")"); +// System.out.println("s line info: " + li.getLineClass()); +// } +// +// for (Line.Info li : mixer.getTargetLineInfo()) { +// System.out.println("t line info: " + li + "("+mixer.getMaxLines(li)+")"); +// System.out.println("t line info: " + li.getLineClass()); +// } +// +// for (Line l : mixer.getSourceLines()) { +// System.out.println("s line: " + l); +// System.out.println("s line info: " + l.getLineInfo()); +// } +// for (Line l : mixer.getTargetLines()) { +// System.out.println("t line: " + l); +// System.out.println("t line info: " + l.getLineInfo()); +// } +// } +// System.out.println("sources: " + Arrays.toString(sources)); +// System.out.println("target: " + Arrays.toString(target)); + + } +} \ No newline at end of file Added: trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/SoundPlayer.java =================================================================== --- trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/SoundPlayer.java (rev 0) +++ trunk/sammoa-application/src/main/java/fr/ulr/sammoa/application/device/audio/SoundPlayer.java 2012-09-04 23:44:49 UTC (rev 521) @@ -0,0 +1,225 @@ +package fr.ulr.sammoa.application.device.audio; + +import fr.ulr.sammoa.application.device.DeviceState; +import fr.ulr.sammoa.application.device.DeviceStateEvent; +import fr.ulr.sammoa.application.device.DeviceStateListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.io.IOException; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +/** + * Composant qui permet de charge un fichier audio et de le jouer. On peut se + * placer ou l'on veut dans le fichier audio. + * + * usage: + * <li> SoundPlayer sp = new SoundPlayer(); + * <li> panel.add(sp); + * <li> sp.load(myFileWav); + * + * Created: 03 septembre 2012 + * + * @author Benjamin POUSSIN <poussin@codelutin.com> + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class SoundPlayer extends JComponent implements DeviceStateListener { + protected SammoaAudioReader reader; + protected boolean playing = false; // whether the sound is currently playing + + // The following fields are for the GUI + protected JButton play; // The Play/Stop button + protected JSlider progress; // Shows and sets current position in sound + protected JLabel time; // Displays audioPosition as a number + protected JLabel maxTime; + + // Create a SoundPlayer component for the specified file. + public SoundPlayer() { + initUI(); + initAudio(); + } + + protected void initUI() { + // Now create the basic GUI + play = new JButton("Play"); // Play/stop button + progress = new JSlider(0, 0, 0); // Shows position in sound + progress.setMajorTickSpacing(60000); + progress.setMinorTickSpacing(10000); + progress.setPaintTicks(true); + progress.setPaintLabels(true); + + time = new JLabel("0"); // Shows position as a # + maxTime = new JLabel("/0"); // Shows position as a # + + // put those controls in a row + Box row = Box.createHorizontalBox( ); + row.add(play); + row.add(progress); + row.add(time); + row.add(maxTime); + + // And add them to this component. + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + this.add(row); + + // ADD LISTENER + + // When clicked, start or stop playing the sound + play.addActionListener(new ActionListener( ) { + public void actionPerformed(ActionEvent e) { + if (playing) { + stop( ); + } else { + play( ); + } + } + }); + + progress.addMouseListener(new MouseAdapter() { + boolean inPlay = false; + + @Override + public void mousePressed(MouseEvent e) { + inPlay= playing; + if (inPlay) { + reader.stop(); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + int value = progress.getValue( ); + // Update the time label + time.setText(value/1000 + "." + (value%1000)/100); + // If we're not already there, skip there. + if (value >= 0 && value <= reader.getLength()) { + reader.setPosition(value); + } + + if (inPlay) { + reader.start(); + } + } + }); + + // Whenever the slider value changes, update the time label. + progress.addChangeListener(new ChangeListener( ) { + public void stateChanged(ChangeEvent e) { + int value = progress.getValue( ); + time.setText(value/1000 + "." + (value%1000)/100); + } + }); + } + + protected void initAudio() { + reader = new SammoaAudioReader(); + reader.addDeviceStateListener(this); + // on se met listener de l'avancee de la lecture + reader.addAudioPositionListener(new SammoaAudioReader.AudioPositionListener() { + public void positionChange(Object source, long audioPosition) { + progress.setValue((int)audioPosition); + } + }); + + } + + public void stateChanged(DeviceStateEvent event) { + DeviceState state = event.getNewValue(); + if (state == DeviceState.RUNNING) { + this.playing = true; + play.setText("Stop"); + } else { + this.playing = false; + play.setText("Play"); + } + } + + /** + * Charge un nouveau fichier + * @param f le fichier a charger + */ + public void loadFile(File f) { + getAudioReader().load(f); + long value = getLength(); + progress.setMaximum((int)value); + maxTime.setText("/" + value/1000 + "." + (value%1000)/100); + } + + /** + * retourne le lecture utilise par ce composant + * @return + */ + public SammoaAudioReader getAudioReader() { + return reader; + } + + /** + * Donne la position actuelle de la lecture en milliseconde + * @return + */ + public long getPosition() { + return getAudioReader().getPosition(); + } + + /** + * Donne la longueur total du fichier en milliseconde + * @return + */ + public long getLength() { + return getAudioReader().getLength(); + } + + /** + * Start playing the sound at the current position + */ + public void play() { + getAudioReader().start(); + } + + /** + * Stop playing the sound, but retain the current position + */ + public void stop() { + getAudioReader().stop(); + } + + // The main method just creates a SoundPlayer in a Frame and displays it + public static void main(String[] args) + throws IOException, UnsupportedAudioFileException, LineUnavailableException { + SoundPlayer player; + + File file; + if (args.length == 0) { + file = new File("/tmp/junkk1.wav"); + } else { + file = new File(args[0]); + } + + // Create a SoundPlayer object to play the sound. + player = new SoundPlayer(); + player.loadFile(file); + + // Put it in a window and play it + JFrame f = new JFrame("SoundPlayer"); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add(player, "Center"); + f.pack(); + f.setVisible(true); + } + +} \ No newline at end of file