Java中与C# system.beep相当的方法是什么?

34

我正在开发一个Java程序,我需要按照指定频率和持续时间播放声音,类似于C#的System.Beep方法。我知道如何在C#中使用它,但我找不到在Java中实现这一点的方法。是否有等效的方法或其他方法可以做到这一点?

using System;

class Program
{
    static void Main()
    {
    // The official music of Dot Net Perls.
    for (int i = 37; i <= 32767; i += 200)
    {
        Console.Beep(i, 100);
    }
    }
}

6
据我所知,您只能发出默认的蜂鸣声:System.out.println("\007"); - SimpleVar
也许这个链接可以帮助你。 - Pau Kiat Wee
1
@YoryeNathan - 如果标准输出不会输出到控制台,那么就根本不会产生蜂鸣声。 - Stephen C
@YoryeNathan 这会在任何 IDE 中打印出 07 - Hunter McMillen
@HunterMcMillen 即使选择工具包解决方案(这也并不总是有效 - 因为这就是 Java 的本质),你仍然只能发出默认的蜂鸣声。 - SimpleVar
尝试一下这个平均律音阶 - trashgod
8个回答

61

你可以使用以下方法:

java.awt.Toolkit.getDefaultToolkit().beep();

编辑

如果你想播放长度不同且包含不同声音的任何内容,你应该考虑使用 Java MIDI 库。默认的蜂鸣声无法满足你的需求,因为你不能改变蜂鸣声的长度。

http://www.oracle.com/technetwork/java/index-139508.html


@AndrewLandsverk 是的,不同平台上的工具包确实很棘手。 - Hunter McMillen
2
@AndrewLandsverk FYI,自gnome 15.10和Java 7以来,一切都很顺利! - Yan Foto
@YanFoto,太好了,我得试试! - Andrew Landsverk
哇!那真是老派了。我已经20多年没用 AWT 了。 - David Urry

11

只需要打印它:

System.out.println("\007")

适用于Windows和MacOS操作系统。


4
如果使用java.exe执行,@devoured-elysium在W7上能够正常工作。如果使用javaw.exe或eclipse(即没有真正的控制台)执行,则没有蜂鸣声。 - RealHowTo
除非你的用户都是完全的音盲,否则你无法演奏出这样的曲调... - Stephen C

5

我编写了一个对我有效的函数。它使用了来自javax.sound.sampled的一堆东西。我将其调整为与我的系统自动从AudioSystem.getClip()获取新剪辑的音频格式配合使用。可能有各种方法可以使其更加健壮和高效。

/**
 * Beeps.  Currently half-assumes that the format the system expects is
 * "PCM_SIGNED unknown sample rate, 16 bit, stereo, 4 bytes/frame, big-endian"
 * I don't know what to do about the sample rate.  Using 11025, since that
 * seems to be right, by testing against A440.  I also can't figure out why
 * I had to *4 the duration.  Also, there's up to about a 100 ms delay before
 * the sound starts playing.
 * @param freq
 * @param millis 
 */
public static void beep(double freq, final double millis) {
    try {
        final Clip clip = AudioSystem.getClip();
        AudioFormat af = clip.getFormat();

        if (af.getSampleSizeInBits() != 16) {
            System.err.println("Weird sample size.  Dunno what to do with it.");
            return;
        }

        //System.out.println("format " + af);

        int bytesPerFrame = af.getFrameSize();
        double fps = 11025;
        int frames = (int)(fps * (millis / 1000));
        frames *= 4; // No idea why it wasn't lasting as long as it should.

        byte[] data = new byte[frames * bytesPerFrame];

        double freqFactor = (Math.PI / 2) * freq / fps;
        double ampFactor = (1 << af.getSampleSizeInBits()) - 1;

        for (int frame = 0; frame < frames; frame++) {
            short sample = (short)(0.5 * ampFactor * Math.sin(frame * freqFactor));
            data[(frame * bytesPerFrame) + 0] = (byte)((sample >> (1 * 8)) & 0xFF);
            data[(frame * bytesPerFrame) + 1] = (byte)((sample >> (0 * 8)) & 0xFF);
            data[(frame * bytesPerFrame) + 2] = (byte)((sample >> (1 * 8)) & 0xFF);
            data[(frame * bytesPerFrame) + 3] = (byte)((sample >> (0 * 8)) & 0xFF);
        }
        clip.open(af, data, 0, data.length);

        // This is so Clip releases its data line when done.  Otherwise at 32 clips it breaks.
        clip.addLineListener(new LineListener() {                
            @Override
            public void update(LineEvent event) {
                if (event.getType() == Type.START) {
                    Timer t = new Timer((int)millis + 1, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            clip.close();
                        }
                    });
                    t.setRepeats(false);
                    t.start();
                }
            }
        });
        clip.start();
    } catch (LineUnavailableException ex) {
        System.err.println(ex);
    }
}

