I'm trying to play sound in Java but it doesn't work and I got error message.
Here is my Code
public class PlaySoundClip extends JFrame {
public PlaySoundClip() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Test Sound Clip");
this.setSize(300, 200);
this.setVisible(true);
try {
URL url = this.getClass().getClassLoader().getResource("click.wav");
AudioInputStream audioIn = AudioSystem.getAudioInputStream(url);//Line 27
// Get a sound clip resource.
Clip clip = AudioSystem.getClip();
// Open audio clip and load samples from the audio input stream.
clip.open(audioIn);
clip.start();
clip.loop(Clip.LOOP_CONTINUOUSLY); // repeat forever
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new PlaySoundClip();//Line 44
}
}
And I get this error message then I'm not here any sound! How to fix this problem?
Exception in thread "main" java.lang.NullPointerException
at com.sun.media.sound.StandardMidiFileReader.getSequence(StandardMidiFileReader.java:205)
at javax.sound.midi.MidiSystem.getSequence(MidiSystem.java:836)
at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(SoftMidiAudioFileReader.java:174)
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1145)
at playsoundclip.PlaySoundClip.<init>(PlaySoundClip.java:27)
at playsoundclip.PlaySoundClip.main(PlaySoundClip.java:44)
Reference from Playing Sound.
Something is wrong with click.wav, it was not found on the classpath, so url became null, hence the NullPointerException.
You should put the click.wav on your classpath, so the program will find it. The most straightforward way is putting into the root folder of the jar file.
Most likely in your build phase there is a list of "resources" that are copied from source tree to the output compiled classes. Usually it is a string of regular expressions like ".txt;.json;…" In your case you need to add ".wav" to it or copy file by hand to the compiler output location.
Most IDEs (Eclipse|IteliJ IDEA) and some ant build scripts have provision for resource copying.
Related
I use Java Media Framework 2.1.1 for playing sounds in my application. It works fine from IDE but once I make jar package. The Player objects cannot be initialized with exception:
javax.media.NoPlayerException: Cannot find a Player for :jar:file:...
I create players using javax.media.Manager.createPlayer(URL sourceURL) method. I suspect that the URL from jar is causing the problems.
Is there an alternative way how to construct the player with files from jar?
Code:
public SoundPlayer() {
urlExplosion = ResourceLoader.getInstance().getSoundResourceUrl(SoundResource.EXPLOSION);
urlTick = ResourceLoader.getInstance().getSoundResourceUrl(SoundResource.TICK);
urlWin = ResourceLoader.getInstance().getSoundResourceUrl(SoundResource.WIN);
}
public void initialize() throws ResourceLoadingException{
try {
explosionPlayer = Manager.createPlayer(urlExplosion);
explosionPlayer.realize();
tickPlayer = Manager.createPlayer(urlTick);
tickPlayer.realize();
winPlayer = Manager.createPlayer(urlWin);
winPlayer.realize();
} catch (NoPlayerException e) {
throw new ResourceLoadingException("Could not initialize the sound player",e);
} catch (IOException e) {
throw new ResourceLoadingException("Could not initialize the sound player",e);
}
isInitialized = true;
}
Note: the URLs are no null during runtime.
Error when run from command line: java -jar minesweeper.jar
Caused by: javax.media.NoPlayerException: Cannot find a Player for :jar:file:/path/to/app/minesweeper.jar!/my/package/minesweeper/gui/explosion.wav
This snippet of code is supposed to play a short beep after the method is executed. Which it is doing inside netbeans. But when I use netbeans to build an executable Jar file it gives me a java.Lang.NullPointerException. Any ideas?
public void playSound() {
try {
AudioStream as = new AudioStream(ClassLoader.getSystemClassLoader().getResourceAsStream("resources\\beep-2.wav"));
AudioPlayer.player.start(as);
} catch (Exception e) {
e.printStackTrace();
}
}
Use a forward slash; backslash is Windows-specific and will only work when you're using an exploded layout.
change the code into the following it will surely work..
public void playSound() {
try {
AudioStream as = AudioSystem.getAudioInputStream(this.getClass().getResource("resources\\beep-2.wav"));
Clip clip = AudioSystem.getClip();
clip.open(as);
clip.start( );
}
catch (Exception e) {
e.printStackTrace();
}
}
It is not able to find your audio file. Make a resources folder in the directory where you jar is kept and keep the audio file in that folder.
Alternatively you can give an exact path in your program. e.g. C:\resources\beep-2.wav
In my application I was trying to save a BufferedImage to a PNG file using ImageIO. The file is chosen by the user so I need to react to errors that might happend (e.g. user tries to save in a location he has no write permission for). However I am unable to catch the IOException that occurs.
The following code shows the problem. Trying to save to "/foo" should throw an exception for most users on *nix systems, since they do not have write permission in the root directory.
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class IOTest {
public static void main(String[] args) {
BufferedImage img = new BufferedImage(640, 480,
BufferedImage.TYPE_INT_RGB);
try {
File f = new File("/foo");
ImageIO.write(img, "png", f);
} catch (IOException e) {
System.out.println("Caught IOException!");
}
}
}
However, the exception is not caught. Output:
java.io.FileNotFoundException: /foo (Permission denied)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:233)
at javax.imageio.stream.FileImageOutputStream.<init>(FileImageOutputStream.java:69)
at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:55)
at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:419)
at javax.imageio.ImageIO.write(ImageIO.java:1530)
at IOTest.main(IOTest.java:16)
Exception in thread "main" java.lang.NullPointerException
at javax.imageio.ImageIO.write(ImageIO.java:1538)
at IOTest.main(IOTest.java:16)
Note that FileNotFoundException is a subclass of IOException so it should get caught. A second catch block did not help either:
catch (FileNotFoundException e) {
System.out.println("Caught FileNotFoundException!");
} catch (IOException e) {
System.out.println("Caught IOException!");
}
What am I doing wrong?
It stems from the details of ImageIO implementation. You will circumvent the problem if you don't pass the File instance to ImageIO.write, but first try to open a FileOutputStream yourself and pass that to write.
This is a more precise analysis of what happens in ImageIO.write. Line 1530:
stream = createImageOutputStream(output);
Line 1538:
stream.close();
And if you take a look at the implementation of createImageOutputStream, you'll see several code paths that return null.
It looks like the ImageIO.write method prints the IOException but really doesn't handle it and ends with a NullPointerException. In this specific case of a buggy library, maybe you should catch any RuntimeException...
Of course it will be better to test before if the directory exists and is writable.
It seems that ImageIO.write() wraps the FileNotFoundException into a NullPointerException.
You should catch NullPointerException, or better check file existence before invoking ImageIO.write().
By the looks of it the FileNotFoundException is being handled within javax.imageio.ImageIO.write and that failure is causing a null pointer exception. Try to check the file permissions before you try saving it!
Ok, so I am making a game and the music changes when you are in different regions or if there is an interruption, like with an AI.
So I have JUST learned how to make music showup in my program, and now I am trying to make it stop, but I am unsure how to, below is a snippet of code where the music plays and then I try to overwite it with new music when an action occurs.
public static void songs(String word) {
String temp = word;
if (temp.equals("start")) {
try {
try {
blah = new FileInputStream("C:/Users/Austin/Desktop/Storage/programimages/game/battle.wav");
} catch (Throwable e) {
e.printStackTrace();
}
AudioStream as = new AudioStream(blah);
AudioPlayer.player.start(as);
System.out.println("going");
} catch (IOException e) {
System.err.println(e);
}
}
if (temp.equals("stop")) {
try {
try {
blah = new FileInputStream("C:/Users/Austin/Desktop/Storage/programimages/game/silence.wav");
} catch (Throwable e) {
e.printStackTrace();
}
AudioStream as = new AudioStream(blah);
AudioPlayer.player.stop(as);
System.out.println("stopping");
} catch (IOException e) {
System.err.println(e);
}
}
}
This is the only method I have been able to find that has the music play, but if you guys have any other suggestions please let me know.
Again, I want to have sound affects and music going, and right now all that happens is one song will play, and it will not stop under any circumstance until it hits the very end of its length. I want to be able to stop songs whenever a new one should come on, and also allow sound affects to pop up.
Thanks!
(since I am stuck on this and need an answer now I will probably repost on one or two more java sites so I can get a response ASAP, thank you though!!!!)
EDITED CODE: (still does not stop the current stream, any more suggestions appreciated)
public static void songs(String word) throws IOException {
String temp = word;
if (temp.equals("go")) {
try {
blah = new FileInputStream("C:/Users/Austin/Desktop/Storage/programimages/game/battle.wav");
} catch (Throwable e) {
e.printStackTrace();
}
AudioStream as = new AudioStream(blah);
AudioPlayer.player.start(as);
System.out.println("going");
}
if (temp.equals("stop")) {
//don't try and do things with a null object!
if (as != null) {
AudioPlayer.player.stop(as);
System.out.println("stopping1");
}
System.out.println("stopping2");
AudioPlayer.player.stop(as);
}
}
Currently you're creating a new AudioStream in your stop branch and calling the stop method using this. This is a different object to the one that is currently playing. Try making the AudioStream a class variable, and calling stop on that instead.
EDIT: at the top of the class containing your code...
class YourClass {
//the class member variable
private AudioStream as;
//[etc...]
In your start branch:
// 'as' has already been defined above
as = new AudioStream(blah);
AudioPlayer.player.start(as);
System.out.println("going");
In your stop branch:
try
{
//don't try and do things with a null object!
if (as != null)
{
AudioPlayer.player.stop(as);
}
System.out.println("stopping");
}
catch (IOException e)
{
System.err.println(e);
}
You may have trouble with the static identifier on your method - if you're calling this from within an instantiated class you don't need this.
I can't even access these sun.audio Objects on my Eclipse IDE--I know they are in rt.jar, but there is header info about them being proprietary and such.
Can the Java Sound library (javax.sound.sampled) handle what you want to do? Both Clip and SourceDataLine allow one to stop playback. That is a more usual way of playing sound, if you want to use native Java.
Playback into is here:
http://docs.oracle.com/javase/tutorial/sound/playing.html
But the documentation, overall, is not exactly rich with examples. There's example code at this site
http://www.jsresources.org/
and plenty of people here who could help if you run into problems with the native Java approach.
The following is a link to the most likely explanation I've seen, but I still have questions.
How can I play sound in Java?
I'll quote the code here:
public static synchronized void playSound(final String url) {
new Thread(new Runnable() {
public void run() {
try {
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(Main.class.getResourceAsStream("/path/to/sounds/" + url));
clip.open(inputStream);
clip.start();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}).start();
}
Does this work in an application, as opposed to an Applet?
The method Main.class.getResourceAsStream() seems to require import com.sun.tools.apt.Main; but I cannot find documentation for that, and I don't know what it does. For instance, is "/path/to/sounds/" absolute, or relative, and if the latter, relative to where?
I've spent many hours now trying to play a simple sound effect. It's unbelievable how difficult it is. I hope that the above code can be made to work. Thanks for any help.
Chap
That should work in an application.
That line of code is most likely referencing the class that method is in. So that method was originally in class Main, if you put the method in class FooBar, you should change it to FooBar.class.getResourceAsStream().
It is a relative path. It will look for the resource outside of every package. Example: Let's say the class that's running this piece of code is located at C:\Users\Jeffrey\bin\foo\bar\SoundPlayer.class and the class is in package foo.bar. This means that the ClassLoader will look for the resources inside the C:\Users\Jeffrey\bin\ folder. (In your case, it will look for the resource at C:\Users\Jeffrey\bin\path\to\sounds\ + url)
I always loaded sounds like this:
Clip sound = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
sound.open(AudioSystem.getAudioInputStream(file));
but your method should also work.
Does this work in an application, as opposed to an Applet?
It works in either.
The method Main.class.getResourceAsStream() seems to require import com.sun.tools.apt.Main;
Where did you get that idea? I've made plenty of sound examples, and never heard of that class that you should not be using.
..but I cannot find documentation for that,..
No, the com.sun classes are not only undocumented, but might change in the next micro-version.
..and I don't know what it does. For instance, is "/path/to/sounds/" absolute, or relative, and if the latter, relative to where?
It is relative to the root of the class-path.
..It's unbelievable how difficult it is.
Media handling in general, is tricky.
BTW - I'm not much impressed with the code on the linked thread. The Thread wrapper is unnecessary, as mentioned in several of the comments, even for playing multiple Clip instances simultaneously.
Instead see this code that I (wrote &) personally recommend.
Although I drew heavily from #Andrew's code, I did have to make some tweaks here and there. The following is a demo of my solution, complete except for a sample .wav file.
// Developed in Eclipse, YMMV regarding resource location.
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
class ClipPlayer {
public static void main(String[] args) {
// First, instantiate ourselves so we can call demoSam which
// needs to be able to do a wait().
ClipPlayer cp = new ClipPlayer();
// Now run the actual demo
cp.demoSam();
}
private void demoSam() {
/**
* Construct a Sam, capable of playing the "Chook.wav", a 0.1 sec sound.
* NOTE: it's very tricky debugging an incorrectly-located
* resource file, and I'm unable to give a general rule
* here. But in this example, Chook.wav is expected to be in the same
* directory as the .class file, and there is no surrounding
* package (i.e. we're taking the default package name). If you
* are using a package, you may have to write "myPackage/Chook.wav"
* instead.
*/
Sam sam;
try {
sam = new Sam("Chook.wav"); // or whatever, but it has to be .wav
}
catch (Exception e) {
say("Exception thrown by Sam: " + e.getMessage());
System.exit(1); // scoot
return; // get rid of warning about sam possib not init'd
}
int countDown = 20;
do {
say("Doing something requiring accompanying sound effect...");
try {
sam.playIt();
}
catch (Exception e) {
say("Caught exception from playIt: " + e.getMessage());
System.exit(1);
}
// Now wait a human-scale duration, like 1/8 second. In
// practice we may be processing, since the sound is playing
// asynchronously.
synchronized (this) {
try {
wait(125); // wait 1/8 sec
}
catch (Exception e2) {
say("huh?");
}
}
} while (--countDown > 0);
}
/**
* 'Sam' is a class that implements one method, playIt(), that simply
* plays the .wav file clip it was instantiated with. Just using an
* inner class here for simplicity of demo.
*/
final class Sam {
AudioInputStream ais;
Clip clip;
/**
* Constructor: prepare clip to be played. Do as much here as
* possible, to minimize the overhead of playing the clip,
* since I want to call the play() method 5-10 times a second.
*/
Sam(String clipName) throws Exception {
// Resource is in same directory as this source code.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource(clipName);
ais = AudioSystem.getAudioInputStream(url);
clip = AudioSystem.getClip();
clip.open(ais);
}
/**
* playIt(): Start the clip playing once, asynchronously, and exit.
*/
public void playIt() throws Exception {
clip.setFramePosition(0); // Must always rewind!
clip.loop(0);
clip.start();
}
}
private static void say(String s) {
System.out.println(s);
}
}