带有 .wav 文件的 UnsupportedAudioFileException

UnsupportedAudioFileException with a .wav file

我试图在我的 EnviromentAudio 对象中加载一个 .wav 文件,但我只收到一个 UnsupportedAudioFileException,我不知道为什么。因为该文件是一个 wav,我尝试将其编码为无符号 8 位、带符号的 16 位、44100 比特率、GSM、A-law...长话短说我已经正如许多人所建议的那样,尝试了很多编码,但没有人奏效。可能我没有得到什么,所以,我想问一下我做错了什么。

编辑:
正如所指出的,我应该指定一些事情:首先,为了设置一些上下文,我正在使用 Java 8 为项目创建一个小 PC 游戏,它必须使用 java 的基本组件.话虽如此,我正在使用 ClassLoader ,因为我的项目文件夹里乱七八糟。它不符合惯例,我必须保持这样。它的结构如下:

-src  
    -app
        -audio
            EnviromentAudio.java // Class that need to load soundtrack.wav
-res  
    -audio
        Soundtrack.wav // Audio to be loaded

而且我知道 getResource.. 应该始终以 / 开头,但如果我添加该斜线,那么每次尝试获取资源都会导致 NPE。可能这是由文件夹配置引起的,顺便说一下,资源文件夹被设置为源文件夹,所以我什至不太确定,因为我已经使用 getResource 来获取其他文件没有问题。

在这种情况下 getResource 工作正常,即它检索文件,但 AudioSystem 生成错误。我试图隔离相关各方,但唯一的问题似乎就在这里。我添加了AudioManagerclass,EnviromentAudio继承的Audioclass,以及整个EnviromentAudio,希望对大家的理解有所帮助。我还在 AudioManager class 中提供了一个 main,这应该足以复制错误。

音频class:


package application.core.audio;

import java.util.ArrayList;

import javax.sound.sampled.Clip;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.swing.JOptionPane;

public abstract class Audio
{
    protected static final String AUDIOERROR="Error in loading audio. "
            + "Execution Failed, please, restart the game. "
    protected static final String AUDIOERRORTITLE="Audio loading error";

    protected ArrayList<Clip> multimedia;
    protected Clip currentAudio;

    protected FloatControl gainControl;

    public Audio()  {
        multimedia=new ArrayList<Clip>();
        currentAudio=null;
    }

    protected abstract void getResources();

    public void playAudio(int index)    {
        try
        {
            currentAudio=multimedia.get(index);
            gainControl=(FloatControl) currentAudio.getControl(
                    FloatControl.Type.MASTER_GAIN);
            currentAudio.open();
        } catch (LineUnavailableException e)
        {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, AUDIOERROR,
                    AUDIOERRORTITLE, JOptionPane.ERROR_MESSAGE);
        }
        currentAudio.start();
    }
    public void loopAudio(int index)    {
        currentAudio=multimedia.get(index);
//          gainControl=(FloatControl) currentAudio.getControl(
//                  FloatControl.Type.MASTER_GAIN);
//          currentAudio.open();
//      currentAudio.start();
        currentAudio.loop(Clip.LOOP_CONTINUOUSLY);
    }
    public void repeatAudio(int index, int times)   {
        try
        {
            currentAudio=multimedia.get(index);
            gainControl=(FloatControl) currentAudio.getControl(
                    FloatControl.Type.MASTER_GAIN);
            currentAudio.open();
        } catch (LineUnavailableException e)
        {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, AUDIOERROR,
                    AUDIOERRORTITLE, JOptionPane.ERROR_MESSAGE);
        }
        currentAudio.loop(times);
    }
    public void stopAudio(int index)    {
        multimedia.get(index).stop();
        multimedia.get(index).close();
    }

    public void setVolume(float volume) {
        float range=gainControl.getMaximum()-gainControl.getMinimum();
        float gain=(range-volume)+gainControl.getMinimum();
        gainControl.setValue(gain);
    }

    public boolean currentAudioIsOpen() {return currentAudio.isOpen();}
    public void openCurrentAudio()  {
        if (!currentAudio.isOpen())
            try
            {
                currentAudio.open();
            } catch (LineUnavailableException e)
            {
                e.printStackTrace();
                JOptionPane.showMessageDialog(null, AUDIOERROR,
                        AUDIOERRORTITLE, JOptionPane.ERROR_MESSAGE);
            }
    }
    public void openAndPlayCurrentAudio()   {
        if (!currentAudio.isOpen())
            openCurrentAudio();
        currentAudio.start();
    }

    public void playCurrentAudio()  {currentAudio.start();}
    public void loopCurrentAudio()  {currentAudio.loop(Clip.LOOP_CONTINUOUSLY);}
    public void repeatCurrentAudio(int times)   {currentAudio.loop(times);}
    public void stopCurrentAudio()  {currentAudio.stop();}
    public void stopAndCloseCurrentAudio()  {
        currentAudio.stop();
        currentAudio.close();
    }
}

