AudioSystem goes into infinite recursive loop

I'm queuing 9 tracks with with repeatAll and crossfade.


              audio.getMusicQueue().setRepeatType(RepeatType.ALL);
              audio.getMusicQueue().setCrossfadeinTime(2.5f);
              audio.getMusicQueue().setCrossfadeoutTime(2.5f);
              audio.getMusicQueue().play();



Everything works fine when I read from directory. However, if i package my application and try to load tracks from the jar, then audio system cannot stream the tracks and goes into infinite recursive loop. Here the log.

It just keeps spitting errors and every new error has one more call to com.jmex.audio.MusicTrackQueue.update().
I suppose it would eventually crash with the stack memory overflow, but it's taking a very long time to reach it. It never throws an exception.


22-Nov-2007 4:37:47 AM com.jmex.audio.openal.OpenALStreamedAudioPlayer playInNewThread
SEVERE: Audio Error!
org.lwjgl.openal.OpenALException: OpenAL error: Invalid Name parameter (40961)
at org.lwjgl.openal.Util.checkALError(Util.java:64)
at org.lwjgl.openal.AL10.alSourcePlay(AL10.java:934)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.playStream(OpenALStreamedAudioPlayer.java:199)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.playInNewThread(OpenALStreamedAudioPlayer.java:214)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.play(OpenALStreamedAudioPlayer.java:166)
at com.jmex.audio.AudioTrack.play(AudioTrack.java:113)
at com.jmex.audio.MusicTrackQueue.play(MusicTrackQueue.java:144)
at com.jmex.audio.MusicTrackQueue.setCurrentTrack(MusicTrackQueue.java:212)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:232)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.openal.OpenALSystem.update(OpenALSystem.java:124)
at com.jmex.game.StandardGame.update(StandardGame.java:305)
at com.jmex.game.StandardGame.run(StandardGame.java:188)
at java.lang.Thread.run(Thread.java:619)
22-Nov-2007 4:37:47 AM com.jmex.audio.openal.OpenALStreamedAudioPlayer playInNewThread
SEVERE: Audio Error!
org.lwjgl.openal.OpenALException: OpenAL error: Invalid Name parameter (40961)
at org.lwjgl.openal.Util.checkALError(Util.java:64)
at org.lwjgl.openal.AL10.alSourcePlay(AL10.java:934)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.playStream(OpenALStreamedAudioPlayer.java:199)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.playInNewThread(OpenALStreamedAudioPlayer.java:214)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.play(OpenALStreamedAudioPlayer.java:166)
at com.jmex.audio.AudioTrack.play(AudioTrack.java:113)
at com.jmex.audio.MusicTrackQueue.play(MusicTrackQueue.java:144)
at com.jmex.audio.MusicTrackQueue.setCurrentTrack(MusicTrackQueue.java:212)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:232)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.openal.OpenALSystem.update(OpenALSystem.java:124)
at com.jmex.game.StandardGame.update(StandardGame.java:305)
at com.jmex.game.StandardGame.run(StandardGame.java:188)
at java.lang.Thread.run(Thread.java:619)
22-Nov-2007 4:37:47 AM com.jmex.audio.openal.OpenALStreamedAudioPlayer playInNewThread
SEVERE: Audio Error!
org.lwjgl.openal.OpenALException: OpenAL error: Invalid Name parameter (40961)
at org.lwjgl.openal.Util.checkALError(Util.java:64)
at org.lwjgl.openal.AL10.alSourcePlay(AL10.java:934)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.playStream(OpenALStreamedAudioPlayer.java:199)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.playInNewThread(OpenALStreamedAudioPlayer.java:214)
at com.jmex.audio.openal.OpenALStreamedAudioPlayer.play(OpenALStreamedAudioPlayer.java:166)
at com.jmex.audio.AudioTrack.play(AudioTrack.java:113)
at com.jmex.audio.MusicTrackQueue.play(MusicTrackQueue.java:144)
at com.jmex.audio.MusicTrackQueue.setCurrentTrack(MusicTrackQueue.java:212)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:232)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.MusicTrackQueue.update(MusicTrackQueue.java:233)
at com.jmex.audio.openal.OpenALSystem.update(OpenALSystem.java:124)
at com.jmex.game.StandardGame.update(StandardGame.java:305)
at com.jmex.game.StandardGame.run(StandardGame.java:188)
at java.lang.Thread.run(Thread.java:619)

