Как правильно воспроизвести звуковой файл, используя java .sound.sampled.Clip - PullRequest
0 голосов
/ 28 апреля 2020

Я прочитал много тем SoF и других сайтов по этой теме c, но ни один из них не работает для меня, поэтому я спрашиваю еще раз, надеясь получить индивидуальный ответ.

У меня есть .WAV файл внутри моей банки, который я хочу воспроизвести, но я получаю NullPointerException. Я пробовал много способов, даже воспроизводил файл вне банки по абсолютному пути, но я получил тот же результат. Это функция для воспроизведения звука

public void gimli(){
        try {
            Clip clip;
             AudioInputStream  stream = AudioSystem.getAudioInputStream(this.getClass().getResource(Utils.class.getResourceAsStream("gimlilaught.wav").toString()));
   AudioFormat format = stream.getFormat();
    DataLine.Info info = new DataLine.Info(Clip.class, format);
  clip = (Clip)AudioSystem.getLine(info);
    clip.open(stream);
    clip.start();
}catch(Exception ex){
ex.printStackTrace(System.out);
}

Спасибо за вашу попытку.

Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

AudioInputStream необходим в качестве аргумента для открытия Clip. Посмотрев на API, вы увидите, что AudioSystem.getAudioInputStream (InputStream) или AudioSystem.getAudioInputStream (URL) можно использовать для получения AudioInputStream .

Существует два метода Class, которые служат: getResource(String) или getResourceAsStream(String). Метод getResource вернет URL. Метод getResourceAsStream вернет InputStream.

Я предпочитаю использовать форму URL, так как она более щадящая. При использовании AudioSystem.getAudioInputStream (InputStream) , IOException будет возвращено, если файл не поддерживает маркировку и сброс . Метод AudioSystem.getAudioInputStream (URL) обходит это требование.

Кроме того, вы должны знать, что URL, в отличие от File, может использоваться для идентификации файла, который находится в банке.

Вы также должны быть осторожны при установке относительного адреса. Я обычно хотел бы иметь файл / res или / audio , содержащий файл .wav для загрузки. Например, вы можете использовать « .. / res / myAudio.wav », если / res - параллельная папка, или « res / myAudio.wav », если / res - это подпапка относительно расположения класса, используемого в методе getResource .

Вот простой рабочий пример, где аудиофайл находится в вложенная папка, / res :

private static void loadAndPlayClip() throws UnsupportedAudioFileException, 
        IOException, LineUnavailableException, InterruptedException
{
    String filename = "a3.wav";
    URL url = BasicClipExample.class.getResource("res/" + filename);
    AudioInputStream ais = AudioSystem.getAudioInputStream(url);
    DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
    Clip clip = (Clip) AudioSystem.getLine(info);
    clip.open(ais);

    clip.start();
    Thread.sleep(7000); // Duration should match length of audio file.
    clip.close();
}

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

  1. Команда Thread.sleep() останавливает основной поток, что обычно не желательно и не нужно. Поток, который система создает для воспроизведения Clip, является потоком daemon . Потоки Daemon не будут препятствовать завершению и завершению программы. В этом простом примере «запускай и забывай» основной поток выполняется быстро, поэтому программа будет немедленно закрыта, если мы не сохраним завершение с интервалом ожидания.

  2. Начальный загрузка Clip и игра Clip обычно выполняются двумя отдельными способами. A Clip был разработан для аудио, которое удобно хранить в памяти, что позволяет воспроизводить его без перезагрузки. Если вы перезагрузите Clip с каждой командой воспроизведения, вы будете одновременно выполнять ненужную работу и добавлять задержку, так как клип не начнет воспроизводиться, пока он не будет полностью загружен. Если аудиофайл неудобно хранить в памяти (например, большой файл из-за большой длительности), предпочтительным способом является его воспроизведение с SourceDataLine.

0 голосов
/ 28 апреля 2020

Я пробовал это прошлой ночью, и мне кажется, что это работает:

try {
            File filePath = new File(audioLocation);

            if (filePath.exists()) {
                AudioInputStream audioInput = AudioSystem.getAudioInputStream(filePath);
                Clip clip = AudioSystem.getClip();
                clip.open(audioInput);
                FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                gainControl.setValue(getVolume());
                clip.loop(Clip.LOOP_CONTINUOUSLY);
                clip.start();
            } else {
                System.out.println("Incorrect audio file path!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

Хотя я думаю, что у меня где-то должен быть clip.open (), и у меня были проблемы с остановкой и запуском звук из другого класса, он действительно воспроизводит звук.

...