这是我的 EnviromentAudio class 产生的异常:


package application.core.audio;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class EnviromentAudio extends Audio
{
    public static final int SOUNDTRACK=0;

    public EnviromentAudio()
    {
        super();
        getResources();
        this.gainControl=(FloatControl) currentAudio.getControl(FloatControl.Type.MASTER_GAIN);
        }

    @Override
    protected void getResources()
    {
        try
        {
        ClassLoader loader=EnviromentAudio.class.getClassLoader();
            multimedia.add(AudioSystem.getClip());
            multimedia.get(SOUNDTRACK).open(AudioSystem.getAudioInputStream( // here the exception is thrown (on getAudioInputStream)
                    loader.getResourceAsStream("resources"+File.separator+"audio"+File.separator+
                    "soundtrack"+File.separator+"igpeSoundtrack.wav")));
            currentAudio=multimedia.get(SOUNDTRACK);
        } catch (LineUnavailableException e)
        {
            e.printStackTrace();
        } catch (IOException | UnsupportedAudioFileException e1)
        {
            e1.printStackTrace();
        }
    }

}

音频管理器class:


    package application.core.audio;
    
    public class AudioManager
    {
        private static AudioManager instance=null;
    
        private EnviromentAudio soundtrack;
        private PlayerAudio playerAudio;
    
        private AudioManager()  {
            soundtrack=new EnviromentAudio();
    //      playerAudio=new PlayerAudio();
    
            soundtrack.loopAudio(EnviromentAudio.SOUNDTRACK);
        }
    
        public static AudioManager getInstance()    {
            if (instance==null)
                instance=new AudioManager();
            return instance;
        }
    
        public Audio getSoundtrack()    {return soundtrack;}
        public Audio getPlayerSounds()  {return playerAudio;}
    
        public void setVolume(float volume) {
            soundtrack.setVolume(volume);
            playerAudio.setVolume(volume);
        }
        public float getVolume()    {return soundtrack.gainControl.getValue();}
    
        public static void main(String[] args)
        {
            AudioManager a=AudioManager.getInstance();
        }
    
    }

这里是错误:

javax.sound.sampled.UnsupportedAudioFileException: Stream of unsupported format
    at java.desktop/javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1020)
    at application.core.audio.EnviromentAudio.getResources(EnviromentAudio.java:29)
    at application.core.audio.EnviromentAudio.<init>(EnviromentAudio.java:18)
    at application.core.audio.AudioManager.<init>(AudioManager.java:11)
    at application.core.audio.AudioManager.getInstance(AudioManager.java:19)
    at application.MainApplication.audioInitialize(MainApplication.java:44)
    at application.MainApplication.main(MainApplication.java:25)

这更多的是帮助解决问题而不是解决方案(扩展了安德鲁汤普森关于制作 MRE 的建议。您使用的是特定框架吗?还是您自己制作的东西?有那么一秒钟我认为它可能是Android(由于存在 AudioManager)。

以下是播放测试 .wav 文件的更简单示例。将 wav 文件放在与此 class 相同的文件夹中。使用此功能时您的 .wav 文件可以播放吗?

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.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class BasicClipExample {

    public static void main(String[] args) {
        try {
            BasicClipExample.run();
        } catch (UnsupportedAudioFileException | IOException 
                | LineUnavailableException | InterruptedException e) {
             e.printStackTrace();
        }
    }

    private static void run() throws UnsupportedAudioFileException, 
            IOException, LineUnavailableException, InterruptedException
    {
        String filename = "yourSound.wav";
        URL url = BasicClipExample.class.getResource(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(6000); // plays up to 6 seconds of sound before exiting
        clip.close();
    }
}

如果有效,则说明您的框架代码有些奇怪。从这里您可以逐步检查文件分隔符逻辑之类的东西是否正常工作。如果文件加载,您还可以添加一些行以打印出 AudioFormat

我有时检查文件的另一种方法是将它们加载到 Audacity,这是免费的。使用该工具很容易检查有关文件格式的信息。如果我不得不打赌,问题出在 .wav 格式上,我猜该文件是以比 Java 更高的质量级别录制的,例如 48000(也许 Java 支持?)或 96000 fps 或 24 或 32 位编码而不是 16 位。