JDK-6186076 : REGRESSION:Doesn't play multiple clips repeatedly after invoking stop(), setFrame..start()
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.sound
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_98
  • CPU: x86
  • Submitted: 2004-10-28
  • Updated: 2010-08-17
  • Resolved: 2005-03-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0Resolved
Related Reports
Duplicate :  
Description
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, sharing)


ADDITIONAL OS VERSION INFORMATION :
Windows 98 SE, Windows XP

A DESCRIPTION OF THE PROBLEM :
JDK 1.5.0/1.4.2

In short, my program that works perfectly in 1.4.2_05, does not work in
1.5.0.

Actual problem is described below. Some issue common  to both 1.5.0 and 1.4.2 is first described to get some idea.

Even after playback has ended, call to clip.stop() is required before it's
frame position can be set to zero.

A LineListener something like this is required to playback clip
multiple time at different different times

  class AudioLineListener implements LineListener
  {
    boolean stopped = false;
    public void update(LineEvent e)
    {
      Clip clip = (Clip)e.getLine();
      if (e.getType().equals(LineEvent.Type.STOP)) {
        if (!stopped) {
          System.out.println("Clip "+clip+" is not stopped...stopping");
          clip.stop();
          clip.setFramePosition(0);
          stopped = true;
        }
      }
      else if (e.getType().equals(LineEvent.Type.START)) {
        stopped = false;
      }
    }
  }

This seems a bit awkward for playing sounds with volume controls
for an application.
An example is playing collision sounds in billiards simulation.

Perhaps we need a method, say, "play()" that starts playing
and rewinds itself to the beginning and come to a stop.
This may be called at any time without having to call stop() without having
to implement the adapter class I have included above.
But this method has effect only after the clip has finished playing.

The need for such is method is that even if I change the sequence
of instructions slightly in the above piece of code, the program goes in a
endless loop or crashes.

It is interesting to note that stop() method inside the update(...) method
above does not fire another stop event. Nevertheless I have put the
controlling code inside a if conditional for safety reasons.

This method works only in 1.4.2 successfully. Even this method does not
work in 1.5.0. It has some problems playing sounds repeatedly at
specified times.

Futher multiple clips could not be heard sometimes in 1.5.0
though start and stop events for all clips are fired.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Please run the code included below with 1.4.2 and 1.5.0to
experience the differences


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
4 media files, namely,

chimes.wav, chord.wav, ding.wav, notify.wav

 in C:\WINDOWS\MEDIA directory in Win98SE OS,

are played in succession with the intervals of 1200 millisecs two times.

Output in 1.4.2

---------- Java (1.4) ----------
JavaSoundTester: Clip 'chimes' opened
JavaSoundTester: Clip 'chord' opened
JavaSoundTester: Clip 'ding' opened
JavaSoundTester: Clip 'notify' opened
JavaSoundTester: Max Gain: 13.979399681091309
JavaSoundTester: Clip 'chimes' started
JavaSoundTester: Clip 'chimes' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'chord' started
JavaSoundTester: Clip 'chord' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'ding' started
JavaSoundTester: Clip 'ding' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'notify' started
JavaSoundTester: Clip chimes started at frame pos 0
JavaSoundTester: Clip chimes stopped at frame pos 0
JavaSoundTester: Clip chord started at frame pos 0
JavaSoundTester: Clip chord stopped at frame pos 0
JavaSoundTester: Clip ding started at frame pos 0
JavaSoundTester: Clip ding stopped at frame pos 0
JavaSoundTester: Clip notify started at frame pos 0
JavaSoundTester: Clip notify stopped at frame pos 0
JavaSoundTester: Clip 'notify' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'chimes' started
JavaSoundTester: Clip 'chimes' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'chord' started
JavaSoundTester: Clip 'chord' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'ding' started
JavaSoundTester: Clip 'ding' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'notify' started
JavaSoundTester: Clip chimes started at frame pos 0
JavaSoundTester: Clip chimes stopped at frame pos 0
JavaSoundTester: Clip chord started at frame pos 0
JavaSoundTester: Clip chord stopped at frame pos 0
JavaSoundTester: Clip ding started at frame pos 0
JavaSoundTester: Clip ding stopped at frame pos 0
JavaSoundTester: Clip notify started at frame pos 0
JavaSoundTester: Clip notify stopped at frame pos 0
JavaSoundTester: Clip 'chimes' closed
JavaSoundTester: Clip 'chord' closed
JavaSoundTester: Clip 'ding' closed
JavaSoundTester: Clip 'notify' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'notify' closed


