如何在Java应用程序中播放声音(警报)?

30

我正在使用一款基于Java的短消息处理软件,并希望在接收到消息时播放提示音。我尝试查找Java.sound库,但没有找到任何有用的信息。我不确定在Java应用程序中使用applet播放声音是否可行!是否有任何预定义音频可以在应用程序中调用?任何指针将不胜感激!

5个回答

59
如果您只想发出蜂鸣声或快速警报,可以使用以下代码:
import java.awt.Toolkit;
Toolkit.getDefaultToolkit().beep();

4
这可能在 Linux 下无法运行。 - Augustin
2
FYI,Windows 10 上运行良好。谢谢。 - Nabin
8
导入java.awt.Toolkit库。 - Lei Yang
在Ubuntu Linux上运行良好。 - Pedro Siqueira
2
无法在Ubuntu 20上工作。 - withoutOne

42

如果你想要比beep()更有趣的声音,而又不需要外部声音文件,你可以自己生成声音。

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);

  }
}

8

这个小程序路线应该很好(也很简单)。为了避免创建Applet实例,你可以使用静态的newAudioClip方法,然后在创建的AudioClip上调用play()方法。

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

在这里,sound.wav文件被打包在你创建的foo/bar包中的jar文件中。一个完全功能的类(其中wav文件在sounds包中)将如下所示:

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();
    }
}

在这里,路径被指定为/sounds/,因为当你提取jar文件时,你会发现wav文件位于jar的第一个文件夹中,即sounds


2
有什么想法为什么这个答案没有被广泛使用?它看起来非常简单和有用... - RaKXeR
1
这对我来说是一个非常出色的解决方案。 - Sam Washburn
1
这在Linux中有效。 - Nav
第一次尝试就非常成功!! - JRichardsz

6
您可以查看Toolkit类中的beep方法,如此处所示:这里

3
如果你想使用声音包播放任意的音频文件,可以使用javax.sound.sampled包。以下是播放音频文件的代码:
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(); } }

调用 clip.start() 后,为什么我们需要让线程休眠呢? - lucks
自从我写了这段代码以来已经有一段时间了,但我的猜测是,使用 Thread.yield() 也可以同样有效地工作。 - Erick Robertson
我认为你实际上需要将系统资源传回,以便剪辑实际上开始。 - Erick Robertson
1
是的,它会在播放完成之前关闭该行。 - Erick Robertson
我移除了Thread.sleep(100),在我的长时间运行的应用中它运行得很好。如果在一个短暂的测试中运行,你可能会发现,没有这个sleep,应用实际上会关闭,从而终止线程...也许...所以这个sleep有助于保持一个短暂的应用活动足够长的时间来播放声音?(但是,drain()将保持线程活动足够长的时间来完成...嗯嗯 - 所以也许这个sleep从来没有任何目的。 - undefined
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接