Java-эквивалент C # system.beep?

Я работаю над программой 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);
    }
    }
}

person Glen654    schedule 27.05.2012    source источник
comment
Насколько мне известно, вы можете подавать только звуковой сигнал по умолчанию: System.out.println("\007");   -  person SimpleVar    schedule 27.05.2012
comment
Возможно, это поможет.   -  person Pau Kiat Wee    schedule 27.05.2012
comment
@YoryeNathan - если стандартный вывод не идет на консоль, он вообще не будет издавать звуковой сигнал.   -  person Stephen C    schedule 27.05.2012
comment
@YoryeNathan Это печатает 07 внутри любой IDE.   -  person Hunter McMillen    schedule 27.05.2012
comment
@HunterMcMillen, даже если вы используете решение с инструментарием (которое тоже не всегда работает - потому что это просто природа java), вы все равно можете подавать только звуковой сигнал по умолчанию.   -  person SimpleVar    schedule 27.05.2012
comment
Попробуйте эту шкалу равного темперирования.   -  person trashgod    schedule 27.05.2012


Ответы (8)


Я не думаю, что есть способ проигрывать мелодию 1 со звуковым сигналом в портативном 2 Java. Думаю, вам нужно будет использовать javax.sound.* API ... если только вы не найдете стороннюю библиотеку, которая упростит вам задачу.

Если вы хотите пойти по этому пути, то эта страница может дать вам идеи.


1 - Если только ваши пользователи не глухие. Конечно, вы можете делать такие вещи, как гудок азбукой Морзе ... но это не мелодия.

2 - Очевидно, вы можете выполнять собственные вызовы звуковой функции Windows. Но это не переносимо.

person Stephen C    schedule 27.05.2012

Вы можете использовать это:

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

ИЗМЕНИТЬ

Если вы пытаетесь воспроизвести что-нибудь длительное и с разными звуками, вам действительно стоит заглянуть в библиотеку Java MIDI. Звуковой сигнал по умолчанию не сможет удовлетворить ваши потребности, так как вы не можете изменить его длину.

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

person Hunter McMillen    schedule 27.05.2012
comment
@AndrewLandsverk Да, инструментарий действительно сложен на разных платформах - person Hunter McMillen; 27.05.2012
comment
@AndrewLandsverk К вашему сведению, начиная с gnome 15.10 и Java 7, все работает отлично! - person Yan Foto; 21.05.2016
comment
@YanFoto милая, надо будет попробовать! - person Andrew Landsverk; 22.05.2016
comment
Вау! Это старая школа. Я не использовал AWT более 20 лет. - person David Urry; 15.07.2020

Просто распечатайте это:

System.out.println("\007")

Работает на Windows и MacOS.

person Adrian    schedule 19.04.2013
comment
@ devoured-elysium, работает на W7, если выполняется с java.exe. Если выполняется с помощью javaw.exe или eclipse (т.е. без настоящей консоли), звуковой сигнал не подается. - person RealHowTo; 18.03.2014
comment
И вы не можете сыграть такую ​​мелодию ... если только все ваши пользователи не глухи по тону. - person Stephen C; 21.02.2018

Я собрал функцию, которая у меня работает. Он использует кучу вещей из 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

person Erhannis    schedule 17.03.2014
comment
Благодаря этому я мог генерировать звук в Ubuntu 12.04. Спасибо! - person Joanis; 05.09.2014
comment
@Erhannis: Я немного улучшил этот фрагмент, и теперь он звучит яснее в моей системе - не стесняйтесь включить его в свой ответ: gist.github.com/jbzdak/61398b8ad795d22724dd - person jb.; 20.03.2015
comment
Невозможно получить доступ к Type из объявленной переменной. Вместо этого просто вызовите его с именем класса, потому что он статический. Поэтому измените строку event.Type.START на LineEvent.Type.START - person ShihabSoft; 06.08.2015
comment
@ShihabSoft Я ... не вижу такой строчки? Есть event.getType() == Type.START, но это другое. - person Erhannis; 06.08.2015
comment
Извините, это не просто Type.START его LineEvent.Type.START - person ShihabSoft; 07.08.2015
comment
@jb: для меня первое решение от Erhannis работает лучше - плавнее. - person mojmir.novak; 09.05.2017

Другое решение, зависящее от Windows, - использовать JNA и напрямую вызывать Windows Функция звукового сигнала, доступная в kernel32. К сожалению, Kernel32 в JNA не предоставляет этот метод в 4.2.1, но вы можете легко расширить его.

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>
person EFalco    schedule 15.02.2017
comment
Проблемы с этим решением: 1) Работает только в Windows. OP не утверждает, что решение только для Windows приемлемо. 2) Вы зависите от внутреннего API, который может измениться или быть отключен в будущей версии Java. 3) Это вряд ли сработает, если JVM находится в песочнице. (Просто говорю). - person Stephen C; 21.02.2018

Вы можете получить ссылку на класс Toolkit здесь, где определен метод beep().

person Bhavik Ambani    schedule 27.05.2012

Вместо этого используйте 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
person Nav    schedule 24.01.2019

Если вы используете виджеты SWT, вы можете сделать это следующим образом (СИСТЕМНЫЙ ЗВУК!)

org.eclipse.swt.widgets.Display.getCurrent().beep();

если вам нужен НАТУРАЛЬНЫЙ JAVA, вот класс для него: https://github.com/marcolopes/dma/blob/master/org.dma.java/src/org/dma/java/util/SoundUtils.java

person marcolopes    schedule 15.11.2019