ACTUAL -
In 1.5.0-rc,  sequence os sounds heard:

chimes.wav
chord.wav
notify.wav
chord.wav
notify.wav

In my actual game app the situation is worse.

Output:

---------- Java Execute (1.5) ----------
JavaSoundTester: Clip 'chimes' opened
JavaSoundTester: Clip 'chord' opened
JavaSoundTester: Clip 'ding' opened
JavaSoundTester: Clip 'notify' opened
JavaSoundTester: Max Gain: 6.020599842071533
JavaSoundTester: Clip 'chimes' started
JavaSoundTester: Clip 'chimes' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'chord' started
JavaSoundTester: Clip 'chord' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'ding' started
JavaSoundTester: Clip 'ding' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'notify' started
JavaSoundTester: Clip chimes started at frame pos 100
JavaSoundTester: Clip chimes stopped at frame pos 13921
JavaSoundTester: Clip chord started at frame pos 0
JavaSoundTester: Clip chord stopped at frame pos 24231
JavaSoundTester: Clip ding started at frame pos 0
JavaSoundTester: Clip ding stopped at frame pos 0
JavaSoundTester: Clip notify started at frame pos 0
JavaSoundTester: Clip notify stopped at frame pos 0
JavaSoundTester: Clip 'notify' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'chimes' started
JavaSoundTester: Clip 'chimes' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'chord' started
JavaSoundTester: Clip 'chord' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'ding' started
JavaSoundTester: Clip 'ding' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'notify' started
JavaSoundTester: Clip chimes started at frame pos 0
JavaSoundTester: Clip chimes stopped at frame pos 0
JavaSoundTester: Clip chord started at frame pos 0
JavaSoundTester: Clip chord stopped at frame pos 24231
JavaSoundTester: Clip ding started at frame pos 0
JavaSoundTester: Clip ding stopped at frame pos 0
JavaSoundTester: Clip notify started at frame pos 0
JavaSoundTester: Clip notify stopped at frame pos 29823
JavaSoundTester: Clip 'chimes' closed
JavaSoundTester: Clip 'chord' closed
JavaSoundTester: Clip 'ding' closed
JavaSoundTester: Clip 'notify' stopped
JavaSoundTester: clip is not stopped...stopping
JavaSoundTester: Clip 'notify' closed





REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
// JavaSoundTester.java
import javax.sound.sampled.*;
import java.io.*;

/** Tests wave sound play back */
class JavaSoundTester
{
  /** Names of the wave file in the c:\windows\media directory */
  private static String[]  clipNames = {
    "chimes", "chord", "ding", "notify"
  };

  /** Array of clips to be test played */
  private static Clip[]         clips       = new Clip[clipNames.length];
  
  /** Master Gain control of the clips */
  private static FloatControl[] gains = new FloatControl[clipNames.length];

  /** Set to true when sound clips are successfully opened */
  private static boolean apiSoundsLoaded = false;

  static long[] startFrames = new long[clipNames.length];
  static long[] stopFrames  = new long[clipNames.length];

  static double maxGain;

  /** loads small sample wave files into clips */
  static void loadSounds()
  {
    if (apiSoundsLoaded) return;

    AudioInputStream in;

    File home = new File(System.getProperty("user.home"));
    File soundFile = null;

    try
    {
      for (int i = 0; i < clipNames.length; i++)
      {
        // For Windows OS only
        soundFile = new File(home, "media/"+clipNames[i]+".wav");

        in  = AudioSystem.getAudioInputStream(soundFile);
        
        clips[i] = getClip(in);
        //clips[i] = AudioSystem.getClip(); // available only in 1.5
        
        clips[i].addLineListener(new AudioLineListener(i));
        clips[i].open(in);
        
        gains[i]
          = (FloatControl) clips[i].getControl(FloatControl.Type.MASTER_GAIN);
      }

      apiSoundsLoaded = true;
      maxGain = gains[0].getMaximum();

      out("Max Gain: "+maxGain);
    }
    catch (IOException ioe)
    {
      out("IOE: "+ioe.getMessage());
      exit1();
    }
    catch (UnsupportedAudioFileException uafe)
    {
      out("UnsupportedAudioFileException: "+uafe.getMessage());
      out("file: " + soundFile);
      exit1();
    }
    catch (LineUnavailableException lue)
    {
      out("LineUnavailableException: "+lue.getMessage());
      exit1();
    }
  }

