как я могу дождаться завершения воспроизведения звукового клипа java? - PullRequest
7 голосов
/ 17 февраля 2009

Я использую следующий код для воспроизведения звукового файла с использованием API Java-звука.

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

Вызов метода для метода Clip.start () немедленно возвращается, и система воспроизводит звуковой файл в фоновом потоке. Я хочу, чтобы мой метод приостановился до завершения воспроизведения.

Есть ли хороший способ сделать это?

РЕДАКТИРОВАТЬ: Для всех, кто интересуется моим окончательным решением, основываясь на ответе Ури, я использовал следующий код:

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

Ответы [ 5 ]

5 голосов
/ 25 июня 2013

Вы можете просто поставить этот код вместо:

предположим, что ваш клип1 воспроизводится, и вы хотите, чтобы клип2 воспроизводился сразу после этого, вы можете:

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

и чтобы это работало без задержки основной задачи (я говорю это потому, что цикл while заставляет работу ждать завершения clip1, независимо от того, какая следующая работа ...) вы можете создать новый поток в укажите, где вы хотите, чтобы это произошло, и просто поместите код в метод run () ... УДАЧИ!

4 голосов
/ 17 февраля 2009

Аудиоклип является типом или строкой и поэтому поддерживает прослушиватели линии.

Если вы используете addLineListener, вы должны получать события, когда воспроизведение начинается и останавливается; если вы не в цикле, вы должны остановиться после окончания клипа. Однако, как и в случае любых других событий, перед фактическим окончанием воспроизведения и остановкой может возникнуть задержка.

Заставить метод ждать немного сложнее. Вы можете либо заняться этим (не очень хорошая идея), либо использовать другие механизмы синхронизации. Я думаю, что есть шаблон (не уверен в этом) для ожидания длинной операции, чтобы вызвать событие завершения, но это общий вопрос, который вы, возможно, захотите опубликовать отдельно в SO.

3 голосов
/ 13 октября 2017

Я предпочитаю этот способ в 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();
0 голосов
/ 11 июля 2017

Я использовал ожидание / уведомление, чтобы реализовать это. Просто для справки.

        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();
0 голосов
/ 06 октября 2016

Начиная с JDK8, слушатель Clip в некотором роде глючит (то есть может случиться так, что он запускает Type.STOP дважды для одного воспроизведения звука (.start()).

Поэтому я бы использовал что-то вроде:

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.

Кроме того, вы можете взглянуть на новый класс AudioClip , который предоставляет JFX8 (имеет несколько изящных методов для работы)

...