Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6196668

Pausing/resuming playback adds overlapped audio to output

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 5.0
    • client-libs

      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

            amenkov Alex Menkov
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: