Java equivalente de C#system.beep?
audio frequency (7)
Estoy trabajando en un programa Java, y realmente necesito poder reproducir un sonido por una cierta frecuencia y duración, de manera similar al método c # System.Beep, sé cómo usarlo en C #, pero no puedo encontrar Una forma de hacer esto en Java. ¿Hay algún equivalente, u otra forma de hacer esto?
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);
}
}
}
He pirateado una función que funciona para mí. Utiliza un montón de cosas de javax.sound.sampled
. Lo he adaptado para que funcione con el formato de audio que mi sistema entrega automáticamente un nuevo Clip de AudioSystem.getClip()
. Probablemente hay muchas formas de hacerlo más robusto y más eficiente.
/**
* 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);
}
}
EDITAR: Al parecer, alguien ha mejorado mi código. No lo he probado todavía, pero inténtelo: https://gist.github.com/jbzdak/61398b8ad795d22724dd
No creo que haya una forma de reproducir las melodías 1 con "beep" en la Java portátil 2 . Necesitará usar las API javax.sound.*
Creo que ... a menos que pueda encontrar una biblioteca de terceros que simplifique las cosas para usted.
Si desea seguir este camino, esta página puede darle algunas ideas.
1 - A menos que sus usuarios sean todos sordos. Por supuesto, puedes hacer cosas como emitir un pitido en el código Morse ... pero eso no es una melodía.
2 - Obviamente, usted podría hacer llamadas nativas a una función de sonido de Windows. Pero eso no sería portátil.
Otra solución, dependiente de Windows, es usar JNA y llamar directamente a la función Windows Beep , disponible en kernel32. Desafortunadamente, Kernel32 en JNA no proporciona este método en 4.2.1, pero puede extenderlo fácilmente.
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);
}
Para usarlo:
static public void main(String... args) throws Exception {
Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
kernel32.Beep(800, 3000);
}
Si usas maven tienes que agregar las siguientes dependencias:
<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>
Puede obtener la referencia de la clase de Toolkit here , donde se define el método beep()
.
Puedes usar esto:
java.awt.Toolkit.getDefaultToolkit().beep();
EDITAR
Si está intentando reproducir algo de duración y con diferentes sonidos, debería mirar la biblioteca Java Java. El pitido predeterminado no podrá satisfacer sus necesidades ya que no puede cambiar la duración del pitido.
Solo imprímelo:
System.out.println("/007")
Funciona al menos en MacOS.
//Here''s the full code that will DEFINITELY work: (can copy & paste)
import java.awt.*;
public class beeper
{
public static void main(String args[])
{
Toolkit.getDefaultToolkit().beep();
}
}