Thanx!

It works now. I owe you one :wink:

Try this:


((StreamedAudioPlayer)track.getPlayer()).getStream().setLength(length);


I forgot to mention that the problem occurs only when tracks are created with STREAM mode set to true.



However steam = true is the only viable option for queuing tracks. Because with stream mode set to false, the adio system loads all the nine tracks into the memory in decoded format size of an uncompressed wav. It's like loading a content of the whole CD into RAM + the decoding time.

I've done some more testing. The bug only manifests itself when playing a queue of multiple tracks (2 and more) in stream mode from a jar.

Single stream track from a jar works. Multiple stream tracks from a filesystem also work.

Thanks for reporting this, I'll have a look when I get back to work Monday.

Thanx! Here is a testcase to ease your job. You will need to find a couple of ogg tracks, package them and change the tracksDir and track names.



import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.jme.util.resource.ResourceLocatorTool;
import com.jme.util.resource.SimpleResourceLocator;
import com.jmex.audio.AudioSystem;
import com.jmex.audio.AudioTrack;
import com.jmex.audio.AudioTrack.TrackType;
import com.jmex.audio.MusicTrackQueue.RepeatType;
import com.pxc.xshift.GameLauncher;

public class TestMusicQueue {

   public static void main(String[] args) throws Exception {
      String tracksDir = "org/lex/test/";
      
      List<String> tracks = new ArrayList<String>();
      tracks.add("track1.ogg");
      tracks.add("track2.ogg");
      
      Collections.shuffle(tracks);
      
      try {
         ResourceLocatorTool.addResourceLocator(
            ResourceLocatorTool.TYPE_AUDIO,
            new SimpleResourceLocator(TestMusicQueue.class
                   .getClassLoader().getResource(tracksDir + tracks.get(0))));
      } catch (URISyntaxException e) {
         e.printStackTrace();
      }
      
      AudioSystem audio = AudioSystem.getSystem();
      
      final List<AudioTrack> loaded = new ArrayList<AudioTrack>();
      
      for (String track : tracks) {
         AudioTrack at = audio.createAudioTrack(track, true);
           at.setType(TrackType.MUSIC);
           at.setRelative(true);
           at.setTargetVolume(0.7f);
           at.setLooping(false);
          
           loaded.add(at);
      }

      for (AudioTrack at : loaded) {
         audio.getMusicQueue().addTrack(at);
      }
       
        audio.getMusicQueue().setRepeatType(RepeatType.ALL);
        audio.getMusicQueue().setCrossfadeinTime(2.5f);
        audio.getMusicQueue().setCrossfadeoutTime(2.5f);
        audio.getMusicQueue().play();
               
          AudioSystem.getSystem().update();
          Thread.sleep(10000);
   }
}

Any luck replicating the problem?

Have not tried yet, tbh.  Not to be too lazy, but if you emailed me a jar to test with I could launch into testing a lot sooner…  :expressionless:

Sure, pm me your email.

Nevermind I found it… I guess I'm the only one who hides his email :smiley:

The main trouble you are running into is the crossfade.  Because you are streaming, the duration of the track is unknown.  This hits a bug in the crossfade logic since it assumes a valid duration.  I'll patch that up soon here (today).  Unfortunately, this fix will not make crossfade work with streaming.  If anyone has a good way to grab the track length from an ogg stream, please let me know.

fyi, I've also exposed access to setting the stream length manually, so if you already know the length of a stream, you can set it in your game and the cross fade should work fine.  Hopefully a more automatic method for streamed sources will be implemented in the future.  From what I've read, you have to skip ahead to the end of the stream, then restart from the beginning, etc.

(in cvs)

I'm testing this right now.



One thing I can note right away is: the queue worked when using streamed tracks from the filesystem. And the bug would only show when streaming from a jar.

Yeah, which makes sense.

fyi, I've also exposed access to setting the stream length manually, so if you already know the length of a stream, you can set it in your game and the cross fade should work fine.  Hopefully a more automatic method for streamed sources will be implemented in the future.  From what I've read, you have to skip ahead to the end of the stream, then restart from the beginning, etc.


I've look at all the methods in AudioTrack and AudioTrack.getPlayer(), but I can't find how to set the stream length manually. Could you point me to the right direction?