Playing music in java

Hey guys,
im currently playing music like this:

//try
File fland = new File(game.getRoot()+"./sounds/land.wav");
Uri uri = fland.toURI();
AudioClip land = Applet.newAudioClip(uri.toURL());
//catch

land.play();

but when many audioclips come after another the game lags and the sound gets messy.

is it the right way to do it with audioclips or is there a better method?

Moep

Try using the Java Sound API in javax.sound.sampled


Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(getClass().getResource("path/to/sound/file.wav")));
clip.start();

The Clip interface:
http://ra4king.is-a-geek.net/javadocs/javax/sound/sampled/Clip.html

Thx 4 the tip but i keep getting a NullPointerException and i dont know why:

			jump = AudioSystem.getClip();
			File f = new File(myRoot + "./sounds/jump.wav");
			jump.open(AudioSystem.getAudioInputStream(getClass().getResource(myRoot + "./sounds/jump.wav")));

The exception is thrown at the third line.
The second line is just for testing and it doesnt throw an exception.

Thx 4 help

Moep

Try separating those calls on separate lines and then tell me which line you get the exception at.

dont know if i understood it right, but if i write it like that:

			jump.open(
					AudioSystem.
					getAudioInputStream(
							getClass().
							getResource(myRoot + "./sounds/jump.wav")));

i get the exception at line 3.

The whole exception message is this:

java.lang.NullPointerException
at com.sun.media.sound.WaveFileReader.getAudioInputStream(Unknown Source)
at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
at MusicList.init(MusicList.java:32)
at MusicList.(MusicList.java:21)
at GameFrame.(GameFrame.java:82)
at GameApp.main(GameApp.java:7)

Moep

My guess it it’s something simple like your not properly pointing to the file.
Try System.out.println(myRoot + “./sounds/jump.wav”); to see if it’s what you were expecting.
Just creating the File object doesn’t test anything, try calling exists() or canRead() on it.
Why don’t you use pass that file to getAudioInputStream, otherwise your test is irrelevant.

Going back to your original post, you say there are problems with lag. Are you running the play command from its own thread? (Answer should be yes.) Are you trying to play the same cue more than once at the same time? That will probably require special handling.

Also, if two cues are recorded “efficiently” (near the loudest volume that doesn’t distort), their combo (both playing at once) could be overdriving your system, and digital distortion is definitely nasty. You might look at setting their volumes to around 50% or somesuch.

[Added as an edit: using File to get a resource doesn’t work so well if you ever intend to ship your app as a jar. I just went through that misunderstanding, myself: http://www.java-gaming.org/index.php/topic,24342.0.html. So, I second the advice from the others here to use the getAudioInputStream method and a relative address. And yes, getting that relative address right can be a pain. An IDE can make it more confusing if you have separate source and class folders.] In my most recent build, I used the file name getAudioInputStream(“sounds/jump.wav”) and placed the “sounds” folder as a subfolder of the package containing the calling code.]

File doesn’t throw an exception if the path isn’t correct. It is better to check if the URL returned by getResource(String) is null. That’s why you get a NullPointerException, because it returns null and getAudioInputStream throws the NPE.

Your link also doesn’t look correct at all. You can’t have a period in the middle of a path. You also do not need “myRoot” because you can also pass a relative path, the path being relative to you current working directory.

Ok now i found the problem.

			URL url = getClass().getResource(".");
			System.out.println(url.getPath());

the output is:
/C:/Users/Wolfe/Eclipse/Game%200.15/bin/

The sounds folder is in the Game 0.15 folder so i have to move up one folder via relative path.
Ive googled for 1/2 hour now and i cant seem to find it.
How is it done?

ps: its really annoying that “…” doesnt work-.-

Moep

You go up folders by using “…” (2 periods); “.” (1 period) signifies the current directory

			System.out.println(getClass().getResource(".").getPath());
			System.out.println(getClass().getResource("./Level.class").getPath());
			System.out.println(getClass().getResource("../sounds/jump.wav").getPath());
			System.out.println(getClass().getResource(".././sounds/jump.wav").getPath());
			System.out.println(getClass().getResource("..").getPath());

only line 1 and 2 work.
what am i doing wrong?

Moep

You can only use getResource() when loading from the classloader. Since your sound folder is not on the classpath, you can’t load from there via getResource().

Usually you solve this by having a folder structure like this in your project:


src/
   [your projects classes]
resources/
   sound/
      [your projects sounds]
   images/
      [your projects images]
   whatever/

and add the resources folder to your classpath, so you can use


getClass().getResource("/sounds/jump.wav")

Notice theat the pathname now is starting with a slash, so its no relative path to your class but absolute from the root of all folders and jars on the classpath. This also means you can zip your resources into the game jar or a separate resources jar when shipping your game.

ok i made my folderstructure like you suggested.
thx 4 everyones help!

but as soon as this works the next question pops up:

now when i e.g. jump the sound only plays the first time.
what do i have to do so the sound plays every time?

i tried something like:

		if(jump.isRunning()) //jump.isActive()
		{
			jump.stop();
		}
		jump.start();

but it wont work.

anybody got ideas?

You have to set the position back at 0:


jump.setMicrosecondPosition(0);

Ok thank you its working now.

Glad to help :slight_smile: