AudioInputStream() does not stop - java

I have inserted a background audio into my program using AudioInputStream.
When I press the On, the background audio will play, and Off will stop playing the background audio.
Here is the part of my code for the audio playing part :
public void playSound(int i)
{
try
{
. //Others buttons sound
. //Others buttons sound
if(i == 3 || i == 4)
{
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("Background.wav"));
Clip clip3 = AudioSystem.getClip( );
clip3.open(audioInputStream);
if(i == 3)
{
clip3.loop(Clip.LOOP_CONTINUOUSLY);
clip3.start();
settingSubMenuItem3.setEnabled(false);
settingSubMenuItem4.setEnabled(true);
}
if(i == 4)
{
clip3.stop();
settingSubMenuItem3.setEnabled(true);
settingSubMenuItem4.setEnabled(false);
}
}
catch(Exception e)
{
System.out.println("Error with playing sound.");
e.printStackTrace();
}
}
And here is the ButtonListener part :
private class MenuItemListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == settingSubMenuItem3)
{
playSound(3);
}
if(e.getSource() == settingSubMenuItem4)
{
playSound(4);
}
}
}
My code can play the audio when I press On button, but when I press Off button, it does not work.
There is no error during compile and run.
What is the error of my code?

Your AudioInputStream variable, audioInputStream, and Clip variable, clip3, are local to the method. The object you are trying to stop is not the same as the one that's playing currently.
Make them class fields, check that they're not null before calling methods on them, don't create a new object if you're trying to stop the currently playing object, and you should be OK.
Something like:
public void playSound(int i) {
try {
// ...
if (i == 3 || i == 4) {
if (i == 3) {
audioInputStream = AudioSystem
.getAudioInputStream(new File("Background.wav"));
clip3 = AudioSystem.getClip();
clip3.open(audioInputStream);
clip3.loop(Clip.LOOP_CONTINUOUSLY);
clip3.start();
settingSubMenuItem3.setEnabled(false);
settingSubMenuItem4.setEnabled(true);
}
if (i == 4) {
if (clip3 != null && clip3.isActive()) {
clip3.stop();
settingSubMenuItem3.setEnabled(true);
settingSubMenuItem4.setEnabled(false);
}
}
}
} catch (Exception e) {
System.out.println("Error with playing sound.");
e.printStackTrace();
}
}
Again, making audioInputStream and clip3 non-static class fields.
As an aside, I would avoid using "magic" numbers such as 3 and 4 as you are doing as this may become a devil to debug 6 months from now. Instead give each JButton its own Action. It deserves no less.

Related

Audio not playing within thread Android

So i've got an audio file that i'd like to play within a thread, this is where i've left the comment // Tried playing audio here . But the even with the logic to make sure that it only plays once no audio is being played. Instead it seems like it's forcing the application to skip frames instead causing the game to have a few glitches because of the inconsistent frame rate.
Here's the code which i've been using.
while (isRunning) {
// Go back to the if statement and check if the surface still isn't valid
if (!mySurfaceHolder.getSurface().isValid())
continue;
// Lock the canvas for editing, make changes and unlock with new changes
final Canvas canvas = mySurfaceHolder.lockCanvas();
canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite);
// Create the block to check the answer
answerObject = new AnswerObject(canvas);
animalObject.move(canvas, tilt);
if(answerObject.onCollision(animalObject) != null){
// Inside of box else is outside of box
if (answerObject.onCollision(animalObject)) {
// If the animal is part of that enviroment
if (verifyEnviroment(enviromentObject.getAnimals())){
isCorrect = true;
} else {
isCorrect = false;
}
} else {
// If the animal is part of that enviroment
if (!verifyEnviroment(enviromentObject.getAnimals())){
// Tried playing audio here
isCorrect = true;
} else {
// Tried playing audio here
isCorrect = false;
}
}
gameActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (isCorrect){
scoreObject.setScore(10);
} else {
healthObject.setHealth(10);
healthObject.setHealthImgs(healthObject.getHealth());
if (healthObject.getHealth() <= 0){
isRunning = false;
}
}
resetGameObjects();
}
});
}
mySurfaceHolder.unlockCanvasAndPost(canvas);
}

How to use a .mp3 file in java?

