почему этот код не воспроизводит звуковой файл - PullRequest
3 голосов
/ 29 июля 2011

Код

import javax.sound.sampled.*;
import java.io.*;

public class Tester {
static Thread th;


public static void main(String[] args) {
    startNewThread();   
   while( th.isAlive() == true) {
       System.out.println("sound thread is working");
   }
}

public static void startNewThread() {
   Runnable r = new Runnable() {
       public void run() {
           startPlaying();
       }
   };
   th =new Thread(r);
   th.start();
} 
public static void startPlaying() {
   try {            
        AudioInputStream ais = AudioSystem.getAudioInputStream(new File("d:/UnderTest/wavtester.wav"));
        Clip clip = AudioSystem.getClip();
        clip.open(ais);
        clip.loop(-1); // keep playing the sound                  
   } catch(Exception exc) {
       System.out.println(exc);
     }       
 }
}

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

В чем причина (для завершения программы и отсутствия звука) ?

Ответы [ 3 ]

6 голосов
/ 29 июля 2011

Проблема в том, что Clip уже запускает фон демон нить для воспроизведения волнового файла.

Итак, поток выполнения вашего кода выглядит так:следует:

  • основной поток запускает вторичный (бесполезный) поток
  • дополнительный поток запускает поток демона (который будет воспроизводить звук)
  • в среднемвремя основной поток продолжает печатать что-то, пока вторичный поток активен
  • Когда вторичный поток завершает запуск потока воспроизведения, он заканчивается, поэтому вторичный поток не будет активнымсостояние больше
  • основной поток заметит, что вторичный поток не активен и будет также завершен
  • Поскольку поток воспроизведения является потоком демона , JVM завершит работу(потому что единственными оставшимися потоками являются потоки демонов)

Окончательный результат - именно то, что вы видите: некоторый текст печатается основным потоком во время запуска дополнительного потокаЕсли поток воспроизведения начнёт воспроизводиться, произойдет бум, JVM завершится.Иногда вы можете даже прослушать некоторые «щелчки» в наушниках (когда начинает воспроизводиться звук) до выхода из JVM.

Самое простое решение - сделать вторичный поток (т. Е. Не демоном)нить) спать во время воспроизведения звука.

...
  clip.open(ais);
  clip.loop(-1);
  Thread.sleep(amountToSleep);
...

Одна важная вещь, на которую следует обратить внимание : около года назад, когда я работал с этим Java-API, я заметил, что метод getMicrosecondLength() глючит.Я программировал как в Windows, так и в Linux, и на одной платформе я получил бы правильное значение, но на другой тот же самый метод вернул бы длину в миллисекундах!

Я обнаружил, что самый надежный способчтобы получить реальную длину звука, нужно использовать метод getFrameLength() и рассчитать длину по нему.

Я не смог найти код, который написал тогда в этой записной книжке.Позже я проверю другой компьютер и, если найду его, выложу полный пример (который надежно работает как на Windows с Sun JVM, так и на Linux с OpenJDK или Sun).

0 голосов
/ 30 сентября 2011
while(clip.isRunning()){} 

лучше

0 голосов
/ 29 июля 2011
import javax.sound.sampled.*;
import java.io.*;
import javax.swing.*;

public class Tester {
static Thread th;


public static void main(String[] args) throws Exception {
     Clip clip = AudioSystem.getClip();
     AudioInputStream ais = AudioSystem.getAudioInputStream(new File("d:/UnderTest/wavtester.wav"));
     clip.open(ais);
     clip.loop(0);
     // Calculate totalFrames
     long totalFrames = (long)(clip.getFrameLength() * clip.getFormat().getFrameRate());
     Thread.sleep( ( totalFrames* 1000 )); // pause the thread till the sound plays

     System.out.println(clip.getFrameLength());
     System.out.println(clip.getFormat().getFrameRate());           
 }
}
...