编辑: 显然,有人改进了我的代码。我还没有尝试过,但你可以试一下: https://gist.github.com/jbzdak/61398b8ad795d22724dd


通过这个,我可以在Ubuntu 12.04下生成声音。谢谢! - Joanis
@Erhannis:我稍微改进了这个片段,现在在我的系统上听起来更清晰了——请随意将其纳入你的答案中:https://gist.github.com/jbzdak/61398b8ad795d22724dd - jb.
无法从已声明的变量访问Type。相反,只需使用类名调用它,因为它是静态的。因此,请将行事件中的event.Type.START更改为LineEvent.Type.START。 - ShihabSoft
@ShihabSoft 我...没有看到这样的一行代码?有event.getType() == Type.START,但那是不同的。 - Erhannis
抱歉,它不仅仅是Type.START,它还包括LineEvent.Type.START。 - ShihabSoft
1
@jb:对我来说,Erhannis的第一个解决方案更好——更流畅。 - mojmir.novak

4
我认为在可移植的Java中没有使用“beep”播放曲调的方法。你需要使用javax.sound.* API,除非你能找到一个简化操作的第三方库。如果你想尝试这种方法,那么这个页面或许会给你一些想法。 1 - 除非你的用户都是音盲。当然你可以用莫尔斯电码发出嘟嘟声,但那不是曲调。 2 - 显然,你可以调用Windows的beep函数。但那不具备可移植性。

4

另一个解决方案,依赖于Windows,是使用JNA并直接调用Windows中的Beep function,该函数可在kernel32中使用。不幸的是,在JNA的4.2.1版本中,Kernel32没有提供此方法,但您可以轻松地扩展它。

public interface Kernel32 extends com.sun.jna.platform.win32.Kernel32 {

        /**
         * Generates simple tones on the speaker. The function is synchronous; 
         * it performs an alertable wait and does not return control to its caller until the sound finishes.
         * 
         * @param dwFreq : The frequency of the sound, in hertz. This parameter must be in the range 37 through 32,767 (0x25 through 0x7FFF).
         * @param dwDuration : The duration of the sound, in milliseconds.
         */
        public abstract void Beep(int dwFreq, int dwDuration);
}

使用它:

static public void main(String... args) throws Exception {
    Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    kernel32.Beep(800, 3000);
}

如果你使用maven,你需要添加以下依赖项:
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.2.1</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>4.2.1</version>
</dependency>

以下是此解决方案的问题:1)它只能在Windows上运行。OP没有说明仅限于Windows的解决方案是否可接受。2)您依赖于一个内部API,该API可能会在未来的Java版本中更改或关闭。3)如果JVM被沙箱化,这很可能无法正常工作。(仅供参考)。 - Stephen C

0

0

0

使用Applet代替。您需要提供wav文件作为蜂鸣音频文件,但它可以工作。我在Ubuntu上尝试过:

package javaapplication2;

import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

public class JavaApplication2 {

    public static void main(String[] args) throws MalformedURLException {
        File file = new File("/path/to/your/sounds/beep3.wav");
        URL url = null;
        if (file.canRead()) {url = file.toURI().toURL();}
        System.out.println(url);
        AudioClip clip = Applet.newAudioClip(url);
        clip.play();
        System.out.println("should've played by now");
    }
}
//beep3.wav was available from: http://www.pacdv.com/sounds/interface_sound_effects/beep-3.wav

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