I'm using java to try and make an alarm of sorts. I want to input a time and then when it hits zero, play a specific .mp3. The countdown works fine, but when it hits zero and tries to play the mp3, it can't find the file. Advice? I've already searched the site and can't find anything simple enough for me to use (I'm a beginner). Here's what I got so far:
public static void main(String[] args) {
int timer;
File song = new File("C:/Users/N/Documents/Random/Handies/Proj/Song.mp3");
timer = 1;
timer*=1;
while (timer != 0)
{
try
{
Thread.sleep(1000);
} catch (InterruptedException e) {}
timer -= 1;
System.out.println(timer);
}
if (timer == 0)
Play(song);
}
public static void Play(File song)
{
try
{
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(song));
clip.start();
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
With JavaFX you can easily play the MP3 like this:
public class Test extends javafx.application.Application {
#Override
public void start(Stage primaryStage) throws Exception {
File file = new File("/path/test.mp3");
Media media = new Media(file.toURI().toString());
MediaPlayer mediaPlayer = new MediaPlayer(media);
mediaPlayer.play();
}
}
I usually find it hard using AudioSystem for this kind of thing.

JAVA - Boolean correction - Still going on when pressing Play

So im pretty close to my end and I can't figure out why its doing like this. Maybe because im stupid right now after coding a while. however. So I have two files that should be allowed to my program. The first one is a MP3 and the Other one is Wav. I got them to work. By that I mean if I choose Wav file, the sound comes, if I choose the mp3 it works so there is no problem with that but the problem is right now is when pressing Open (-> browersing a file) and then press play, the sound should come, and yes it does. so when I open a another file for exemple a new song. then press play. the song is playing with the first song which makes it two tracks at the same time and I want it to make -> when one song is playing then play. and if I choose new song and press play, then the first song should go away. I think im pretty close but yeah. However I have done this
static boolean status = true;
btnPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnPlay) {
if(!status) {
clip.start();
lblPlaying.setText("Enjoy the music!");
} else if(status == true) {
mp3_player.play();
lblPlaying.setText("Enjoy the music!");
}
}
}
});
public void Choose() throws IOException {
String userDir = System.getProperty("user.home");
JFileChooser fileChooser = new JFileChooser(userDir +"/Desktop");
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
System.out.println(selectedFile.getName());
String ext = selectedFile.getPath();
if(ext.endsWith(".mp3")) { // For mp3
status = true;
mp3_player = new MP3Player(selectedFile);
lblPlayURL.setText(selectedFile.getName());
}
else if(ext.endsWith(".wav")) {
status = false; //For .Wav
try {
AudioInputStream stream;
AudioFormat format;
DataLine.Info info;
clip = clip;
stream = AudioSystem.getAudioInputStream(selectedFile);
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
lblPlayURL.setText(selectedFile.getName());
}
catch(Exception e) {
//whatevers
}
}
}
}
}
To make the story shorter so what I have done is I have a variable that is set boolean to false. so whenever False is running it takes the Wav. when True its mp3. but as I said. the problem is sitting when.
Choose a song
Press play for the song
Choose new song
Press play for the new song (and here is where the 1st one song still going on which I don't want to)
Have I done something wrong with booleans?
EDIT: Forgot to add the open button:
btnOpen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnOpen) {
try {
Choose();
}
catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
}
edit : Stop method
,
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnStop) {
if(!status) {
clip.stop();
lblPlaying.setText("Nothing plays right now!");
} else if(status == true) {
mp3_player.stop();
lblPlaying.setText("Nothing plays right now!");
}
}
}
});
You need to have another flag which tells you if it's playing or not. Then before you start the song, check the flag, then STOP any music if it's true, then start the new one.
You essentially have a design flaw. The system is capable of playing multiple songs at once, it didn't know you wanted to stop one of them.

manipulating time in java swing

I was trying to manipulate an amateur animation using Swing in Java. The goal was to start an animation if I hover over a certain button. That was easy. But the problem is, I want to manipulate the speed of the timer of the animation according to the coordinates of the button.
For example, the more right I go on the button the more speedy the animation gets (delay time decreases) and vice-versa. The code I wrote works if I move the arrow out of the button then enter again. Then the delay changes according to co-ordinates. But not if I move the arrow within the region of the button. I used mouseEntered here. That may cause cause the problem. But the mouseMove function seems not to work too.
Here's my code:
private void jButton1MouseEntered(java.awt.event.MouseEvent evt)
{
// TODO add your handling code here:
PointerInfo inf = MouseInfo.getPointerInfo();
Point a = inf.getLocation();
double x = a.getX();
final int n = (int) (x - 161);
//String str=""+x;
//Output.setText(str);
ActionListener taskPerformer = null;
taskPerformer = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent evt)
{
//...Perform a task...
//if(t>0)timer.setDelay(1000);
if (t > 0)
{
timer.setDelay(500 + 50 * n);
}
if (label1 == 0)
{
jTextField1.setText(" A");
}
else if (label1 == 1)
{
jTextField1.setText(" B");
}
else if (label1 == 2)
{
jTextField1.setText(" C");
}
else if (label1 == 3)
{
jTextField1.setText(" D");
}
else if (label1 == 4)
{
jTextField1.setText(" E");
}
else if (label1 == 5)
{
jTextField1.setText(" F");
}
else if (label1 == 6)
{
jTextField1.setText(" G");
}
if (label1 >= 7)
{
label1 = 0;
}
else
{
label1++;
}
t++;
//System.out.printf("Reading SMTP Info. %d\n",x);
//System.out.printf("Reading SMTP Info. %d\n",label1t);
//jLabel3.setText("fsd");
}
private Object getContentPane()
{
throw new UnsupportedOperationException("Not supported yet.");
}
};
timer = new Timer(500, taskPerformer);
timer.start();
//timer.setRepeats(false);
try
{
Thread.sleep(10);
}
catch (InterruptedException ex)
{
Logger.getLogger(Keyboard_Gui.class.getName()).log(Level.SEVERE, null, ex);
}
}
But the mouseMove function seems not to work too.
The mouseMoved event is generated by a MouseMotionListener (not a MouseListener) so you will also need to implement that listener to manipulate the Timer interval.

