Проблемы с воспроизведением всего аудио клипа - PullRequest
0 голосов
/ 11 июня 2018

Я играю звуковые эффекты (файлы WAV) в игре с javax.sound.sampled.Clip.Тем не менее, эффект, который имеет 2 секунды, не воспроизводится полностью, только его часть.Если я добавлю clip.loop(2), то звук будет воспроизводиться правильно несколько раз, то есть целых 2 секунды.Что не так и как это исправить?

package com.zetcode;

import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JOptionPane;

public enum SoundEffect {

    EXPLODE("resources/explosion.wav"),
    HITGROUND("resources/impact.wav"),
    CANNON("resources/cannon.wav");

    private Clip clip;

    SoundEffect(String soundFileName) {
        try {
            URL url = this.getClass().getClassLoader().getResource(soundFileName);

            try (AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url)) {
                clip = AudioSystem.getClip();
                clip.open(audioInputStream);
            }
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
            JOptionPane.showMessageDialog(null, "Cannot play sound", "Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    public void play() {

        if (clip.isRunning()) {
            clip.stop();
        }
        clip.setFramePosition(0);
        clip.start();
    }

    static void init() {
        values();
    }    
}

1 Ответ

0 голосов
/ 12 июня 2018

Знаете ли вы и учитываете ли вы тот факт, что при воспроизведении клипа (с помощью метода start ()) поток, воспроизводящий код, является демоном?В отличие от обычных потоков, поток демона не будет препятствовать закрытию Java-программы.Если ваша программа заканчивается до того, как завершится выполнение звука, поток состояния демона также завершается, даже если он не завершен.

Вы пытаетесь запустить пример кода SoundClipTest или SoundEffectDemo?Мне кажется, что SoundClipTest выйдет, как только программа выполнит метод start (), тогда как SoundEffectDemo сохранится и позволит завершить воспроизведение звука.


** Edit 1 **


Я только сейчас замечаю, что вы сделали SoundEffect перечислением.Я никогда не видел, чтобы этот подход использовался ранее.

Один из подходов, который я использовал, - это создание класса с именем GameSound, и его конструктор предварительно загружает каждый клип по отдельности и сохраняет их в памяти, готовые для воспроизведения.Затем я создаю метод или методы для их воспроизведения.

gameSound.playExplosion();

Класс GameSound будет иметь переменные экземпляра для каждого звукового эффекта.

private Clip explosion;
private Clip cannon;

И конструктор GameSound будет иметь:

URL url = this.getClass().getResource("resources/explosion.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url); 
explosion = AudioSystem.getClip();
explosion.open(ais);

, а GameSound будет иметь метод:

public void playExplosion()
{
    if (explosion.isRunning()) {
        explosion.stop();
    }
    explosion.setFramePosition(0);
    explosion.start();
}

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

Этот подход может работать лучше (его легко добавить в GameSound, так как код становится более сложным), и он не должен быть слишком сложным для кодирования.Мне было бы любопытно узнать, решает ли проблема этот план или нет.


** Edit 2 **


Извините за ошибки вприведенный выше код.Я исправил их, когда сделал следующий пример.Одна мысль, однако, когда я пошел слушать звуковые эффекты, которые вы связали, несколько взрывов были с самого начала усечены.Проигрывали ли вы звуки в другом приложении (например, в Windows Groove Music или с веб-сайта, на котором вы их получили) и проверяли, отличаются ли они, когда вы воспроизводите их в своем коде?

Вот краткая справка "GameSound",Я скачал файл Explosion + 2.wav из вашей справки, так как он был длиннее других и имеет четкое окончание, и я ссылаюсь на это.

package stackoverflow.janbodnar;

import java.io.IOException;
import java.net.URL;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class GameSound {

    private final Clip explosion;

    public GameSound() throws LineUnavailableException, 
    IOException, UnsupportedAudioFileException
    {
        URL url = this.getClass().getResource(
                "resources/Explosion+2.wav");
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        explosion = AudioSystem.getClip();
        explosion.open(ais);
    }

    public void playExplosion()
    {
        if (explosion.isRunning()) {
            explosion.stop();
        }
        explosion.setFramePosition(0);
        explosion.start();
    }
}

А вот простая кнопка Swing, которая вызывает GameSound.

package stackoverflow.janbodnar;

import java.io.IOException;

import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class GameSoundTest extends JFrame
{
    private static final long serialVersionUID = 1L;

    private final GameSound gameSound;

    public GameSoundTest() throws LineUnavailableException,
    IOException, UnsupportedAudioFileException
    {
        gameSound = new GameSound();

        JButton button = new JButton("Play Explosion");
        button.addActionListener(e -> gameSound.playExplosion());
        getContentPane().add(button);
    }

    private static void createAndShowGUI()
    {
        JFrame frame;
        try 
        {
            frame = new GameSoundTest();
            frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            frame.setBounds(0, 0, 200, 200);
            frame.setVisible(true);
        } 
        catch (LineUnavailableException | IOException 
                | UnsupportedAudioFileException e) 
        {
            e.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGUI());
    }
}

Все это предполагает, конечно, что есть подпапка под названием "ресурсы" с взрывающимся SFX в ней.

...