in a recent discussion on StackOverflow I was trying to resolve an imageicon issue that didn't display images after compilation, only when ran in eclipse. This problem was solved by changing the location of my resources folder from my project folder to the src folder. I was also taught to get my resources with the following code:
ImageIcon img = new ImageIcon(getClass().getResource("/resources/picture.jpg"));
Without looking at how I had coded my audio method, I asked if the method of putting resources inside the src folder was the same for all types of resources, in which I was told, pretty much. Anyway, now I have got to my audio code, I am a little unsure of how to implement the "getClass().getResource()" line into it.
As it stands my audio works as intended, when ran in eclipse, but when compiled it has the same issue as the images used too. I know that the problem is very similar, but I believe it is a matter of coding, or lack of it. Any pointers, or examples will be greatly appreciated. Thanks.
SOURCE CODE:
public static void menusong(){
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("sounds/dre2.wav"));
bgclip = AudioSystem.getClip();
bgclip.open(ais);
bgclip.start();
try {
Thread.sleep(33000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
Right, got it! Instead of this:
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("sounds/dre2.wav"));
I changed it to this:
AudioInputStream ais = AudioSystem.getAudioInputStream(classname.class.getClass().getResource("sounds/dre2.wav"));
All is now working beautifully when compiled, thanks anyway for the help, much appreciated.
Related
Apologies if this has been asked before, but I was unable to find an answer that worked for us. I am also a beginner so please bear with me.
Essentially, after jarring our code the audio stopped working.
clip = AudioSystem.getClip();
File file = new File(musicLocation);
clip.open(AudioSystem.getAudioInputStream(file.getAbsoluteFile()));
clip.start();
I have tried using getResourceAsStream and getResource as apparently files don't work properly when jarred but it still does not work even in Intellij.
My code is located in the src folder and the music location is being passed to the code like so:
filepath = "src/Images/music/click.wav";
musicObject.playMusic(filepath);
Images are working properly in the jar file.
Edit: it appear that the jar file is unable to take the audio files, which are within another folder that is otherwise being accessed, because the file size of the jar does not change after the deletion of the .wav files.
Edit 2:
public class Music {
Clip loop;
void loopMusic(String musicLocation) {
try {
loop = AudioSystem.getClip();
InputStream is = getClass().getResourceAsStream(musicLocation);
AudioInputStream audioS = AudioSystem.getAudioInputStream(is);
loop = AudioSystem.getClip();
loop.open(audioS);
loop.start();
loop.loop(Clip.LOOP_CONTINUOUSLY);
} catch (Exception e) {
System.out.println(e);
}
}
void stopLoop(){
if (loop != null) {
loop.stop();
loop.close();
}
loop=null;
}
}
This is the coe we are attempting to use. The musicLocation String is passed in the format of: /folder/file.wav
After manually putting the .wav files into the jar through winrar, it still is unable to load the music in the jar file.
Edit 3:Attempting to use URL Class, receiving NullPointerException
URL musicLocation = this.getClass().getResource("/Images/music/battle.wav");
AudioInputStream inputStream = AudioSystem.getAudioInputStream(musicLocation);
When passed into the AudioInputStream as a file with the "src" before the location name, it does not pass a null.
Edit 4: Attempting to use URL Class with the file inside of folder in Music class package
URL musicLocation = this.getClass().getResource("audio/battle.wav");
AudioInputStream inputStream = AudioSystem.getAudioInputStream(musicLocation);
With the audio folder above being inside the classes (containing all the .java files) package, this returns a NullPointerException. After adding a "Classes/" to the front, hovering over the string in my IDE allows me to "see" that the file is correctly being sourced if you will but it still returns a NullPointerException to the .wav file.
Edit 5:
Receiving this error after implementing Phil's code
Exception in thread "main" java.lang.ExceptionInInitializerError
at Classes.Frame.<init>(Frame.java:15)
at Classes.GraphicsRunner.main(GraphicsRunner.java:15)
Caused by: java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:222)
at java.desktop/javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1032)
at Classes.Music.<init>(Music.java:16)
at Classes.Panel.<clinit>(Panel.java:24)
... 2 more
Edit 6: Displaying class that resulted in error above
package Classes;
import javax.sound.sampled.*;
import javax.swing.*;
import java.io.*;
import java.net.URL;
public class Music {
Clip clip;
// Constructor, create looping audio resource, hold in memory.
public Music() {
URL url = this.getClass().getResource("audio/battle.wav");
AudioInputStream ais;
try {
ais = AudioSystem.getAudioInputStream(url);
//line 16 above
DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}
}
public void play() {
clip.setFramePosition(0);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
}
Edit 7: Phils identical set of code worked upon moving project to Eclipse. I'm still unsure of why it didn't work in Intellij but my problem was solved nonetheless. Thanks to everyone who offered their help!
The java.io.File object is not a good choice for addressing files that are packed in jars. I don't know the correct technical way to explain this, but in simple language, it can only address files that are in file folders. It has no ability to "see" within jar files.
For this reason, it's more usual to access the file by getting its URL using the Class.getResource method. A URL can identify a file that has been compressed and is located within a jar.
It is also possible to address and load a sound file in a jar using the .getResourceAsStream method. This method returns an InputStream, not a URL. But this is a dicier option. If you look at the API for the overloaded AudioSystem.getAudioInputStream, and compare the versions, you'll see that if the argument is an InputStream, the file will be subjected to tests to determine if "mark" and "reset" are supported. A sizable number of audio files fail these tests. For this reason, it's safer to use the method with a URL argument.
Problems can also arise in how the file name is provide in the getResource method, but usually if the name String works in the DAW it will also work in a jar (assuming you are obtaining a URL and not a File). The specifics about "relative" and "root" addressing aren't the easiest to explain. But we can go there if needed.
EDIT: Code example for troubleshooting.
public class Music {
Clip clip;
// Constructor, create looping audio resource, hold in memory.
public Music() {
URL url = this.getClass().getResource("audio/battle.wav");
AudioInputStream ais;
try {
ais = AudioSystem.getAudioInputStream(url);
DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
clip = (Clip) AudioSystem.getLine(info);
clip.open(ais);
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}
}
public void play() {
clip.setFramePosition(0);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
}
The code assumes the following file folder structure:
/src/.../folderwithMusic/Music
/src/.../folderwithMusic/audio/battle.wav
Note that the file name is case sensitive. A null value for the URL indicates that the file is not at the expected location. First get this working in your IDE, and maybe prefer either your console or File Explorer to verify the file structure and file location.
If you try running the above and have problems, the exact code as entered and stack trace would be helpful.
Okay, so I have a simple program that loads audio files and plays them.
I have this for loading my audio files
Clip c1 = null;
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(songPaths[k + 1]).getAbsoluteFile());
c1 = AudioSystem.getClip();
c1.open(audioInputStream);
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
It runs fine in my intelliJ, and when I look to build artifacts and try to run the jar that's made it fails to load the resources. My songPaths array looks like this:
private final String[] songPaths = {"res/fcpOriginal.wav", "res/fcpRemix.wav",
"res/ibizaOriginal.wav", "res/ibizaRemix.wav",
"res/pohOriginal.wav", "res/pohRemix.wav",
"res/sugarOriginal.wav", "res/sugarRemix.wav",
"res/wavesOriginal.wav", "res/wavesRemix.wav"};
I'm not quite sure what's going on. Any help would be greatly appreciated.
So if I'm understanding your directory hierarchy correctly, you have the following:
src
out/artifacts/nameOfProject_jar.
res
You should put a copy of your res folder in to the nameOfProject_jar folder. Because the working directory for your application is now your nameOfProject_jar folder, so when you are using relative paths like you are, it will look for the res folder in nameOfProject_jar directory instead. :)
I figured it out. FOR ANY FUTURE RESEARCHERS!
I changed
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(songPaths[k + 1]).getAbsoluteFile());
to
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(getClass.getResource(songPaths[k + 1]));
Sound does not play when I run the JAR, but it does when I run it in eclipse.
Here is where I load the clips: (the files are loaded from the directory of the jar, Not from within the jar)
public void init(){
System.out.println("grabbing Music");
String currentDir = new File("").getAbsolutePath();
name=new File(currentDir+"\\music\\").list();
clip=new Clip[name.length];
soundFile=new File[name.length];
for(int x=0;x<name.length;x++){
System.out.println(currentDir+"\\music\\"+name[x]);
try {
soundFile[x]= new File(currentDir+"\\music\\"+name[x]);
AudioInputStream sound = AudioSystem.getAudioInputStream(soundFile[x]);
DataLine.Info info= new DataLine.Info(Clip.class, sound.getFormat());
clip[x] = (Clip) AudioSystem.getLine(info);
clip[x].open(sound);
clip[x].addLineListener(new LineListener(){
public void update(LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
event.getLine().close();
}
}
});
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
}
}
}
I do not get any errors when running it in Eclipse. There should be no possibility of an invalid directory error, so what is wrong?
-When the jar is run in CMD i get no errors nor stacktraces, so it IS loading the files, it just isnt running it when the clip.start() is called. So the way im loading the files in is not compatible with runnable jars.
edit: I feel like I am loading the audio wrong, hence why I pasted the code I used to load the files in. In my searches I haven't seen anyone use File to load in a sound file. Wonder if that is the problem?
-Also switching to embedded resources ALSO does not work.
The reason your sound is not playing because it is most likely not being compiled into your runnable jar and thus cannot be found. The best way to have it compile into a runnable jar is to create a source folder in eclipse, and then add your sound file in there. It will then be compiled into your jar
I struggled with this as well. You need to use
getClass().getSystemResource("pathToResourceFromClass")
For example, if your project structure is like the following:
-ProjectName
-----src
----------SomeClass.java
-----images
----------SomeImage.png
Then from SomeClass.java, you would use
getClass().getSystemResource("images/SomeImage.png")
to obtain the URL object which references that file. You could then pass that URL object to the constructor of ImageIcon if you want.
Note that getClass().getResource() does not work for images or sound files in a jar file!!! I've spent many hours on this, and getResource() does not work. You have to use getSystemResource(..) for resources within a jar file.
Let me know if you have any questions about this. I'd be glad to clarify any confusing points.
I'm trying to load a clip from my JAR file, but it only works in my IDE (NetBeans), and not when I run its JAR executable.
Here's the code I'm using that returns a clip:
public static Clip getClipFromJar(String filePath) {
try {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(FileLoader.class.getResourceAsStream(filePath)));
return clip;
} catch (Exception error) {
System.exit(-1);
return null;
}
}
I'm really stuck, using getResourceAsStream() seemed to work for other things such as images, but it's not working for getting a clip.
Thanks for all the help everyone! The tips I got from you guys are good for programming in general, so thanks! :)
Get the URL , take care of the AudioInputStream and AudioSytem and then return the clip . And the clip can be started like clip.start() after that
try{
URL soundURL = getClass().getResource(filePath);
AudioInputStream AIS = AudioSystem.getAudioInputStream(soundURL);
Clip clip = AudioSystem.getClip();
clip.open(AIS);
return clip;
} catch (Exception ex) {
ex.printStackTrace();
}
Note : I tried this code and it worked properly both in IDE and outside
getResourceAsStream() looks for its resource on the classpath, starting with the location of the class itself -- so if your clip (or whatever resource) is in the same folder as the class, it'll find it there. If it isn't there, you have to make sure you have it in the classpath somewhere, and it sounds like that might be difference between your IDE environment and your program runtime.
Look at the 'filepath' you have also -- if it starts with a slash of course, it is absolute, etc.; I'm assuming you know about the absolute and relative paths.
A suggestion for debugging -- eliminate all the 'stacking' of calls. Make one call to get the stream; make another call to get the audio input stream, and a third to open it. Then you can at least put in trace statements to see which one of them is failing (since you can't debug outside of the IDE, and it isn't failing there).
I am trying the following code to play an mp3. The file is in the correct folder. An exception is thrown when opening the file.
Any ideas what could be wrong?
When trying to print the url on the third line it gives me a null pointer exception.
I am compiling with 1.8 to a min compat version of 1.6. Could this be related?
AudioInputStream audioIn = null;
URL url = this.getClass().getResource("./data/1.wav");
System.out.print(url.getFile());
try {
audioIn = AudioSystem.getAudioInputStream(url);
//audioInputStream = AudioSystem.getAudioInputStream(this.getClass().getResource(soundFile));
}
catch(Exception ex) {System.out.print("exception opening file");}
try{
Clip clip = AudioSystem.getClip();
clip.open(audioIn);
clip.start();
}
catch(Exception ex)
{
System.out.print("exception mediaplayer");
}
}
Instead of using a String var, you could use a Clip object. With Clip, it worked for me.
Oh I had to put the data folder in the src directory.
Still a problem though: when I compile as a jar file, it does not find the data folder. And I want the user to be able to put different things in there.
A URL can see into Jar, unlike a File address. So, you should be fine using the URL to obtain the file.
Two possible problems:
(1) if the file is an .mp3 and you are trying to load a .wav, there will of course be a mismatch as 1.mp3 <> 1.wav.
(2) putting the data into the src folder is not enough. It must also be in a subfolder of the folder that contains the "this" that you refer to. For example, if your code is in package "foo", the place to put the file would be src/foo/data/1.wav.
Do you have a library to decode the .mp3? If so, something like JavaZoom should work.