[committed] Sound Memory Leak and OpenAL exception patch

  1. memory leak

       I found memory problem while using jme sound streaming.

       http://www.jmonkeyengine.com/jmeforum/index.php?topic=10835.0

       Maybe we could fix it by cleaning up OpenAL buffers but I couldn't find the solution.

       I suggest another approach which reuses OpenAL buffers.



       In this approach, we should call AudioTrack.release() when the track is not used anymore. (for streaming source)

       It can be done by TrackStateListener


  2. OpenALExceptions

       Current implementation uses same pool for memory source and stream source.

       So when we use memory player and stream player at once it throws OpenALException.

       I split it with two source pool.



    patch file

    http://mulova.tistory.com/attachment/cfile5.uf@165F15234A08C48E267F4E.patch



    Test Code (without sound file)


package test;

import java.net.URL;

import com.jme.app.SimpleGame;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jmex.audio.AudioSystem;
import com.jmex.audio.AudioTrack;
import com.jmex.audio.AudioTrack.TrackType;

public class TestOggStreaming extends SimpleGame {
   private static final String MEMORY = "Memory";
   private static final String   STREAM_STOP   = "Stream Stop";
   private static final String   STREAM   = "Stream";
   private int c;
   private AudioSystem audio;
   private AudioTrack streamTrack;
   private String[] paths;
   
   @Override
   protected void simpleInitGame() {
      paths = new String[10];
      for (int i = 0; i < paths.length; i++) {
         paths[i] = "/test/"+i+").ogg";
      }
      
      KeyBindingManager.getKeyBindingManager().add(STREAM_STOP, KeyInput.KEY_1);
      KeyBindingManager.getKeyBindingManager().add(STREAM, KeyInput.KEY_2);
      KeyBindingManager.getKeyBindingManager().add(MEMORY, KeyInput.KEY_3);
        audio = AudioSystem.getSystem();
   }

   @Override
   protected void simpleUpdate() {
      if(KeyBindingManager.getKeyBindingManager().isValidCommand(STREAM_STOP, false)) {
         play(true, true);
      } else if(KeyBindingManager.getKeyBindingManager().isValidCommand(STREAM, false)) {
            play(true, false);
      } else if(KeyBindingManager.getKeyBindingManager().isValidCommand(MEMORY, false)) {
         play(false, false);
      }
      
      audio.update();
   }

   private void play(boolean stream, boolean stop) {
      if (c >= paths.length) {
         c = 0;
      }
      URL url = TestOggStreaming.class.getResource(paths[c]);
      if (stream) {
         if (streamTrack != null && stop) {
            streamTrack.stop();
            streamTrack.release();
         }
         streamTrack = getSFX(url, stream);
         streamTrack.play();
      } else {
         AudioTrack memoryTrack = getSFX(url, stream);
         memoryTrack.play();
         
      }
      c++;
   }
   
    private AudioTrack getSFX(URL resource, boolean stream) {
       audio = AudioSystem.getSystem();
//       final boolean stream = FastMath.rand.nextBoolean();
        AudioTrack sound = audio.createAudioTrack(resource, stream);
        sound.setType(TrackType.MUSIC);
        sound.setVolume(1f);
        sound.setRelative(false);
        sound.setLooping(false);
        return sound;
    }

   public static void main(String[] args) {
      TestOggStreaming app = new TestOggStreaming();
      app.start();
   }
}