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

REGRESSION:Doesn't play multiple clips repeatedly after invoking stop(), setFrame..start()

    XMLWordPrintable

Details

    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

      Attachments

        Issue Links

          Activity

            People

              rohixon Ronald Hixon (Inactive)
              rmandalasunw Ranjith Mandala (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: