How to play a sound (alert) in a java application? [duplicate]
Asked Answered
C

5

32

I am working with a SMS handling, java based software and want to play a beep / alert sound whenever we receive a message. I tried looking at the java.sound libraries and could not find anything. I do not know if going the applet way of playing a sound will be okay in a java application! Are there any predefined sounds in any java libraries which we can call in an application? Any pointers will be appreciated!

Concerted answered 23/9, 2010 at 16:18 Comment(0)
I
61

If you just want to produce a beep or a quick alert, you can use the following code:

import java.awt.Toolkit;
Toolkit.getDefaultToolkit().beep();
Illsorted answered 23/9, 2010 at 16:24 Comment(4)
This might not work under Linux.Convolvulaceous
FYI, working fine on Windows 10. Thank youHaveman
works fine on ubuntu linuxNefertiti
not working on ubuntu 20Ruffle
M
42

You can generate your own sound if you looking for something less boring than a beep() without an external sound file.

import javax.sound.sampled.*;

public class SoundUtils {

  public static float SAMPLE_RATE = 8000f;

  public static void tone(int hz, int msecs) 
     throws LineUnavailableException 
  {
     tone(hz, msecs, 1.0);
  }

  public static void tone(int hz, int msecs, double vol)
      throws LineUnavailableException 
  {
    byte[] buf = new byte[1];
    AudioFormat af = 
        new AudioFormat(
            SAMPLE_RATE, // sampleRate
            8,           // sampleSizeInBits
            1,           // channels
            true,        // signed
            false);      // bigEndian
    SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
    sdl.open(af);
    sdl.start();
    for (int i=0; i < msecs*8; i++) {
      double angle = i / (SAMPLE_RATE / hz) * 2.0 * Math.PI;
      buf[0] = (byte)(Math.sin(angle) * 127.0 * vol);
      sdl.write(buf,0,1);
    }
    sdl.drain();
    sdl.stop();
    sdl.close();
  }
  
  public static void main(String[] args) throws Exception {
    SoundUtils.tone(1000,100);
    Thread.sleep(1000);
    SoundUtils.tone(100,1000);
    Thread.sleep(1000);
    SoundUtils.tone(5000,100);
    Thread.sleep(1000);
    SoundUtils.tone(400,500);
    Thread.sleep(1000);
    SoundUtils.tone(400,500, 0.2);

  }
}
Murchison answered 14/7, 2011 at 21:17 Comment(0)
C
8

The applet route should be fine (and is very straightforward). To avoid creating an Applet instance you can use the static newAudioClip method, and then call play() on the AudioClip created.

URL url = getClass().getResource("/foo/bar/sound.wav");
AudioClip clip = Applet.newAudioClip(url);
clip.play();

Here, the sound.wav file is bundled in the jar file in the foo/bar package that you create. A fully functional class (where the wav file is in the sounds package) would look like this:

package sounds;

import java.applet.Applet;
import java.applet.AudioClip;

public class PlaySound {

    public void PlayBeep() {        
        AudioClip clip = Applet.newAudioClip(getClass().getResource("/sounds/beep3.wav"));
        clip.play();
    }
}

Here, the path is given as /sounds/ because when you extract the jar, you'll see that the wav file is located in the first folder in the jar, which is sounds.

Coonhound answered 23/9, 2010 at 16:22 Comment(4)
any idea why this answer is not widely used? It seems extremely simple and useful...Greyso
This was an excellent solution for me.Malignity
This works in Linux.Sleeper
Worked very well at first attempt!!Fernandes
C
6

You can take a look at the beep method within the Toolkit class, as shown here

Countersubject answered 23/9, 2010 at 16:20 Comment(0)
M
3

If you want to use the sound package to play an arbitrary sound file, you can use the javax.sound.sampled package. Here is the code that will play a sound file:

private void playSound(File f) {
    Runnable r = new Runnable() {
        private File f;

        public void run() {
            playSoundInternal(this.f);
        }

        public Runnable setFile(File f) {
            this.f = f;
            return this;
        }
    }.setFile(f);

    new Thread(r).start();
}

private void playSoundInternal(File f) {
    try {
        AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(f);
        try {
            Clip clip = AudioSystem.getClip();
            clip.open(audioInputStream);
            try {
                clip.start();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                clip.drain();
            } finally {
                clip.close();
            }
        } catch (LineUnavailableException e) {
            e.printStackTrace();
        } finally {
            audioInputStream.close();
        }
    } catch (UnsupportedAudioFileException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Matchwood answered 23/9, 2010 at 16:25 Comment(7)
Can you explain why we need the thread to sleep after calling clip.start()?Pool
It's been a while since I wrote this code, but my guess is that it would probably work just as well with a Thread.yield().Matchwood
I was referring to why we need to block in the first place, but I realized it's probably because we'd close the line before it finishes playingPool
I think you actually needed to pass back to system resources in order for the clip to actually start.Matchwood
Yes, it would close the line before it finishes playing.Matchwood
I removed the Thread.sleep(100) and it works fine for me in a long running app. If running in a short test you might find that, without this sleep the app is actually closing and therefore terminates the thread ... maybe... so the sleep helps to keep a short lived app alive long enough for the sound to play? (but then drain() would keep the thread alive long enough to finish... hmmm - so maybe the sleep never had any purpose at all.Wordless
It didn't work without it. I ran this in a long-running app. The clip.start() would signal the clip to start, and then it acted like the clip.drain() canceled that before it could actually start. Once I put the Thread.sleep() call in, it played. It's quite possible that this was a bug which has been fixed since then.Matchwood

© 2022 - 2024 — McMap. All rights reserved.