Whar be my problem? (Song not freeing/stopping)

Started by Overkill, June 06, 2006, 00:22:09

Previous topic - Next topic

Overkill

Yes.... so, for some reason unknown to me, my Music class instances fail to stop or free the song assigned to them. As a result, songs are able to overlap, even if I free the previous song from an object before reassigning, like so:
if (song != null)
		{
			song.Free();
		}
		song = new Music(map.musicFilename);
		song.Play();


The following code is executed upon initialization of my program.
FMOD.create();
		FSound.FSOUND_SetMixer(FSound.FSOUND_MIXER_QUALITY_FPU);
		FSound.FSOUND_Init(48000, 64, FSound.FSOUND_INIT_USEDEFAULTMIDISYNTH);


The following is my code for my Music wrapper.
package trouser;

import org.lwjgl.fmod3.*;

public class Music
{
	public static final int NONE = 0;
	public static final int MODULE = 1;
	public static final int STREAM = 2;

	public int musicType;
	public FSoundStream stream;
	public int streamChannel;
	public FMusicModule mod;
	public Music(String filename)
	{
		if (Helper.getExtension(filename).equalsIgnoreCase("mp3")
				|| Helper.getExtension(filename).equalsIgnoreCase("mpeg3")
				|| Helper.getExtension(filename).equalsIgnoreCase("ogg"))
		{
			this.musicType = STREAM;
			this.stream = FSound.FSOUND_Stream_Open(filename, FSound.FSOUND_LOOP_NORMAL, 0, 0);
			if (stream == null)
			{
				this.musicType = NONE;
				System.out.println("Song \"" + filename + "\" could not be loaded.");
			}
		}
		else
		{
			this.musicType = MODULE;
			this.mod = FMusic.FMUSIC_LoadSong(filename);
			if (this.mod == null)
			{
				this.musicType = NONE;
				System.out.println("Song \"" + filename + "\" could not be loaded.");
			}
			else
			{
				FMusic.FMUSIC_SetLooping(this.mod, true);
			}
		}
	}
	
	public void Play()
	{
		if (this.musicType == NONE) return;
		else if (this.musicType == STREAM)
		{
			streamChannel = FSound.FSOUND_Stream_Play(FSound.FSOUND_FREE, this.stream);
			return;
		}
		else if (this.musicType == MODULE)
		{
			FMusic.FMUSIC_PlaySong(this.mod);
			return;
		}
	}
	
	public void SetVolume(int volume)
	{
		if (this.musicType == NONE) return;
		else if (this.musicType == STREAM)
		{
			FSound.FSOUND_SetVolume(this.streamChannel, volume * 256 / 100);
			return;
		}
		else if (this.musicType == MODULE)
		{
			FMusic.FMUSIC_SetMasterVolume(this.mod, volume * 256 / 100);
			return;
		}
	}
	
	public void Stop()
	{
		if (this.musicType == NONE) return;
		else if (this.musicType == STREAM)
		{
			FSound.FSOUND_Stream_Stop(this.stream);
			return;
		}
		else if (this.musicType == MODULE)
		{
			FMusic.FMUSIC_StopSong(this.mod);
			return;
		}
	}
	
	public void Free()
	{
		this.Stop();
		if (this.musicType == NONE) return;
		else if (this.musicType == STREAM)
		{
			FSound.FSOUND_Stream_Close(this.stream);
			this.stream = null;
			this.musicType = NONE;
			return;
		}
		else if (this.musicType == MODULE)
		{
			FMusic.FMUSIC_FreeSong(this.mod);
			this.mod = null;
			this.musicType = NONE;
			return;
		}
	}
	
}


Any help is much appreciated, I'm sure I must be overlooking a small detail.

Overkill

Something even more scary! It says the song has stopped, after I stop it when I check with FMusic.FMUSIC_IsPlaying(this.mod). However, the song still plays afterward. Is this the result of garbage collection lameness?

Matzon

must be something in your code... this simple test based on your code works as expected (except a native crash on exit, which I am investigating atm):
package org.lwjgl.test.fmod3;
import org.lwjgl.fmod3.*;

public class MusicTest
{
   public static final int NONE = 0;
   public static final int MODULE = 1;
   public static final int STREAM = 2;