How to delay a board game between moves so a sound can play

In the board game I am designing, each user has a grid with 100 cells. The user clicks a cell in the computer's grid, which makes a sound and changes to a different colour. The computer then automatically clicks a cell in the user's grid, which makes a sound and changes to a different colour.
The user's clicks are dealt with via the MouseListener (and the MouseClicked method). Currently, the last thing the method does is call the computerMove() method. This method executes and performs the computer move before giving changing the current player back to human. The game proceeds when the human makes another mouse click.
Ideally, I'd like to have a pause (perhaps a second) between each player move. However, due to the fact the computerMove method is being called inside the MouseClicked method, this is proving troublesome. By using Thread.sleep and even a TimerTask, the best I can do is to slow the human player's move down. However, as soon as the player makes a mouse click, the computer instantaneously responds.
Does anybody have any suggestions as to how I could implement a delay? Do I need to change how I am calling the methods?
ComputerMove method:
public void computerMove() {
if (currentTurn == computer) {
int xPos = randomGenerator.nextInt(10);
int yPos = randomGenerator.nextInt(10);
LogicCell attackedCell = new LogicCell(xPos, yPos);
playerGridLogic.addCellsThatHaveBeenAttacked(attackedCell);
if (playerGridLogic.getCellsWithShips().contains(attackedCell)) {
playerGrid.getCellArray()[xPos][yPos].setBackground(Color.ORANGE);
hitSound();
}
else {
playerGrid.getCellArray()[xPos][yPos].setBackground(Color.MAGENTA);
missSound();
}
nextTurn();
}
}
Corresponding MouseClick method:
#Override
public void mouseClicked(MouseEvent e) {
if (allComputerShipsPlaced && currentTurn == human) {
ViewCell currentCell = (ViewCell) e.getSource();
xPos = currentCell.getXPos();
yPos = currentCell.getYPos();
LogicCell attackedCell = new LogicCell(xPos, yPos);
computerGridLogic.addCellsThatHaveBeenAttacked(attackedCell);
if (computerGridLogic.getCellsWithShips().contains(attackedCell)) {
cellArray[xPos][yPos].setBackground(Color.ORANGE);
hitSound();
}
else {
cellArray[xPos][yPos].setBackground(Color.MAGENTA);
missSound();
}
nextTurn();
computerMove();
}
}
missSound method() (hitSound is very similar):
public static void missSound() {
try {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("water-splash.wav")));
clip.start();
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
Edit: I've tried changing the sound classes to this, but to no avail:
public static void hitSound()
{
try
{
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("bomb-explosion.wav")));
clip.start();
LineListener listener = new LineListener() {
public void update(LineEvent event) {
if (event.getType() != Type.STOP) {
return;
}
try {
queue.take();
} catch (InterruptedException e) {
//ignore this
}
}
};
clip.addLineListener(listener);
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
You should be able to add a listener and react to the end of the sound.
See this question: how can I wait for a java sound clip to finish playing back?
This works for me:
public class Test {
public static void main(String[] args) {
final Object foo = new Object();
Clip clip;
try {
clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("go.wav")));
clip.addLineListener(new LineListener() {
public void update(LineEvent event) {
if(event.getType() == LineEvent.Type.STOP){
System.out.println("done playing");
synchronized(foo) {
foo.notify();
}
}
}
});
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
synchronized(foo) {
try {
foo.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I would consider calling computerMove inside nextTurn, and do the waiting inside nextTurn.
You could use Thread.sleep in computerMove() to pause the execution. You can use clip.getMicrosecondsLength to get the length of the sound effect in microseconds. Multiply it with 1000 and pass it to sleep to wait for the sound effect to finish.
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("water-splash.wav")));
clip.start();
int lengthInMilliseconds = clip.getMicrosecondLength() * 1000;
Thread.sleep(lengthInMilliseconds);

Categories