带有 .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 位。
我试图在我的 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 位。