2012-05-27 23 views
17

Sto lavorando su un programma Java e ho davvero bisogno di essere in grado di riprodurre un suono con una certa frequenza e durata, in modo simile al metodo C# System.Beep, so come usarlo in C#, ma posso ' t trovare un modo per farlo in Java. C'è qualche equivalente, o un altro modo per farlo?Equivalente Java di C# system.beep?

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

Per quanto ne so, è possibile un segnale acustico solo il segnale acustico di default : 'System.out.println (" \ 007 ");' – SimpleVar

+0

Forse [questo] (http://stackoverflow.com/q/691743/1285418) può essere d'aiuto. –

+1

@YoryeNathan: se l'output standard non va a una console, non verrà emesso alcun segnale acustico. –

risposta

2

Non credo che ci sia un modo per suonare brani con "beep" in Java. Dovrai utilizzare le API javax.sound.* che penso ... a meno che tu non riesca a trovare una libreria di terze parti che semplifica le cose per te.

Se si vuole percorrere questo percorso, allora this page potrebbe darvi qualche idea.

+1

Sebbene l'OP lo abbia accettato come corretto, non è corretto; vedere la voce successiva per la risposta corretta. –

+0

@RobCranfill - Non puoi suonare ** un brano ** con '" \ 007 "' ... se questo è quello che stai insinuando. In caso contrario, spiegare come "la voce successiva" risponde alla domanda. –

+0

Mi scuso umilmente per il mio commento. * Il mio * commento è sbagliato, mi mancava l'intero punto di questa domanda, per suonare "melodie". Colpa mia. –

39

È possibile utilizzare questo:

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

EDIT

Se si sta tentando di riprodurre qualsiasi cosa di durata e con differenti suoni si dovrebbe davvero esaminare la libreria Java MIDI. Il segnale acustico predefinito non sarà in grado di soddisfare le tue esigenze poiché non puoi modificare la durata del segnale acustico.

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

+6

Peccato che non funzioni su Linux con Gnome in esecuzione ... –

+0

@AndrewLandsverk Sì, la roba del toolkit è davvero complicata su diverse piattaforme –

+2

@AndrewLandsverk FYI a partire da gnome 15.10 e Java 7 funziona tutto bene! –

0

È possibile ottenere il riferimento della classe Toolkit here, in cui è definito il metodo beep().

7

basta stampare:

System.out.println("\007") 

lavora almeno su MacOS.

+0

Non funziona qui (Win7). –

+2

Non funziona anche qui (Ubuntu 13.04) – math

+2

@ devoured-elysium, funziona su W7 se eseguito con java.exe. Se eseguito con javaw.exe o eclipse (ad esempio nessuna console reale), non viene emesso alcun segnale acustico. – RealHowTo

0
//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(); 
    } 
} 
+1

Andrew, già spiegato (27 maggio 12), QUESTO non funzionerà sotto Linux con Gnome e l'ho testato di nuovo. – math

+1

È un duplicato completo di [una risposta precedente] (http://stackoverflow.com/questions/10771441/java-equivalent-of-c-sharp-system-beep/10771452#10771452) –

+0

non funziona in Windows . –

3

Ho hackerato insieme una funzione che funziona per me. Usa un sacco di cose da javax.sound.sampled. L'ho adattato per funzionare con il formato audio il mio sistema fornisce automaticamente una nuova clip da AudioSystem.getClip(). Ci sono probabilmente tutti i modi in cui potrebbe essere reso più robusto e più efficiente.

/** 
* 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); 
    } 
} 

EDIT: A quanto pare qualcuno è migliorato il mio codice. Non ho ancora provato, ma dargli un andare: https://gist.github.com/jbzdak/61398b8ad795d22724dd

+0

Con questo, ho potuto generare suoni con Ubuntu 12.04. Grazie! – Joanis

+0

@Erhannis: ho leggermente migliorato questo snippet e ora suona più chiaro sul mio sistema --- feek libero di incorporarlo nella risposta: https://gist.github.com/jbzdak/61398b8ad795d22724dd –

+0

Impossibile accedere a Type da dichiarata una variabile. Invece basta chiamarla con il nome della classe perché è statica. Cambia la linea event.Type.START a LineEvent.Type.START – ShihabSoft

2

Un'altra soluzione, Windows dipendente è quello di utilizzare JNA e chiamare direttamente di Windows Beep function, disponibile in Kernel32. Sfortunatamente Kernel32 in JNA non fornisce questo metodo in 4.2.1, ma puoi facilmente estenderlo.

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

Per utilizzarlo:

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

Se si utilizza Maven è necessario aggiungere le seguenti dipendenze:

<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> 
+0

Problemi con questa soluzione: 1) Funzionerà solo su Windows. L'OP non afferma che una soluzione solo per Windows è accettabile. 2) Sei dipendente da un'API interna che potrebbe cambiare o essere chiusa in una versione futura di Java. 3) È improbabile che funzioni se la JVM è in modalità sandbox. (Sto solo dicendo). –