I have looked at countless different StackOverflow answers as well as answers from other sites, but none of the solutions have fixed my problem. I cannot for the life of me get my .wav file to play.
Here is my code:
Sound class:
public class Sound {
/**
* Static file paths for each sound.
*/
public static String stepSound = "/resources/step.wav";
/**
* Audio input stream for this sound.
*/
private AudioInputStream audioInputStream;
/**
* Audio clip for this sound.
*/
private Clip clip;
/* -- Constructor -- */
/**
* Creates a new sound at the specified file path.
*
* #param path File path to sound file
*/
public Sound(String path) {
// Get the audio from the file
try {
// Convert the file path string to a URL
URL sound = getClass().getResource(path);
System.out.println(sound);
// Get audio input stream from the file
audioInputStream = AudioSystem.getAudioInputStream(sound);
// Get clip resource
clip = AudioSystem.getClip();
// Open clip from audio input stream
clip.open(audioInputStream);
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}
}
/* -- Method -- */
/**
* Play the sound.
*/
public void play() {
// Stop clip if it's already running
if (clip.isRunning())
stop();
// Rewind clip to beginning
clip.setFramePosition(0);
// Play clip
clip.start();
}
/**
* Stop the sound.
*/
public void stop() {
clip.stop();
}
}
Constructor call that leads to error:
// Play step sound
new Sound(Sound.stepSound).play();
I know this isn't the first time a problem like this has been asked or answered on this website, but I've been trying other solutions for hours at this point and all I've found is pain and frustration. I can post more code if needed. Thanks in advance.
EDIT: I have unpacked the .jar file and confirmed that the file is indeed there. The problem is that the URL ends up being null, and so a NullPointerException is thrown.
EDIT #2: Added more code in case there's another problem.
Related
I have been searching for how to play audio in java ( textpad ). There are plenty of examples but they use a GUI. I am using a command line interface. How do I play audio and use key event e.g spacebar to pause the audio and press spacebar again to replay the audio?
I do not know which examples you have been looking at but I do not think the GUI has anything to do with IF you can play sounds.
The following code is a simple sound class you can use in order to play audio in Java, you can read more about it at this Documentation.
import javax.sound.sampled.*;
import java.io.IOException;
import java.net.URL;
public class Sound {
private URL url;
private Clip clip;
/**
* #param requestedSound The requested type of sound
*/
public Sound(String requestedSound) {
url = this.getClass().getResource(requestedSound);
if (url != null) {
try {
// Open an audio input stream.
// Get a sound clip resource.
// Open audio clip and load samples from the audio input stream.
AudioInputStream audioInput = AudioSystem.getAudioInputStream(url);
clip = AudioSystem.getClip();
clip.open(audioInput);
} catch (UnsupportedAudioFileException | LineUnavailableException | IOException e) {
e.printStackTrace();
}
}
}
/**
* Plays the sound
*/
public void play() {
clip.setFramePosition(0);
clip.start();
}
}
To use it you simply create a sound in your main file, with Sound mySound = new Sound("path_to_sound"); Where you replace path_to_sound with your path. I believe one of the supported formats is .wav. Then you can just play the sound whenever you want to with mySound.play();, and whenever you do it will be played from the beginning.
Regarding your implementation of using spacebar to play / replay the audio, I believe it is better if you try to work with the given code in order to understand how it works.
I would like to run audio file from java and i read many codes in SO but unbale to run my file perhaps!
Seems I have mentioned wrong path or using wrong lib .
Please assist me what's wrong in below code to run mp3 or VLC .aac format file
public void playSound() {
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("D:/clinic/clinic/mysound.mp3").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
} catch(Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
If you use the this.getClass.getResource() method instead of the File(file) method, maybe it would work. Remember that the file that the audio is in has to be in the same package as the class that is running it. If this doesn't work, then try it with a .wav file(you can use a .mp3 to .wav converter).
public void run() {
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(this.getClass().getResource("mysound.mp3"));
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
clip.loop(Clip.LOOP_CONTINUOUSLY);
} catch (Exception ex) {
ex.printStackTrace();
}
}
I hope this helps.
AudioSystem does not support .mp3 files. (Only AIFC, AIFF, AU, SND, and WAVE)
If you want to use .mp3 files, try using MediaPlayer instead.
// Fake init of JFX Toolkit (Just do this once before you use MediaPlayer)
// Not needed in a JavaFX application as Application.launch() inits the toolkit
new JFXPanel();
Media media = new Media(new File("yourFile.mp3").toURI().toString());
MediaPlayer player = new MediaPlayer(media);
player.play();
The audioformats supported natively are nit that useful if you don't want to have huge audiofiles.
I ended using WAV files as it was what I could get to work, but it bothered me all the time.
Using jaad was trickier than I thought, but I got it working now: Java play AAC encoded audio
I know this question has been asked many times and I've looked at many in hopes to figure out my problems, but it didn't really help much. I was given this class to use to play WAV files on my GUI and it works when retrieving local files. But it doesn't work in a JAR file. I know this is because the music class only works for retrieving local files, so I need help changing the code to retrieve music files from the JAR.
Here's the SoundPlayer class:
package extra;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import org.pscode.xui.sound.bigclip.BigClip;
/**
* A class to play audio clips. Caches previously-played clips,
* allowing fast re-playback of previously played sounds.
*
* #author Anon
* #version 1.51
*/
public class SoundPlayer {
/** A cache of previously-played audio clips. */
private final Map<String, Clip> myClips = new HashMap<String, Clip>();
/**
* Plays the audio file with the given file name.
* This method returns instantly, without waiting for the clip to finish playing.
*
* #param theFilename The name of the file to play.
* #return a Clip object representing the sound played.
* #throws IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip play(final String theFilename) throws IllegalArgumentException {
return loop(theFilename, 1);
}
/**
* Plays the clip with the given file name in a continuous loop.
* The clip keeps looping until it is later stopped by calling the
* stop() method. This function returns instantly
*
* #param theFilename The name of the file to play.
* #return a Clip object representing the sound played.
* #throws IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip loop(final String theFilename) throws IllegalArgumentException {
return loop(theFilename, Clip.LOOP_CONTINUOUSLY);
}
/**
* Plays the clip with the given file name in a loop.
* The clip loops until it has played the specified number of times,
* or until it is later stopped by calling the stop() method.
* This function returns instantly, without waiting for the clip to finish looping.
*
* #param theFilename The name of the file to play.
* #param theNumberOfTimes The number of times to loop the clip.
* #return a Clip object representing the sound played.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip loop(final String theFilename, final int theNumberOfTimes)
throws IllegalArgumentException {
final Clip clip = getClip(theFilename);
if (clip != null) {
clip.loop(theNumberOfTimes);
}
return clip;
}
/**
* Pauses the clip with the given file name.
* If the clip is later played, it will resume from where it was paused.
* Calling this method does not resume a thread that is
* suspended on a playAndWait() or a loopAndWait().
*
* If stop() is called on a paused clip, it will reset to the
* beginning of the clip for the next play.
*
* #param theFilename The name of the file to pause.
* #exception IllegalArgumentException if there is a problem reading from
* or playing the sound file.
*/
public void pause(final String theFilename) throws IllegalArgumentException {
final Clip clip = getClip(theFilename);
if (clip != null) {
final int pos = clip.getFramePosition();
clip.stop();
clip.setFramePosition(pos);
}
}
/**
* Stops the clip with the specified filename
* (and wakes up any threads waiting for it to finish playing).
*
* #param theFilename The name of the file to stop.
* #return a Clip object representing the sound stopped.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip stop(final String theFilename)
throws IllegalArgumentException {
final Clip clip = getClip(theFilename);
stopClip(clip);
return clip;
}
/**
* Stops all currently playing sound clips
* (and wakes up the threads waiting for them to finish playing).
*/
public void stopAll() {
for (final Clip clip : myClips.values()) {
stopClip(clip);
}
}
/**
* Preloads the clip at the given file name.
* This means the clip will be available faster, when requested for playing the first time.
* #param theFilename The name of the file to preload.
* #return a Clip object representing the preloaded sound.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
public Clip preLoad(final String theFilename)
throws IllegalArgumentException {
return getClip(theFilename);
}
/**
* Returns a Clip object for a filename, either by creating
* a new one or loading it from the cache.
*
* #param theFilename The name of the file to load.
* #return a Clip object, or null if one is not found.
* #exception IllegalArgumentException if there is a problem reading from the sound file.
*/
private Clip getClip(final String theFilename) throws IllegalArgumentException {
BigClip clip = null;
AudioInputStream ais = null;
if (myClips.containsKey(theFilename)) {
clip = (BigClip) myClips.get(theFilename);
} else {
// read audio file from disk
try {
ais = AudioSystem.getAudioInputStream(new File(theFilename));
clip = new BigClip();
clip.open(ais);
clip.addLineListener(new LineListener() {
/**
* Responds to audio events generated by clips.
*
* #param theEvent The event generated.
*/
public void update(final LineEvent theEvent) {
if (theEvent.getType() == LineEvent.Type.STOP) {
// clip is done playing
stopClip((Clip) theEvent.getSource());
}
}
});
myClips.put(theFilename, clip);
} catch (final UnsupportedAudioFileException uafe) {
throw new IllegalArgumentException
("Not a valid supported audio file: \"" + theFilename + "\"", uafe);
} catch (final LineUnavailableException lue) {
lue.printStackTrace();
throw new IllegalArgumentException
("Line is not available to play sound \"" + theFilename + " \"", lue);
} catch (final IOException ioe) {
throw new IllegalArgumentException
("I/O error while reading file: \"" + theFilename + "\" ", ioe);
}
}
return clip;
}
/**
* Stops the playing of the specified clip.
*
* #param theClip The clip.
*/
private void stopClip(final Clip theClip) {
if (theClip != null) {
synchronized (theClip) {
theClip.stop();
theClip.setFramePosition(0);
theClip.notifyAll(); // awaken threads waiting for this Clip
}
}
}
}
// end of class SoundPlayer
In the getClip() method, I think that's where there needs to be a change since that's where the AudioInputStream is grabbing local files. I'm just not sure how to change it though.
Files in a jar file can't actually be retrieved as a file. Instead, you need to use the Class object (usually the this variable)'s .getResource to retrieve a URL or .getResourceAsStream to retrieve an InputStream for it.
You can then pass either of these into one of AudioSystem.getAudioInputStream's overloads as it has one for InputStreams and one for URLs.
Use ClassLoader.getSystemResource("path/inside/of/jar").
If the goal is to simply play sound:
Try TinySound. I recently used this in a project I'm working on, and it's mindblowingly easy to use. Make sure you use either .wav or .ogg files though, you can use http://media.io/ to convert to both of those.
I created a project that plays audio within the netbeans IDE. Those audio files were placed in the Classes folder.
Although when I created it as a JAR file, it was unable to locate the audio files. I even copy and pasted the files inside the new dist folder.
Here is a snippet of code:
private void playSound39()
{
try
{
/**Sound player code from:
http://alvinalexander.com/java/java-audio-example-java-au-play-sound
*/
// the input stream portion of this recipe comes from a javaworld.com article.
InputStream inputStream = getClass().getResourceAsStream("./beep39.wav");
AudioStream audioStream = new AudioStream(inputStream);
AudioPlayer.player.start(audioStream);
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null,"Audio file not found!");
}
}
If you want to embedd the audio file in your program it's must be placed inside the src folder in a package.
For example I'll demonstrate a code I use to set icons to buttons (should work for audio files as well) :
While creating the JFrame I wrote :
jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/GUI/Icon/PatientBig.png")));
I have in my project a package called GUI with a subpackage called Icons where my icons exist and they all are in src folder.
When you using getClass().getResource function , I prefer to use an absolute path.
After seeing your respone I have noticed that you keep using . in the begining of the class path, I copied the snippet you published and removed the . from the begining of the path and placed my audio file bark.wav in the src folder in the default package and it worked
public class test {
private void playSound39() {
try {
/**
* Sound player code from:
* http://alvinalexander.com/java/java-audio-example-java-au-play-sound
*/
// the input stream portion of this recipe comes from a javaworld.com article.
InputStream inputStream = getClass().getResourceAsStream("/bark.wav");
AudioStream audioStream = new AudioStream(inputStream);
AudioPlayer.player.start(audioStream);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Audio file not found!");
}
}
public static void main(String[] args){
new test().playSound39();
}
}
Then I placed the audio file inside a package called test1 and modified the path in getResourceAsStream function and again it worked:
public class test {
private void playSound39() {
try {
/**
* Sound player code from:
* http://alvinalexander.com/java/java-audio-example-java-au-play-sound
*/
// the input stream portion of this recipe comes from a javaworld.com article.
InputStream inputStream = getClass().getResourceAsStream("/test1/bark.wav");
AudioStream audioStream = new AudioStream(inputStream);
AudioPlayer.player.start(audioStream);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Audio file not found!");
}
}
public static void main(String[] args){
new test().playSound39();
}
}
The Most important thing is to remove . from the path
try this
InputStream in = getClass().getResourceAsStream("/beep39.wav");
I think you need to bypass use of the InputStream. When running the getAudioInputStream method, using InputStream as a parameter triggers markability and resetability tests on the audio file. Audio files usually fail these tests. If you create your AudioInputStream with a URL or File parameter, these tests are circumvented. I prefer URL as it seems more robust and can "see into" jars.
URL url = getClass().getResource("./beep39.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
Then, in a while loop, you would execute a read method on the AudioInputStream and send the data to a SourceDataLine.
The Java Tutorials covers this in their audio trail. This link jumps into the middle of the tutorials.
AFAIK, there is no "AudioPlayer" in the Java 7 SDK.
Let's suppose that we have the following scenario: something is playing on an android device (an mp3 par example, but it could be anything that use the audio part of an android device). From an application (android application :) ), I would like to intercept the audio stream to analyze it, to record it, etc. From this application (let's say "the analyzer") I don't want to start an mp3 or something, all I want is to have access to the audio stream of android.
Any advice is appreciated, it could a Java or C++ solution.
http://developer.android.com/reference/android/media/MediaRecorder.html
public class AudioRecorder {
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD
* card).
*/
public AudioRecorder(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath()
+ path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if (!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state
+ ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
Consider using the AudioPlaybackCapture API that was introduced in Android 10 if you want to get the audio stream for a particular app.