   public int musicType;
   public FSoundStream stream;
   public int streamChannel;
   public FMusicModule mod;
   public MusicTest(String filename)
   {
      if (filename.endsWith("mp3")
            || filename.endsWith("mpeg3")
            || filename.endsWith("ogg"))
      {
         this.musicType = STREAM;
         this.stream = FSound.FSOUND_Stream_Open(filename, FSound.FSOUND_LOOP_NORMAL, 0, 0);
         if (stream == null)
         {
            this.musicType = NONE;
            System.out.println("Song \"" + filename + "\" could not be loaded.");
         }
      }
      else
      {
         this.musicType = MODULE;
         this.mod = FMusic.FMUSIC_LoadSong(filename);
         if (this.mod == null)
         {
            this.musicType = NONE;
            System.out.println("Song \"" + filename + "\" could not be loaded.");
         }
         else
         {
            FMusic.FMUSIC_SetLooping(this.mod, true);
         }
      }
   }
   
   public void Play()
   {
      if (this.musicType == NONE) return;
      else if (this.musicType == STREAM)
      {
         streamChannel = FSound.FSOUND_Stream_Play(FSound.FSOUND_FREE, this.stream);
         return;
      }
      else if (this.musicType == MODULE)
      {
         FMusic.FMUSIC_PlaySong(this.mod);
         return;
      }
   }
   
   public void SetVolume(int volume)
   {
      if (this.musicType == NONE) return;
      else if (this.musicType == STREAM)
      {
         FSound.FSOUND_SetVolume(this.streamChannel, volume * 256 / 100);
         return;
      }
      else if (this.musicType == MODULE)
      {
         FMusic.FMUSIC_SetMasterVolume(this.mod, volume * 256 / 100);
         return;
      }
   }
   
   public void Stop()
   {
      if (this.musicType == NONE) return;
      else if (this.musicType == STREAM)
      {
         FSound.FSOUND_Stream_Stop(this.stream);
         return;
      }
      else if (this.musicType == MODULE)
      {
         FMusic.FMUSIC_StopSong(this.mod);
         return;
      }
   }
   
   public void Free()
   {
      this.Stop();
      if (this.musicType == NONE) return;
      else if (this.musicType == STREAM)
      {
         FSound.FSOUND_Stream_Close(this.stream);
         this.stream = null;
         this.musicType = NONE;
         return;
      }
      else if (this.musicType == MODULE)
      {
         FMusic.FMUSIC_FreeSong(this.mod);
         this.mod = null;
         this.musicType = NONE;
         return;
      }
   }
   
   public static void main(String[] args) {
	   try {
		   FMOD.create();
		   FSound.FSOUND_SetMixer(FSound.FSOUND_MIXER_QUALITY_FPU);
		   FSound.FSOUND_Init(48000, 64, FSound.FSOUND_INIT_USEDEFAULTMIDISYNTH);
	   } catch (Exception e) {
		e.printStackTrace();
	   }
	   
	   
	   MusicTest mt = new MusicTest("res/phero.mp3");
	   System.out.println("loading mp3");
	   mt.Play();
	   System.out.println("play mp3");
	   
	   try {
		   System.out.println("sleep");
		   Thread.sleep(5000);
	   } catch (Exception e) {
		e.printStackTrace();
	   }
	   
	   System.out.println("free");
	   mt.Free();

	   try {
		   System.out.println("enjoy the silence *umpti*");
		   Thread.sleep(5000);
	   } catch (Exception e) {
		   e.printStackTrace();
	   }
	   
	   mt = new MusicTest("res/phero2.ogg");
	   System.out.println("loading ogg");
	   mt.Play();	   
	   System.out.println("play ogg");

	   try {
		   System.out.println("sleep");
		   Thread.sleep(5000);
	   } catch (Exception e) {
		   e.printStackTrace();
	   }
	   
	   System.out.println("destroy");
	   FMOD.destroy();	   
   }
   
}

Matzon

hmm needed a FSound.FSOUND_Close(); else you'd get a VM crash. Updating code to always call:
FSound.FSOUND_Close();
FMusic.FMUSIC_StopAllSongs();
on FMOD.destroy();

Overkill

Actually, I do that on my end. I just figured that was more of a given that you need to deinit/destroy everything properly at the end of the program.

Also, seems that simply moving a static song variable into the music class rather than an external class, and now it frees things properly. So it must have been garbage collection oddness. The reason why is likely related to the following fact: the class that specified the song variable also created a Groovy script engine instance (which is what I use for my game events). And from what I can tell it uses the classloader from the class that creates it. Or something like that.

Anyway, somehow it was fixed. It's probably better that I put static song related stuff in the Music class anyways ;__;