Duplicate :
|
FULL PRODUCT VERSION : java version "1.5.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64) Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows XP [Version 5.1.2600] EXTRA RELEVANT SYSTEM CONFIGURATION : Realtek AC97 Audio on motherboard A DESCRIPTION OF THE PROBLEM : (This is being resubmitted since I didn't get an auto-generated email the first time it was submitted.) Audio playback within a java.sound.sampled.Clip is behaving strangely. While playing a wav (haven't tried anything else) file, if playback is paused and resumed, the audio output is repeating audio data. It kind of sounds like a skip and then it continues (eg. "Welcome <pause><resume> to Java...to Java sound"). When it get's to the end of the file the microsecond position indicates a position longer than the actual length. Playback can be paused and resumed multiple times for a more pronounced effect. Debugger shows that the actual Clip class is com.sun.media.sound.DirectAudioDevice$DirectClip. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Run the test app provided. 2. Open a wav file. 3. Click Play. 4. Click Pause, then Play again to resume. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - Clip is played, paused and resumed without a problem. ACTUAL - No error, just a problem with the audio playback. A portion of the audio is overlapped with previously played audio. REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import javax.sound.sampled.*; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.util.Vector; public class VoicePromptPlayer extends JFrame implements ActionListener { Player player = new Player(); AudioInputStream audioInputStream; JButton buttonPlayPause = new JButton(); JButton buttonStop = new JButton(); JButton buttonClose = new JButton(); JLabel lblPosition = new JLabel(); JLabel lblLength = new JLabel(); JLabel lblPositionSeconds = new JLabel(); JLabel lblLengthSeconds = new JLabel(); JLabel lblSecond1 = new JLabel(); JLabel lblSecond2 = new JLabel(); JPanel topPanel = new JPanel(new BorderLayout()); JPanel positionPanel = new JPanel(); JPanel lengthPanel = new JPanel(); JPanel bottomPanel = new JPanel(new BorderLayout()); JPanel controlButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5)); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5)); int lengthInMilliseconds, seconds; Vector lines = new Vector(); public VoicePromptPlayer() { super("Player"); this.getContentPane().setLayout(new BorderLayout()); setupTopPanel(); buttonPlayPause.setText("Play"); buttonPlayPause.setActionCommand("Play"); buttonPlayPause.addActionListener(this); buttonPlayPause.setEnabled(false); buttonPlayPause.setFocusPainted(false); buttonStop.setText("Stop"); buttonStop.setActionCommand("Stop"); buttonStop.addActionListener(this); buttonStop.setEnabled(false); buttonStop.setFocusPainted(false); buttonClose.setText("Close"); buttonClose.addActionListener(this); buttonPanel.add(buttonClose); controlButtonPanel.add(buttonPlayPause); controlButtonPanel.add(buttonStop); controlButtonPanel.add(buttonPanel); bottomPanel.add(controlButtonPanel, BorderLayout.WEST); bottomPanel.add(buttonPanel, BorderLayout.EAST); this.getContentPane().add(topPanel, BorderLayout.NORTH); this.getContentPane().add(bottomPanel, BorderLayout.SOUTH); createAudioInputStream(); lblPosition.setText("Position: "); lblPositionSeconds.setText(formatMilliseconds(0)); lblLength.setText("Length: "); lblLengthSeconds.setText(formatMilliseconds((long)lengthInMilliseconds)); lblSecond1.setText(" sec."); lblSecond2.setText(" sec."); if (audioInputStream != null) { buttonPlayPause.setEnabled(true); } this.setResizable(false); this.addWindowListener(new MyWindowAdapter()); this.pack(); this.setLocationRelativeTo(null); } private void setupTopPanel() { GridBagLayout gbLayout = new GridBagLayout(); GridBagConstraints gbc = new GridBagConstraints(); positionPanel.setLayout(gbLayout); gbc.weightx = 0.0; gbc.weighty = 0.0; gbc.gridheight = 1; gbc.gridwidth = 1; gbc.insets = new Insets(4, 4, 0, 0); gbc.ipadx = 0; gbc.ipady = 0; gbc.gridx = 0; gbc.gridy = 0; gbc.fill = GridBagConstraints.NONE; gbc.anchor = GridBagConstraints.WEST; gbLayout.setConstraints(lblPosition, gbc); positionPanel.add(lblPosition); gbc.insets = new Insets(4, 0, 0, 0); gbc.gridx = 1; positionPanel.add(lblPositionSeconds, gbc); gbc.weightx = 1.0; gbc.gridx = 2; positionPanel.add(lblSecond1, gbc); topPanel.add(positionPanel, BorderLayout.WEST); gbLayout = new GridBagLayout(); lengthPanel.setLayout(gbLayout); gbc.gridx = 0; gbc.anchor = GridBagConstraints.EAST; lengthPanel.add(lblLength, gbc); gbc.weightx = 0.0; gbc.gridx = 1; lengthPanel.add(lblLengthSeconds, gbc); gbc.insets = new Insets(4, 0, 0, 4); gbc.gridx = 2; lengthPanel.add(lblSecond2, gbc); topPanel.add(lengthPanel, BorderLayout.EAST); } public static void main(String args[]) { VoicePromptPlayer player = new VoicePromptPlayer(); player.setVisible(true); } public String toString() { return ("Player"); } public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if (obj.equals(buttonPlayPause)) { if (buttonPlayPause.getActionCommand().equals("Play")) { // Need to start play or resume if (player.isPaused()) player.resume(); else player.play(); // Either way modify the button setPauseButton(); buttonStop.setEnabled(true); } else { player.pause(); setPlayButton(); } pack(); } else if (obj.equals(buttonStop)) { player.stop(); buttonStop.setEnabled(false); if (buttonPlayPause.getActionCommand().equals("Pause")) setPlayButton(); } else if (obj.equals(buttonClose)) { player.stop(); this.dispose(); } } private String formatMilliseconds(long milliseconds) { DecimalFormat format = new DecimalFormat("0.00"); double seconds = milliseconds / 1000.0; String formattedOutput = format.format(seconds); return formattedOutput; } private void setPlayButton() { buttonPlayPause.setText("Play"); buttonPlayPause.setActionCommand("Play"); } private void setPauseButton() { buttonPlayPause.setText("Pause"); buttonPlayPause.setActionCommand("Pause"); } public void createAudioInputStream() { JFileChooser chooser = new JFileChooser(); chooser.setFileSelectionMode(ListSelectionModel.SINGLE_SELECTION); chooser.showOpenDialog(this); File file = chooser.getSelectedFile(); try { audioInputStream = AudioSystem.getAudioInputStream(file); } catch (Exception e) {} if (audioInputStream != null) { player.initialize(); lengthInMilliseconds = (int)((audioInputStream.getFrameLength() * 1000) / audioInputStream.getFormat().getFrameRate()); } } /** * Voice prompt player. */ public class Player implements ActionListener { Timer timer; Clip clip; boolean paused = false; public Player() { timer = new Timer(100, this); timer.setRepeats(true); } public void actionPerformed(ActionEvent e) { long usec = clip.getMicrosecondPosition(); System.out.println("Clip position: " + usec + " usec, isRunning: " + clip.isRunning()); System.out.println("Timer time: " + System.currentTimeMillis() + " msec"); if ( (clip.isRunning() == false)) { // At end of playback if (buttonStop.isEnabled()) buttonStop.doClick(); } lblPositionSeconds.setText(formatMilliseconds((long) usec/1000)); lblPosition.repaint(); } public boolean isPaused() { return paused; } public void play() { if(clip == null) { JOptionPane.showMessageDialog(null, "There is no loaded audio to playback.", "Play Problem",JOptionPane.WARNING_MESSAGE); return; } System.out.println("\nClip starting"); System.out.println("Clip position: " + clip.getMicrosecondPosition() + " usec, isRunning: " + clip.isRunning()); clip.start(); System.out.println("Clip started"); System.out.println("Clip position: " + clip.getMicrosecondPosition() + " usec, isRunning: " + clip.isRunning()); System.out.println("Start time: " + System.currentTimeMillis() + " msec"); timer.start(); } public void pause() { if (timer != null) timer.stop(); if (clip != null) clip.stop(); paused = true; } public void resume() { if (clip != null) clip.start(); if (timer != null) timer.restart(); paused = false; } public void stop() { if (timer != null) timer.stop(); if (clip != null) { clip.stop(); clip.setFramePosition(0); } paused = false; } private void shutDown(String message) { if (message != null) { System.err.println(message); } setPlayButton(); buttonStop.setEnabled(false); } public void setPosition(long microseconds) { clip.setMicrosecondPosition(microseconds); } public void initialize() { // make sure we have something to play if (audioInputStream == null) { shutDown("There is no loaded audio to playback."); return; } // define the required attributes for our line, // and make sure a compatible line is supported. AudioFormat format = audioInputStream.getFormat(); DataLine.Info clipInfo = new DataLine.Info(Clip.class, format); if (!AudioSystem.isLineSupported(clipInfo)) { shutDown("A line matching desired info not supported" + ": " + clipInfo); return; } // get and open the source data line for playback. try { clip = (Clip)AudioSystem.getLine(clipInfo); // Create the clip clip.open(audioInputStream); clip.setFramePosition(0); } catch (IOException e) { shutDown("Unable to open clip" + ": " + e); return; } catch (LineUnavailableException ex) { shutDown("Unable to open line" + ": " + ex); return; } } } // End class Player class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { player.stop(); } } } ---------- END SOURCE ---------- ###@###.### 2004-11-17 17:32:17 GMT