Reputation: 5052
Is it possible to cast from an InputStream to an AudioInputStream?
I want to play little sound files at certain events, so I made following 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();
}
}
}
I run it with
new Thread(new SoundThread("nameOfTheSoundFile")).start();
At the beginning I handled it with the sun.audio.AudioPlayer and sun.audio.AudioStream, but as soon I put that code in eclipse, it showed me errors. So I tried
AudioInputStream in = (AudioInputStream)ClassLoader.getSystemResourceAsStream("sounds/"+filename+".wav");
to cast the InputStream to AudioInputStream (eclipse didn't show any errors), but running it it throws an ClassCastException. Is there any solution for this problem?
Upvotes: 3
Views: 12239
Reputation: 168835
Use the AudioSystem
to get an AudioInputStream
directly from the URL
to the resource.
URL url = ClassLoader.getResource("/sounds/"+filename+".wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
Clip clip = AudioSystem.getClip();
clip.open(ais);
See also AudioSystem.getAudioInputStream(InputStream)
but this is 'more dangerous'. Java Sound will typically require a repositionable input stream. For some reason that I am not quite clear on, the Class.getResourceAsStream()
variants sometimes return a non-repositionable stream.
Upvotes: 7
Reputation: 719239
You can't cast it. In Java, a type cast on a reference type only works if the real object you are casting is already an instance of the target type. For example:
String myString = new String("42");
Object obj = (Object) myString; // OK
String mystery = (String) obj; // OK
String mystery2 = (Integer) obj; // FAIL
The first two succeed because the string object that we created in the first line is an instance of Object
(because String
is a subtype of Object
), and an instance of String
. The third one fails because a String
is NOT an Integer
.
In your example, the object that you get from getSystemResourceAsStream
is a raw stream containing (presumably) audio data. It is not an audio stream; i.e. not an instance of AudioInputStream
.
You have to wrap the raw input stream, something like this:
InputStream in = ClassLoader.getSystemResourceAsStream(
"sounds/"+filename+".wav");
AudioFormat format = ...
int length = ...
AudioInputStream audio = new AudioInputStream(in, format, length);
or use one of AudioSystem.getAudioInputStream(...)
factory methods, which does the wrapping under the hood.
See Andrew Thomson's answer for details of the RIGHT way to do this.
Upvotes: 1
Reputation: 44808
The InputStream
returned by getSystemResourceAsStream
is not an AudioInputStream
, so casting it will never work. Just create a new AudioInputStream
instead.
Upvotes: 0