I'm trying to make an application where when I click a JButton, it plays a song. I've already figured out how to specify JButtons. However, I can't seem to find a way to play sound. I'm not going to use sun.audio, so many of the threads that I looked at didnt work. I found many low quality answers. Eventually, I settled on this code.
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();
}
Inside my src folder, I have a folder called "Songs". I changed the file path to this:
/Songs/
Then, I tried calling the function using a wav file:
playSound("song.wav");
And then I get a null error. I believe that this is because it does not recognize the file path. The answer to my problem is most likely very obvious, but somehow I cant find it.
put song.wav in the same folder of your Main class, then the getResourceAsStream will find it.
if you're using eclipse, it can automatically copy the .wav file to the output folder.
You might want to create a class on some different java package so your entry point does not get polluted by assets.
This reading might help you: http://www.thinkplexx.com/learn/howto/java/system/java-resource-loading-explained-absolute-and-relative-names-difference-between-classloader-and-class-resource-loading
Related
I made this method to play audio in my class and it works fine.
but for some reason when i export it to a jar file nothing happens.
I tried other solutions but i just get null-pointer exceptions.
does anyone have an idea what i'm doing wrong
public void welcome(){
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("sound/garage1.wav").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
} catch(Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
if you load the file like this (not as ressource of a class), the folder "sound" containing the "garage1.wav" has to be located in the working directory when you execute the jar, because new File("") points to the working directory. For example: if you execute the jar with a double click on it, the folder "sound" must have the same parent folder as the jar.
I have a problem and I hope you can help me.
Some talk about what I am doing so you know what's going on: So at the moment I'm trying to program a litte piece of software which can play me some music files (mp3 files to be exact, so i'm using the jLayer API). I'm working with Netbeans and I have succesfully imported a music file in the project. If I build my program and open the resulting JAR file with an archive program, I can find my music file in there. My function which I'm using goes like this:
public static String play(String file) {
File test = new File(file);
try {
FileInputStream in = new FileInputStream(test);
Player pl = new Player(in);
pl.play();
return "success";
}
catch (Exception e) {
return e.toString();
}
}
As you can see I'm getting a String with the Path Name and refactor him so I can play the file. I'm calling the function with the following code (the music file is saved in the ressources package):
MP3.play(getClass().getResource("/ressources/angel.mp3").getPath())
So if I start the programm via Netbeans everything works perfectly fine. But if I create a JAR file and start the program nothing happens. The Exception getting is the following:
java.io.FileNotFoundException: file:\C:\Users\Raphael\Documents\NetBeansProjects\MP3\dist\MP3.jar!\ressources\angel.mp3
It says the File does not exist but if I check my JAR the file is there......
Another strange thing I found out is the following: If I use the following function to play the music file:
public static String play(InputStream test) {
try {
Player pl = new Player(test);
pl.play();
return "success";
}
catch (Exception e) {
return e.toString();
}
}
and call the function with the following argument:
MP3.play(getClass().getResourceAsStream("/ressources/angel.mp3"));
Everything works fine in both Netbeans and the final JAR. Can anybody explain me what I'm doing wrong and only the second function works in the JAR version?
It would be really nice if you could help me in this matter.
Greetings,
xXKnightRiderXx
I am assuming that you have 2 packages 1 is src where your .java files is located and other is resources where your sound files is located
So i suggest you to use
MP3.play(getClass().getResourceAsStream("/angel.mp3"));
Because GetResource() automatically finds the resource package
I have a program which has to play sounds from a terminal interface.
The code is fairly simple and here it is :
public static synchronized void playSound() {
new Thread(new Runnable() {
public void run() {
File _file = new File("music/sound.wav");
try (AudioInputStream _audio = AudioSystem
.getAudioInputStream(_file)) {
Clip _clip = AudioSystem.getClip();
_clip.open(_audio);
_clip.start();
} catch ([…] e) {
// […]
}
}
}).start();
}
The file is in the music folder which is in my source path.
All work perfectly well when I run the program in eclipse. But if I export it in a .jar file and try it in the windows cmd I get this message :
java.io.FileNotFoundException: music\sound.wav (The system cannot find the path specified)
[edit] The audio files are indeed packed into the .jar, but it still doesn’t work.
Is it even possible to play a sound from the windows prompt? If not, is there one that does?
Thanks,
SilverDuck
When the file is packaged into a jar file, it is no longer a File. It needs to be read as a resource. Try changing the code like this
InputStream inputStream = this.getClass().getResourceAsStream("music/sound.wav");
try (AudioInputStream _audio = AudioSystem.getAudioInputStream(inputStream)) {
Try either not packaging your music in jar (put it alongside) or load your packaged file as a resource.
See Java resource files for example.
Here Loading resources (images) contained in a .Jar file or in the classpath might be a better explanation.
I've got an issue with saving a BufferedImage using a simple paint program. When I save the image from the paint such as a picture of a snake that I drew earlier, it saves the image just fine, but it doesn't save it in the way you might think. Instead of saving the image to a C:\ drive (or whatever drive a user may be using) it saves the image to the eclipse workspace. This of course is unacceptable, as this needs to be given directly to a user's main place of access is. Here is the method that is used for saving the bufferedimage.
static void saveImage() {
try {
ImageIO.write(background, "png",
new File(fileName + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
}
So here, background is obviously the image being saved, png is the extension, and fileName is a string that is saved earlier using a prior method that isn't important here. This method saves the image to the eclipse workspace. This is bad. We need this to save to the default drive. How do I accomplish this? Let me know if you need anything else to aid you with your answer.
EDIT: So, as requested, here is the code that changes the fileName. It is in a different class with a differnt UI completely, and because I'm not sure of how much to post, I'll post the actionListener and the getName() method. What happens here is that there is a JTextField that, once a JButton is pressed, has the string extracted from it and uses it as the fileName. Here's the code:
`finishButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ProgramUI.fileName = getName();
ProgramUI.fileHasName = true;
ProgramUI.saveImage();
frame.dispose();
}
});
}
public String getName() {
return nameField.getText();
}
`
Offer the user a JFileChooser (as seen in this answer) to allow them to navigate to a path and select a name.
Restrict the path using a FileSystemView as seen here.
You have not given the path to save the file when you are creating a File object. By default it will save the file in the current working directory.
Try this :
static void saveImage() {
try {
ImageIO.write(background, "png",
new File("C:\\" + fileName + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
}
or better add a path parameter to the method:
static void saveImage(String filePath) {
try {
ImageIO.write(background, "png",
new File(filePath + fileName + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
}
but make sure that you get the path with proper slashes (//)
If that code is saving to an Eclipse workspace, it is because:
you are supplying a relative pathname in filename, AND
the current directory is the Eclipse workspace directory when you run the application from within Eclipse.
Try running the command from the command prompt. With the same inputs (i.e. the same filename as you are currently using) it should save to the current directory.
It is not possible to give you a simple recipe for solving this problem. The correct solution depends on how you want the program to actually work:
Where (i.e. in what directory) you want the file to be saved.
Whether (and how) you want the user to be able to say where to save the file.
Whether this application needs to be portable; i.e. work on something other than Windows.
I suggest that you start by reading up on the concept of "the current directory", and read the javadoc for the java.io.File class ... which will explain how Java decides what file you "mean" when you try to open one.
i am trying to loop an audio file but when i've tried the other various methods available, my music doesn't play.
My basic code is:
import java.io.*;
import sun.audio.*;
public class PlayMusic {
public void playSound() {
try {
AudioPlayer p = AudioPlayer.player;
AudioStream as = new AudioStream(new FileInputStream("02 River Flows In You.wav"));
p.start(as);
} catch (IOException IOE) {
}
}
I've never seen sun.audio.AudioPlayer in use before! I've always used the javax.sound.sampled library.
Maybe you can tell me how you came across it. It looks to me like rather old code (10 years?) and also a bit on the limited side.
I think, if you aren't getting a single playback, you should try the URL form:
AudioStream audiostream = new AudioStream(url.openStream());
AudioPlayer.player.start(audiostream);
Then try putting the code in a loop? A lot depends on whether the .start command blocks or not. If it launches a separate thread (most likely), then you will have to figure out when the file ends, and I don't see any commands provided to do that! The spec also lists the possibility of creating an ContinuousAudioDataStream and managing that.
Unless there is something I don't know about this library that I should, I recommend using either a javax.sound.sampled.Clip, or javax.sound.sampled.SourceDataLine for playback. The Clip has a boolean you can set for looping, but requires the entire file be loaded into memory first. The SourceDataLine plays back from a url or file location, and can implement a listener to tell you when the file is done.
http://docs.oracle.com/javase/tutorial/sound/playing.html