sonidos sonido reproducir como audioclip archivos archivo agregar abrir java javasound

como - ¿Cómo puedo esperar a que un clip de sonido java termine de reproducirse?



reproducir sonido jframe (5)

Un clip de sonido es un tipo o línea y, por lo tanto, es compatible con oyentes de línea.

Si usas addLineListener, deberías obtener eventos cuando comience y se detenga la reproducción; si no estás en un bucle, deberías detenerte cuando termine el clip. Sin embargo, como ocurre con cualquier evento, puede haber un retraso antes del final real de la reproducción y la detención.

Hacer que el método espere es un poco más complicado. Puede estar ocupado, esperar (no es una buena idea) o usar otros mecanismos de sincronización. Creo que hay un patrón (no estoy seguro al respecto) para esperar en una operación larga para lanzar un evento de finalización, pero esa es una pregunta general que quizás desee publicar por separado en SO.

Estoy usando el siguiente código para reproducir un archivo de sonido usando la API de sonido java.

Clip clip = AudioSystem.getClip(); AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream); clip.open(inputStream); clip.start();

La llamada de método al método Clip.start () regresa inmediatamente, y el sistema reproduce el archivo de sonido en una cadena de fondo. Quiero que mi método se detenga hasta que se complete la reproducción.

¿Hay alguna buena manera de hacerlo?

EDITAR: Para todos los interesados ​​en mi solución final, basada en la respuesta de Uri, utilicé el siguiente código:

private final BlockingQueue<URL> queue = new ArrayBlockingQueue<URL>(1); public void playSoundStream(InputStream stream) { Clip clip = AudioSystem.getClip(); AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream); clip.open(inputStream); clip.start(); LineListener listener = new LineListener() { public void update(LineEvent event) { if (event.getType() != Type.STOP) { return; } try { queue.take(); } catch (InterruptedException e) { //ignore this } } }; clip.addLineListener(listener ); }


puedes poner este código en su lugar:

supongamos que su clip1 se está reproduciendo y desea que se reproduzca un clip2 inmediatamente después de eso, puede:

clip1.start(); while(clip1.getMicrosecondLength() != clip1.getMicrosecondPosition()) { } clip2.loop(some int here);

y, para hacer que esto funcione sin retrasar su tarea principal (lo digo porque el bucle while hace que el trabajo espere a que el clip1 termine, sin importar cuál sea el próximo trabajo ...) puede crear un nuevo hilo en el punto donde quiero que suceda, y simplemente pongo el código en su método run () ... ¡BUENA SUERTE!


A partir de JDK8, el oyente de Clip algún tipo de error (es decir, puede ocurrir que dispare el Type.STOP dos veces para una sola reproducción del audio ( .start() ).

Por lo tanto, usaría algo como:

Clip[] myBunchOfClipsToPlaySequentially=new Clip[A_BUNCH]; // // [load actual clips...] // [...] // for(Clip c: myBunchOfClipsToPlaySequentially) while(c.getFramePosition()<c.getFrameLength()) Thread.yield(); // Note that if we simply put a NO-OP instead (like a // semicolon or a {}), we make our CPU // cry). Thread.yield() allows for almost 0% CPU consumption.

Además, puede echar un vistazo a la nueva clase AudioClip que ofrece JFX8 (tiene algunos métodos ingeniosos para jugar)


He usado un wait / notify para implementar esto. Solo por tu referencia.

final Clip clip = AudioSystem.getClip(mixerInfo); clip.addLineListener(new LineListener(){ @Override public void update(LineEvent e) { if (e.getType()==LineEvent.Type.STOP){ synchronized(clip){ clip.notifyAll(); } System.err.println("STOP!"); } } }); clip.open(as); clip.start(); while (true){ synchronized(clip){ clip.wait(); } if (!clip.isRunning()){ break; } } clip.drain(); clip.stop(); clip.close();


Prefiero esto en Java 8:

CountDownLatch syncLatch = new CountDownLatch(1); try (AudioInputStream stream = AudioSystem.getAudioInputStream(inStream)) { Clip clip = AudioSystem.getClip(); // Listener which allow method return once sound is completed clip.addLineListener(e -> { if (e.getType() == LineEvent.Type.STOP) { syncLatch.countDown(); } }); clip.open(stream); clip.start(); } syncLatch.await();