I wrote Snake code, and want to add a sound effect when snake eats an apple. I copyied a code from some guy on YT, but it doesn't work to me. Can somebody explain me how to do this?
Code:
import com.sun.tools.javac.Main;
import javax.sound.sampled.*;
import java.io.IOException;
import java.net.URL;
public class AppleEatSoundEffect {
public static Mixer mixer;
public static Clip clip;
public static void main(String[] args) {
Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();
mixer = AudioSystem.getMixer(mixInfos[0]);
DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);
try {
clip = (Clip) mixer.getLine(dataInfo);
} catch (LineUnavailableException lue) {
lue.printStackTrace();
}
try {
URL soundURL = Main.class.getResource("NotBad.wav");
AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundURL);
clip.open(audioStream);
} catch (LineUnavailableException lue) {
lue.printStackTrace();
} catch (UnsupportedAudioFileException uafe) {
uafe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
clip.start();
do {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
} while (clip.isActive());
}
}
Compiler says thas something wrong with clip = (Clip) mixer.getLine(dataInfo);:
Exception in thread "main" java.lang.IllegalArgumentException: Line unsupported: interface Clip
at java.desktop/com.sun.media.sound.PortMixer.getLine(PortMixer.java:131)
Below is a method which allows you to play audio files, in particular the common WAV or MIDI files. Try it...if you get your desired audio then let me know.
public Thread playWav(final File wavFile, final boolean... loopContinuous) {
String ls = System.lineSeparator();
// Was a file object supplied?
if (wavFile == null) {
throw new IllegalArgumentException(ls + "playWav() Method Error! "
+ "Sound file object can not be null!" + ls);
}
// Does the file exist?
if (!wavFile.exists()) {
throw new IllegalArgumentException(ls + "playWav() Method Error! "
+ "The sound file specified below can not be found!" + ls
+ "(" + wavFile.getAbsolutePath() + ")" + ls);
}
// Play the Wav file from its own Thread.
Thread t = null;
try {
t = new Thread("Audio Thread") {
#Override
public void run() {
try {
Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
audioClip = clip;
clip.addLineListener((LineEvent event) -> {
if (event.getType() == LineEvent.Type.STOP) {
clip.drain();
clip.flush();
clip.close();
}
});
clip.open(AudioSystem.getAudioInputStream(wavFile));
// Are we to loop the audio?
if (loopContinuous.length > 0 && loopContinuous[0]) {
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
clip.start();
}
catch (LineUnavailableException | UnsupportedAudioFileException | IOException ex) {
ex.printStackTrace();
}
}
};
t.start();
Thread.sleep(100);
}
catch (InterruptedException e) {
e.printStackTrace();
}
return t;
}
To use this method simply call it wherever and whenever you want a particular sound effect to be played:
File file = new File("resources/NotBad.wav");
playWav(file);
Make sure the file object points to the correct file location. If you want to loop the audio file as for perhaps game background music then supply boolean true to the optional loopContinuous parameter:
File file = new File("resources/BackgroundMusic.mid");
playWav(file, true);
Related
I try to load my sounds from my resource folder when trying out my Application in the IDE.
For images and other stuff that uses InputStreams I use this method:
#Override
public InputStream readAsset(String fileName) throws IOException {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream(fileName);
return is;
}
this lets me open an Inputstream of which I can pull Images.
As soon as I would try to cast this InputStream to an Audio InputStream I get errors. Also if I would try to make a new AudioInputStream passing the above InputStream as the parameter.
This is my current way to load sounds from external paths:
public class JavaSound implements Sound {
private Clip clip;
public JavaSound(String fileName){
try {
File file = new File(fileName);
if (file.exists()) {
//for external storage Path
AudioInputStream sound = AudioSystem.getAudioInputStream(file);
// load the sound into memory (a Clip)
clip = AudioSystem.getClip();
clip.open(sound);
}
else {
throw new RuntimeException("Sound: file not found: " + fileName);
}
}
catch (MalformedURLException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Malformed URL: " + e);
}
catch (UnsupportedAudioFileException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Unsupported Audio File: " + e);
}
catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Input/Output Error: " + e);
}
catch (LineUnavailableException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Line Unavailable Exception Error: " + e);
}
}
#Override
public void play(float volume) {
// Get the gain control from clip
FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
// set the gain (between 0.0 and 1.0)
float gain = volume;
float dB = (float) (Math.log(gain) / Math.log(10.0) * 20.0);
gainControl.setValue(dB);
clip.setFramePosition(0); // Must always rewind!
clip.start();
}
#Override
public void dispose() {
clip.close();
}
}
how can i exchange the AudioInputStream part to work like the first code, pulling the files out of my resource directory?
EDIT :
this way of creating a new AudioInputStream by passing an InputStream
File file = new File(fileName);
if (file.exists()) {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream(fileName);
//for external storage Path
AudioInputStream sound = new AudioInputStream(is);
// load the sound into memory (a Clip)
clip = AudioSystem.getClip();
clip.open(sound);
}
also throws errors before even running it
this made it work in my above code:
public JavaSound(String fileName){
try {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream(fileName);
AudioInputStream sound = AudioSystem.getAudioInputStream(new BufferedInputStream(is));
// load the sound into memory (a Clip)
clip = AudioSystem.getClip();
clip.open(sound);
}
catch (MalformedURLException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Malformed URL: " + e);
}
catch (UnsupportedAudioFileException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Unsupported Audio File: " + e);
}
catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Input/Output Error: " + e);
}
catch (LineUnavailableException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Line Unavailable Exception Error: " + e);
}
}
just had to start a new bufferedInputStream with my inputStream to have the AudioInputStream... :D still thanks a lot ;)
You cannot cast InputStream to AudioInputStream (you could do the inverse). The Clip.open() wants an AudioInputStream.
An approach, suggested by this answer here is to use the URL from the .getResource() call, rather than attempting to open the InputStream and then pass that in.
Therefore, try:
URL soundURL = classloader.getResource(fileName);
AudioInputStream ais = AudioSystem.getAudioInputStream(soundURL);
I'm writing an new audio system for my game and i have come across this error and can not seem to find and solution anywhere,
java.lang.IllegalArgumentException: illegal call to open() in interface Clip
at com.sun.media.sound.DirectAudioDevice$DirectClip.implOpen(Unknown Source)
at com.sun.media.sound.AbstractDataLine.open(Unknown Source)
at com.sun.media.sound.AbstractDataLine.open(Unknown Source)
This is the code i use to load and play my audio.
private Clip load(String filename) {
try {
//Loads the file
InputStream in = new FileInputStream(new File("res/" + filename + FILE_EXT));
//Create the input buffer
InputStream bufferedIn = new BufferedInputStream(in);
//Convert into an audio stream
AudioInputStream audioStream = AudioSystem.getAudioInputStream(bufferedIn);
//Get the audio format
AudioFormat format = audioStream.getFormat();
//Get the data line info
DataLine.Info info = new DataLine.Info(Clip.class, format);
//Return the clip
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.addLineListener(this);
return this.clip = audioClip;
} catch (FileNotFoundException e) {
System.err.println("Failed to load audio! " + filename + " not found!");
throw new RuntimeException(e);
} catch (UnsupportedAudioFileException e) {
System.err.println("Failed to load audio! " + filename + " is unsupported!");
throw new RuntimeException(e);
} catch (IOException e) {
System.err.println("Failed to load audio! " + filename + " caused an IO Exception!");
throw new RuntimeException(e);
} catch (LineUnavailableException e) {
System.err.println("Failed to load audio! " + filename + " line is unavalible!");
e.printStackTrace();
}
throw new RuntimeException("Failed to load audio! input == null!");
}
private void startClip() {
if(this.clip != null) this.clip.start();
else throw new RuntimeException("Failed to start audio clip! The clip appears to be null.");
}
private void stopClip() {
if(this.clip != null) this.clip.close();
else throw new RuntimeException("Failed to close audio clip! The clip appears to be null.");
}
#Override
public void play() {
try {
if(isPlaying()) return;
else {
startClip();
this.clip.open();
this.playing = true;
}
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
The error occurs at this.clip.open();
Can anyone help me?
You don't pass anything to the Clip to play.
Line#open:
IllegalArgumentException - if this method is called on a Clip instance.
You need to call clip.open(audioStream) instead of clip.open(). Also, you need to do this before starting the Clip.
I'm getting some weird behavior from JavaSound in Java 8 in which I have a Sound class and randomly (every 3-5 instances or so) when being created the thread halts for 0-2s
This is constructor method
public Sound(String fileName) {
// specify the sound to play
// (assuming the sound can be played by the audio system)
// from a wave File
try {
File file = new File(fileName);
if (file.exists()) {
AudioInputStream sound = AudioSystem.getAudioInputStream(file);
// load the sound into memory (a Clip)
clip = AudioSystem.getClip();
clip.open(sound);
length = clip.getMicrosecondLength();
System.out.println("length: " + length);
}
else {
throw new RuntimeException("Sound: file not found: " + fileName);
}
}
catch (MalformedURLException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Malformed URL: " + e);
}
catch (UnsupportedAudioFileException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Unsupported Audio File: " + e);
}
catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Input/Output Error: " + e);
}
catch (LineUnavailableException e) {
e.printStackTrace();
throw new RuntimeException("Sound: Line Unavailable Exception Error: " + e);
}
}
My current thoughts are either it is having issues allocating memory(seeing as there are multiple of these instances in an ArrayList), the file is taking long to open from as the coding isn't ideal or it's having trouble removing the objects.
Here's the ArrayList code just in case
public static void playSound(String file){
sounds.add(new Sound("res/" + file));
Sound sound = sounds.get(sounds.size()-1);
sound.setVolume(Screen.music.getVolume());
sound.play();
}
I've tried running the above section of code in a new thread and the main thread continues but the sounds don't always play.
Edit: I do have some sort of garbage collection to clear up most of the memory for the Sound objects but I don't think the problem is related to that, however reusing the objects might be a valid idea?
public void checkStatus(){
if(clip.getMicrosecondPosition() >= length){
new Thread(){
public void run(){
clip.stop();
clip.close();
clip.flush();
clip.drain();
Screen.sounds.remove(this);
}
}.start();
}
}
i have made a jar program that need to run an audio file
this is how i open the audio file(not in jar file)
Thread sound = new Thread(){
public void run(){
MakeSound.playSound("Raef.wav");
}
};
i run it with
sound.start();
and end it with
sound.stop();
when i run it on blue j its worked but the sound isnt play on the jar files
can someone solve this ?
i need to make a program with jar
nb : MakeSound is another class i used to play the sound
public class MakeSound {
private static final int BUFFER_SIZE = 128000;
private static File soundFile;
private static AudioInputStream audioStream;
private static AudioFormat audioFormat;
private static SourceDataLine sourceLine;
/**
* #param filename the name of the file that is going to be played
*/
public static void playSound(String filename){
String strFilename = filename;
// buka file
try {
soundFile = new File(strFilename);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
try {
audioStream = AudioSystem.getAudioInputStream(soundFile);
} catch (Exception e){
e.printStackTrace();
System.exit(1);
}
audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
try {
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
} catch (LineUnavailableException e) {
e.printStackTrace();
System.exit(1);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
sourceLine.start();
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
try {
nBytesRead = audioStream.read(abData, 0, abData.length);
} catch (IOException e) {
e.printStackTrace();
}
if (nBytesRead >= 0) {
#SuppressWarnings("unused")
int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
}
}
sourceLine.drain();
sourceLine.close();
}
The exact steps to put an audio file in a jar depends on the IDE you are using.
What I normally do is to make a subfolder "audio" and put the audio files there. The subfolder is a subfolder of the code source.
Then, in the code, I create a URL that points to this subfolder.
URL url = this.getClass().getResource("audio/" + fileName);
I don't know about the specifics of MakeSound.playSound(). Hopefully it accepts a URL as a parameter. If it only accepts file names, you might need to rewrite it. Operating Systems generally aren't set up to find files that are packed in jars. URLs, though, are able to point inside of a jar.
Key point: the calling code is in a folder. I used "this" instead of invoking the class name of the calling code which is also possible. If this folder has a subfolder named "audio", the above line of code should find the file.
How do we play sound (a music file of any format like .wma, .mp3 ) in a Java desktop application? (not an applet)
I have used the following code (taken from another question on Stack Overflow) but it throws an Exception.
public class playsound {
public static void main(String[] args) {
s s=new s();
s.start();
}
}
class s extends Thread{
public void run(){
try{
InputStream in = new FileInputStream("C:\\Users\\srgf\\Desktop\\s.wma");
AudioStream as = new AudioStream(in); //line 26
AudioPlayer.player.start(as);
}
catch(Exception e){
e.printStackTrace();
System.exit(1);
}
}
}
The program when run throws the following Exception:
java.io.IOException: could not create audio stream from input stream
at sun.audio.AudioStream.<init>(AudioStream.java:82)
at s.run(delplaysound.java:26)
Use this library:
http://www.javazoom.net/javalayer/javalayer.html
public void play() {
String song = "http://www.ntonyx.com/mp3files/Morning_Flower.mp3";
Player mp3player = null;
BufferedInputStream in = null;
try {
in = new BufferedInputStream(new URL(song).openStream());
mp3player = new Player(in);
mp3player.play();
} catch (MalformedURLException ex) {
} catch (IOException e) {
} catch (JavaLayerException e) {
} catch (NullPointerException ex) {
}
}
Hope that helps everyone with a similar question :-)
Hmmm. This might look like advertisement for my stuff, but you could use my API here:
https://github.com/s4ke/HotSound
playback is quite easy with this one.
Alternative: use Java Clips (prebuffering)
... code ...
// specify the sound to play
File soundFile = new File("pathToYouFile");
//this does the conversion stuff for you if you have the correct SPIs installed
AudioInputStream inputStream =
getSupportedAudioInputStreamFromInputStream(new FileInputStream(soundFile));
// load the sound into memory (a Clip)
DataLine.Info info = new DataLine.Info(Clip.class, inputStream.getFormat());
Clip clip = (Clip) AudioSystem.getLine(info);
clip.open(sound);
// due to bug in Java Sound, explicitly exit the VM when
// the sound has stopped.
clip.addLineListener(new LineListener() {
public void update(LineEvent event) {
if (event.getType() == LineEvent.Type.STOP) {
event.getLine().close();
System.exit(0);
}
}
});
// play the sound clip
clip.start();
... code ...
Then you need this method:
public static AudioInputStream getSupportedAudioInputStreamFromInputStream(InputStream pInputStream) throws UnsupportedAudioFileException,
IOException {
AudioInputStream sourceAudioInputStream = AudioSystem
.getAudioInputStream(pInputStream);
AudioInputStream ret = sourceAudioInputStream;
AudioFormat sourceAudioFormat = sourceAudioInputStream.getFormat();
DataLine.Info supportInfo = new DataLine.Info(SourceDataLine.class,
sourceAudioFormat,
AudioSystem.NOT_SPECIFIED);
boolean directSupport = AudioSystem.isLineSupported(supportInfo);
if(!directSupport) {
float sampleRate = sourceAudioFormat.getSampleRate();
int channels = sourceAudioFormat.getChannels();
AudioFormat newFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
sampleRate,
16,
channels,
channels * 2,
sampleRate,
false);
AudioInputStream convertedAudioInputStream = AudioSystem
.getAudioInputStream(newFormat, sourceAudioInputStream);
sourceAudioFormat = newFormat;
ret = convertedAudioInputStream;
}
return ret;
}
Source for the Clip example (with little changes by me): http://www.java2s.com/Code/Java/Development-Class/AnexampleofloadingandplayingasoundusingaClip.htm
SPIs are added via adding their .jars to the classpath
for mp3 these are:
http://www.javazoom.net/mp3spi/mp3spi.html
http://www.javazoom.net/javalayer/javalayer.html
http://www.tritonus.org/plugins.html (tritonus_share.jar)
Using JavaFX (which is bundled with your JDK) is pretty simple.
You will need the following imports:
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.util.Duration;
import java.nio.file.Paths;
Steps:
Initialize JavaFX:
new JFXPanel();
Create a Media (sound):
Media media = new Media(Paths.get(filename).toUri().toString());
Create a MediaPlayer to play the sound:
MediaPlayer player = new MediaPlayer(media);
And play the Media:
player.play();
You can set the start/stop times as well with MediaPlayer.setStartTime() and MediaPlayer.setStopTime():
player.setStartTime(new Duration(Duration.ZERO)); // Start at the beginning of the sound file
player.setStopTime(1000); // Stop one second (1000 milliseconds) into the playback
Or, you can stop playing with MediaPlayer.stop().
A sample function to play audio:
public static void playAudio(String name, double startMillis, double stopMillis) {
Media media = new Media(Paths.get(name).toUri().toString());
MediaPlayer player = new MediaPlayer(media);
player.setStartTime(new Duration(startMillis));
player.setStopTime(new Duration(stopMillis));
player.play();
}
More info can be found at the JavaFX javadoc.