  /** Returns clip from AudioInPutStream */
  private static Clip getClip(AudioInputStream in)
    throws LineUnavailableException
  {
    AudioFormat format = in.getFormat();
    
    DataLine.Info
      info = new DataLine.Info(
                   Clip.class,
                   format,
                   ((int) in.getFrameLength() * format.getFrameSize())
             );

    return (Clip) AudioSystem.getLine(info);
  }

  /** Custom line events listener */
  private static class AudioLineListener implements LineListener
  {
    int ix;
    boolean stopped = false;

    AudioLineListener(int index)
    {
      ix = index;
    }

    public void update(LineEvent e)
    {
      Clip clip = clips[ix];
      //Clip clip = (Clip)e.getLine();
      String clipName = clipNames[ix];

      if (e.getType().equals(LineEvent.Type.START))
      {
        stopped = false;
        if (debug)
        {
          startFrames[ix] = clip.getFramePosition();
          out("Clip '" + clipName + "' started");
          //out("frame pos: " + clip.getFramePosition());
        }
      }
      else if (e.getType().equals(LineEvent.Type.STOP))
      {
        if (debug)
        {
          stopFrames[ix] = clip.getFramePosition();
          out("Clip '" + clipName + "' stopped");
          //out("frame pos: " + clip.getFramePosition());
        }
        
        // has to be invoked .. otherwise goes in an inf loop with the
        // next line of code
        if (!stopped) {
          if (debug) out("clip is not stopped...stopping");
          clip.stop();
          clip.setFramePosition(0);
          stopped = true;
        }
      }
      else if (e.getType().equals(LineEvent.Type.OPEN))
      {
        if (debug) out("Clip '" + clipName + "' opened");
      }
      else if (e.getType().equals(LineEvent.Type.CLOSE))
      {
        if (debug) out("Clip '" + clipName + "' closed");
      }
    }
  }

  static void playSounds()
  {
    if (!apiSoundsLoaded)
      return;

    for (int i = 0; i < clipNames.length; i++)
    {
      clips[i].start();
            
      try {
        Thread.sleep(1200);
      }
      catch (Exception ex) {}
    }

    for (int i = 0; i < clipNames.length; i++)
    {
      out("Clip "+clipNames[i]+" started at frame pos " + startFrames[i]);
      out("Clip "+clipNames[i]+" stopped at frame pos " + stopFrames[i] );
    }
  }


  static void closeLines()
  {
    for (int i = 0; i < clipNames.length; i++) {
      if (clips[i] != null) {
        if (clips[i].isOpen()) {
          clips[i].close();
        }
      }
    }
  }

  static void exit1()
  {
    closeLines();
    System.exit(1);
  }

  static void exit()
  {
    closeLines();
    System.exit(0);
  }

  static boolean debug = true;
  static void out(Object o)
  {
    System.out.println("JavaSoundTester: " + o);
  }

  public static void main(String[] args)
  {
    loadSounds();

    playSounds();
    
    try {
      Thread.sleep(2000);
    }
    catch (Exception ex) {
    }

    playSounds();

    exit();

    System.out.println("Hello World!");
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None. Simply use JDK 1.4.2 instead of 1.5.0-rc

Release Regression From : 1.4.2_05
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.
###@###.### 10/28/04 16:48 GMT

Comments
EVALUATION This test program plays four very short sound files as clips. It appears to be a duplicate of 5070730 -- fixed in J2SE 1.5 update 2. ###@###.### 2005-03-16 04:23:08 GMT
16-03-2005