无法播放整个音频片段

时间:2018-06-11 12:37:02

标签: java audio javasound game-development

我在path的游戏中播放声音效果(WAV文件)。但是,有2秒的效果并非完全播放,只是其中的一部分。如果我添加javax.sound.sampled.Clip,则声音会正确播放多次,即整整2秒。有什么问题以及如何解决?

clip.loop(2)

1 个答案:

答案 0 :(得分:1)

你是否意识到并且考虑到当播放剪辑时(通过start()方法),播放代码的线程是一个守护进程?与常规线程不同,守护程序线程不会阻止Java程序关闭。如果您的程序在声音执行完毕之前结束,守护程序状态线程也会结束,即使它没有完成。

您是否尝试运行示例代码SoundClipTest或SoundEffectDemo?在我看来,SoundClipTest将在程序执行start()方法后立即退出,而SoundEffectDemo将保持并允许声音完成播放。

**编辑1 **

我刚才注意到你已经将SoundEffect作为枚举。我以前从没见过这种方法。

我使用的一种方法是创建一个名为GameSound的类,让它的构造函数单独预加载每个Clip并将它们保存在内存中,准备播放。然后,我为他们的播放创建一个或多个方法。

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中),而且编码也不会太难。我很想知道改变这个计划是否会使问题消失。

**编辑2 **

对于上述代码中的错误,我们深表歉意。当我做出以下示例时,我修复了它们。但是,有人想到,当我去听你所连接的声音效果时,有几个爆炸开始被截断了。您是否在其他应用程序中播放了这些声音(如Windows Groove音乐,或者从您获得它们的网站),并在您的代码中播放它们时验证它们是不同的?

这是一个快速的游戏" 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());
    }
}

当然,这一切都假定有一个名为" resources"的子文件夹。随着爆炸SFX。