How to cast from InputStream to AudioInputStream

11,174

Solution 1

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.

Solution 2

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.

Share:
11,174
Valentino Ru
Author by

Valentino Ru

Updated on June 04, 2022

Comments

  • Valentino Ru
    Valentino Ru about 2 years

    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?