I did sound in a REALLY wierd way, do you think that there may be a way to loop it? cuz it only plays once then stops. Here is code for sound:
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class Sound {
private final static int BUFFER_SIZE = 12800000;
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;
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();
}
}
To activate it i do:
new Thread(new Runnable() {
public void run() {
Sound.playSound("hurt.au");
}
}).start();
(if i do just Sound.playSound("hurt.au"); the game freezes because the sound plays on the games main thread so i put the sound in it's own thread to save the game from freezing)
So the question is, how do i loop it?
You will need some sort of test to see whether the sound currently playing is finished or not. If you are making a game, I might suggest using some libraries to make it easier. Such as slick2d. This has inbuilt functions to loop a sound instead of just playing it once. If you choose not to, you will have to keep track of the thread and on every update of your game state look at the sound object and ask the sourceline if it has finished playing or not. If it has then sourceline.start() else no-op. You could also put the thread inside the sound.playsound method itself, thereby making your code a little bit less coupled.
http://www.slick2d.org/
I really recommend using a 3rd party library to make it easier on yourself though.
Related
So I have this code, and I would like to know how could I join it with the rest of my game, 'cause the only way it plays sound now is by selecting this class as a launcher. Also, could I get some info, what exactly is changed and why. I feel like I should get a better understanding of this code, since I just found the code, and pasted it :D
Code:
package main;
import main.Handler;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioPlayer implements LineListener {
boolean playCompleted;
void play(String audioFilePath) {
File audioFile = new File(audioFilePath);
try {
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.addLineListener(this);
audioClip.open(audioStream);
audioClip.start();
while (!playCompleted) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
audioClip.close();
} catch (UnsupportedAudioFileException ex) {
System.out.println("The specified audio file is not supported.");
ex.printStackTrace();
} catch (LineUnavailableException ex) {
System.out.println("Audio line for playing back is unavailable.");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("Error playing the audio file.");
ex.printStackTrace();
}
}
public void update(LineEvent event) {
LineEvent.Type type = event.getType();
if (type == LineEvent.Type.START) {
System.out.println("Playback started.");
} else if (type == LineEvent.Type.STOP) {
playCompleted = true;
System.out.println("Playback completed.");
}
}
public static void main(String[] args) {
String audioFilePath = "res/music/dark_theme.wav";
AudioPlayer player = new AudioPlayer();
player.play(audioFilePath);
}
}'
This class is a fairly normal class to use: Construct an instance, call some methods, and it does what it is expected to do. When you are using it as a launcher, all you're doing is calling the main method, which serves as an example of how to use this class:
public static void main(String[] args) {
String audioFilePath = "res/music/dark_theme.wav";
AudioPlayer player = new AudioPlayer();
player.play(audioFilePath);
}
Just construct an instance, and call play() on it with the name of the audio file intended.
However, be warned that this class isn't really a good example of how to go about doing this, for a few reasons:
It blocks while playing, meaning that you can't start playing sound and go about doing something different at the same time.
It can't play a sound more than once without incurring issues.
So, let's modify this class to not have these issues. This class will let you load a clip into memory, and start it asynchronously (meaning that you start it and then your program keeps running). The start() method starts it to play once, and the loop() method loops it forever. stop() is self-explanatory, and cleanup() should be called to release resources once you no longer need this audio clip. (Of course, if you intend to start playing the clip again soon, you should not cleanup() at that point).
import main.Handler;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioPlayer{
Clip audioClip;
boolean playCompleted;
String path;
public AudioPlayer(String path){
this.path = path;
File audioFile = new File(path);
try {
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
} catch (UnsupportedAudioFileException ex) {
System.out.println("The specified audio file is not supported.");
ex.printStackTrace();
} catch (LineUnavailableException ex) {
System.out.println("Audio line for playing back is unavailable.");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("Error playing the audio file.");
ex.printStackTrace();
}
}
void play() {
audioClip.start();
}
void loop(){
audioClip.loop(Clip.LOOP_CONTINUOUSLY);
}
void stop(){
audioClip.stop();
}
void cleanup(){
audioClip.close();
}
public static void main(String[] args) throws InterruptedException {
String audioFilePath = "res/music/dark_theme.wav";
AudioPlayer player = new AudioPlayer(audioFilePath);
player.play();
// give the sound time to play
while(true){
Thread.sleep(1000);
}
}
}
Hi Stackoverflow!
So basically, I have two audio clips going on in my Java program and I want one of them to stop at a certain time and the other to start at a certain time.
I'll try to explain the code the best I can.
http://pastebin.com/1zGdb30x Music.java
package testingground;
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Music {
public void musictwo() {
URL url;
try {
url = new URL("file:///D:/Yes/GUI/song.wav");
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.
getAudioInputStream( url );
clip.open(ais);
clip.loop(100);
} catch (UnsupportedAudioFileException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void musicone() {
URL url;
try {
url = new URL("file:///D:/Yes/GUI/rival.wav");
Clip clip = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.
getAudioInputStream( url );
clip.open(ais);
clip.loop(100);
} catch (UnsupportedAudioFileException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
http://pastebin.com/nGm4DZfr Program.java
package testingground;
import javax.swing.JOptionPane;
public class Program {
public static void main(String[] args) {
System.out.println("The first song should play now!");
Music a = new Music();
a.musicone();
System.out.println("The second song should play now!");
a.musictwo();
JOptionPane.showMessageDialog(null,"Press 'ok' to end the application.");
}
}
In Music.java, I have the audio files working and they are only local .wav files that are only available on my computer. In program.java, the output is musicone and musictwo both play at the same time. Is there a way so that muscone plays, stops, then musictwo plays?
Things I have tried-
- Have an if and else statement in program.java to execute clip.stop(). No errors, it just didn't work.
- Have an if and else boolean from program.java to execute clip.stop() in Music.java. No syntax errors, it just didn't work.
The way I understand your question, you can use a LineListener.
Just, for example, here is a class that goes through a List, playing the next stream each time the current one completes:
class Playlist implements LineListener {
private final List<AudioInputStream> list = new ArrayList<>();
private Clip clip;
private int next;
#Override
public void update(LineEvent evt) {
if(evt.getType() == LineEvent.STOP) {
try {
playNext();
} catch(LineUnavailableException | IOException e) {
e.printStackTrace();
}
}
}
void enqueue(AudioInputStream ais) {
synchronized(this) {
list.add(ais);
}
}
void playNext() throws LineUnavailableException, IOException {
synchronized(this) {
if(list.isEmpty()) {
throw new IllegalStateException();
}
if(clip != null) {
if(clip.isRunning()) clip.stop();
if(clip.isOpen()) clip.close();
}
clip = AudioSystem.getClip();
clip.addLineListener(listener);
try {
clip.open(list.get(next));
} finally {
next = (next + 1) % list.size();
}
clip.start();
}
}
}
I have some code that serves as a super basic music player:
import java.io.File;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class MusicPlayer{
private Clip c;
private boolean playing;
public MusicPlayer(){
playing = false;
}
public void play(String fileName) {
if(playing == false){
try {
c.drain();
c.flush();
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(fileName));
c = AudioSystem.getClip();
c.open(audioInputStream);
c.start();
playing = true;
} catch(Exception ex) {
System.out.println("Error with playing sound:" + ex);
ex.printStackTrace();
}
}
}
public void stop(){
if(playing == true){
c.stop();
playing = false;
}
}
}
The problem is that if I try to open too many wav files, the program crashes with an OutOfMemoryError. Giving the program more memory to work with (less than ideal to begin with) still means that the program runs slower each time a new file is opened. You can see I tried to solve this with:
c.drain();
c.flush();
but plainly this is not enough. Any help is appreciated!
I have a character quotes application in which the GUI class calls a player class that handles the .wav files. A user uses a radio button to select a quote and hits the play button to initiate. The application works fine when the path to the .wav is defined as an absolute path on the system. I want to incorporate the .wav files into a package my.sounds as "/my/sounds/anyfilename.wav" I know that I need to use the getResourceAsStream() method but I don't know how to incorporate it into the GUI class when calling the Player class. Again, the Player class works fine with absolute paths. The error is a file not found error.
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
if (jRadioButton1.isSelected()){
new Player("/my/sounds/fear_converted.wav").start();
}
else if (jRadioButton2.isSelected()){
new Player("C:/Users/joel.ramsey/Desktop/Audio for Quotes Program/initiated_converted.wav").start();
}
else if (jRadioButton3.isSelected()){
new Player("C:/Users/joel.ramsey/Desktop/Audio for Quotes Program/fight_converted.wav").start();
}
else if (jRadioButton10.isSelected()){
new Player("C:/Users/joel.ramsey/Desktop/Audio for Quotes Program/incharge_converted.wav").start();
}
else if (jRadioButton11.isSelected()){
new Player("C:/Users/joel.ramsey/Desktop/Audio for Quotes Program/break_converted.wav").start();
}
Okay, I took advice and tried to implement a .getResource method but its still not finding the file in the package directory "/my/sounds"
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
if (jRadioButton1.isSelected()){
URL resource = getClass().getResource("/my/sounds/fear_converted.wav");
new Player("/my/sounds/fear_converted.wav").start();
}
For those who were asking, the Player class is below. Again, it works fine with an absolute path to the file on the client. I didn't make it but it works if I call the .start() method.
package my.quotesbutton;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Player extends Thread {
private String filename;
private Position curPosition;
private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb
enum Position {
LEFT, RIGHT, NORMAL
};
public Player(String wavfile) {
filename = wavfile;
curPosition = Position.NORMAL;
}
public Player(String wavfile, Position p) {
filename = wavfile;
curPosition = p;
}
public void run() {
File soundFile = new File(filename);
if (!soundFile.exists()) {
System.err.println("Wave file not found: " + filename);
return;
}
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline
.getControl(FloatControl.Type.PAN);
if (curPosition == Position.RIGHT)
pan.setValue(1.0f);
else if (curPosition == Position.LEFT)
pan.setValue(-1.0f);
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
I think you need somthing like this
URL resource = Example.class.getResource("/res/1.jpg");
where /res/1.jpg is file in my project. Then you can get or File, or path to it, for your purposes
you can read this question
EDIT: Next code works fine for your Player class, just use resource.getFile() instead of resource.toString();
URL resource = QuotesButtonUI.class.getResource("/my/sounds/fear_converted.wav");
String file = resource.getFile();
Player p = new Player(file);
p.start();
Change your Player class to take a URL as an argument to its constructor, instead of a String. (A String could be anything, anyway, so it's not a good idea.)
i tried to search up online there are very limited resources. in the action Performed Method:
actionPerformed(){
---------------
new Sound();}
and in Sound class
public Sound(){
try {
String filePath="path\\file.wav";
File path= new File(filePath);
AudioInputStream stream;
AudioFormat format;
DataLine.Info info;
Clip clip;
stream = AudioSystem.getAudioInputStream(path);
format = stream.getFormat();//becomes formatted
info = new DataLine.Info(Clip.class, format);// info
clip = (Clip) AudioSystem.getLine(info);// casting for clip
clip.open(stream); // clip opens stream with path
clip.start();
}
catch (Exception e) {
System.out.println("errors");
}
}
Thank you.
As per the Javadoc of the .start() method:
Allows a line to engage in data I/O. If invoked on a line that is
already running, this method does nothing. Unless the data in the
buffer has been flushed, the line resumes I/O starting with the first
frame that was unprocessed at the time the line was stopped. When
audio capture or playback starts, a START event is generated.
There is no mention of the audio being played in an asynchronous manner. This means that your sound will be tackled by the thread which calls the start method, which since you are calling it in your event handler, will eventually mean that your Event Dispatching Thread is taking care of playing audio.
This thread is also responsible for drawing stuff on screen, so any other thing that runs on it, audio in your case, will have a negative effect on your rendering.
You could use some code like below (taken from here) to make your audio be played on a separate thread. This should cater for your lagging problems.
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AePlayWave extends Thread {
private String filename;
private Position curPosition;
private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb
enum Position {
LEFT, RIGHT, NORMAL
};
public AePlayWave(String wavfile) {
filename = wavfile;
curPosition = Position.NORMAL;
}
public AePlayWave(String wavfile, Position p) {
filename = wavfile;
curPosition = p;
}
public void run() {
File soundFile = new File(filename);
if (!soundFile.exists()) {
System.err.println("Wave file not found: " + filename);
return;
}
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat();
SourceDataLine auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline
.getControl(FloatControl.Type.PAN);
if (curPosition == Position.RIGHT)
pan.setValue(1.0f);
else if (curPosition == Position.LEFT)
pan.setValue(-1.0f);
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try {
while (nBytesRead != -1) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
auline.drain();
auline.close();
}
}
}
You might want to check out the Lightweight Java Game Library's OpenAL bindings.
It worked very nicely for me when I had to write a game with a large number of sound files.
Other than that, Clips are named Clips for a reason; they're supposed to be very brief and very small, as they're loaded instead of streamed in real-time.
LWJGL:
http://www.lwjgl.org/