不支持的音频文件异常,使用 .wav 文件。

huangapple go评论109阅读模式
英文:

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 // 需要加载soundtrack.wav的类
-res  
    -audio
        Soundtrack.wav // 需要加载的音频

我知道getResource..应该始终以斜杠/开头,但是如果我添加了那个斜杠,那么每次尝试获取资源都会导致NPE(空指针异常)。可能这是由于文件夹的布置导致的,另外,资源文件夹被设置为源文件夹,所以我甚至对此不是很确定,因为我以前已经使用getResource获取其他文件而没有问题。

在这种情况下,getResource可以正常工作,也就是说它能够获取到文件,但是AudioSystem会生成一个错误。我试图隔离所涉及的部分,但是唯一的问题似乎就在这里。我将提供AudioManager类、EnviromentAudio继承的Audio类以及整个EnviromentAudio代码,希望这些对于更好理解问题有所帮助。我还在AudioManager类中提供了一个main方法,足以复现这个错误。

Audio类:

// 代码部分

这是我的EnviromentAudio类,它产生异常:

// 代码部分

AudioManager类:

// 代码部分

以下是错误信息:

// 错误信息部分
英文:

I'm trying to load a .wav file in my EnviromentAudio object, but I received only an UnsupportedAudioFileException and I don't know why. Because the file is a wav and I've tried to encode it as an unsigned 8 bit, as a signed 16 bit, with a 44100 bit rate, as a GSM, as a A-law... long story short I've tried a lot of encoding, as many people suggested, but no one worked. Probably I'm not getting something, so, I want to ask what I'm doing wrong.

EDIT:
As pointed out I should have specified some things: first of all, to set some context, I am using Java 8 to create a little pc game for a project, which must uses the basics components of java. Said that, I'm using the
ClassLoader

, because I have a mess in the project folder. It does not follow the convention and I have to keep like that. It's structured like this:

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

And I know that a getResource.. should start always with a /, but if I add that slash, then every attempt to get a resource results in a NPE. Probably that's caused by the folders disposition and, by the way, the resources folder is set as source folder, so I'm not even quite sure about that, cause, also, I've already used the getResource to get other files without problems.

In this case The getResource works fine, that is it retrieves the file, but the AudioSystem generates an error. I've tried to isolate the parties involved, but the only problem seems to be here. I'm adding the AudioManager class, the Audio class inherited by EnviromentAudio, and the whole EnviromentAudio, with the hope that it will be of help for a better understanding. I also provided a main in the AudioManager class, which should be enough to replicate the error.

Audio 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();
	}
}

This is my EnviromentAudio class that produce the exception:


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();
		}
	}

}

AudioManager 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();
    	}
    
    }

And here is the error:

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)

答案1

得分: 1

这更多是为了帮助故障排除而不是解决方案(对于扩展 Andrew Thompson 建议的制作 MRE 进行了扩展)。您是否使用特定的框架?还是您自己制作的?起初我以为可能是 Android(因为存在 AudioManager)。

以下是一个更简化的示例,用于测试播放您的 .wav 文件。将 wav 文件放在与此类相同的文件夹中。在使用此代码时,您的 .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); // 在退出之前播放最多 6 秒的声音
        clip.close();
    }
}

如果可以工作,那么您的框架代码可能有些奇怪。从这里开始,您可以逐步检查诸如文件分隔符逻辑是否正常工作的事情。您还可以添加一些代码来打印出文件加载时的 AudioFormat

我有时候检查文件的另一种方法是将它们加载到免费的 Audacity 软件中。使用该工具很容易检查文件格式的信息。如果我必须打赌,假设问题是 .wav 格式,我猜测该文件的录制质量可能高于 Java 的设置,例如,48000(也许 Java 支持?)或 96000 fps,或者是 24 位或 32 位编码,而不是 16 位。

英文:

This is more to help with troubleshooting than a solution (expanding on Andrew Thompson's suggestion of making an MRE. Are you using a particular framework? Or is it something of your own making? For a second I though it might be Android (due to presence of AudioManager).

Following is a more minimal example for play testing your .wav file. Put the wav file in the same folder as this class. Does your .wav file play when using this?

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();
    }
}

If it works, then something is odd about your framing code. From here you can progressively check if things like the file separator logic are working. You can also add some lines to print out the AudioFormat if the file loads.

Another way I sometimes inspect files is to load them into Audacity, which is free. Info about the file format is pretty easy to inspect with that tool. If I had to wager, and the issue IS the .wav format, I'm guessing that the file is recorded at a higher quality level than Java is set to work with, e.g., 48000 (maybe Java supports?) or 96000 fps or 24- or 32-bit encoding rather than 16-bit.

huangapple
  • 本文由 发表于 2020年7月24日 03:10:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63061511.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定