3

是否可以从 InputStream 转换为 AudioInputStream?

我想在某些事件中播放小声音文件,所以我按照 SoundThread

import java.io.*;
import javax.sound.sampled.*;

public class SoundThread implements Runnable{

    private String filename;

    SoundThread(String filename) {
        this.filename = filename;
    }

    public void run() {
        try {
            InputStream in = ClassLoader.getSystemResourceAsStream("sounds/"+filename+".wav");
            Clip clip = AudioSystem.getClip();
            clip.open((AudioInputStream)in);
            clip.start();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (LineUnavailableException e){
            e.printStackTrace();
        } 
    }
}

我运行它

new Thread(new SoundThread("nameOfTheSoundFile")).start();

一开始我用 sun.audio.AudioPlayer 和 sun.audio.AudioStream 处理它,但是当我将该代码放入 eclipse 中时,它向我显示了错误。所以我尝试了

AudioInputStream in = (AudioInputStream)ClassLoader.getSystemResourceAsStream("sounds/"+filename+".wav");

将 InputStream 转换为 AudioInputStream(eclipse 没有显示任何错误),但运行它会引发 ClassCastException。这个问题有什么解决办法吗?

4

3 回答 3

7

使用直接从资源 AudioSystem中获取。AudioInputStreamURL

URL url = ClassLoader.getResource("/sounds/"+filename+".wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(ais);

另见AudioSystem.getAudioInputStream(InputStream),但这“更危险”。Java Sound 通常需要一个可重新定位的输入流。出于某种我不太清楚的原因,Class.getResourceAsStream()变体有时会返回不可重新定位的流。

于 2012-05-14T22:34:09.963 回答
1

你不能投。在 Java 中,仅当您要转换的真实对象已经是目标类型的实例时,才能对引用类型进行类型转换。例如:

    String myString = new String("42");
    Object obj = (Object) myString;  // OK
    String mystery = (String) obj;   // OK
    String mystery2 = (Integer) obj; // FAIL

前两个成功是因为我们在第一行创建的字符串对象是 的实例Object(因为String是 的子类型Object)和 的实例String。第三个失败,因为 aString不是Integer


在您的示例中,您从中获取的对象getSystemResourceAsStream是包含(可能)音频数据的原始流。它不是音频流;即不是AudioInputStream.

您必须包装原始输入流,如下所示:

    InputStream in = ClassLoader.getSystemResourceAsStream(
        "sounds/"+filename+".wav");
    AudioFormat format = ...
    int length = ...
    AudioInputStream audio = new AudioInputStream(in, format, length);

或使用一种AudioSystem.getAudioInputStream(...)工厂方法,它在引擎盖下进行包装。

有关执行此操作的正确方法的详细信息,请参阅 Andrew Thomson 的回答。

于 2012-05-14T22:35:01.980 回答
0

InputStream返回的不是getSystemResourceAsStream一个AudioInputStream,所以强制转换它永远不会起作用。只需创建一个新的AudioInputStream

于 2012-05-14T22:33:32.497 回答