Valentino Ru
Valentino Ru

Reputation: 5052

How to cast from InputStream to AudioInputStream

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

Answers (3)

Andrew Thompson
Andrew Thompson

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

Stephen C
Stephen C

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

Jeffrey
Jeffrey

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

Related Questions