user1766089
user1766089

Reputation: 19

java.io.IOException: mark/reset not supported

I know this has been asked a ton of times but it's different in some scenarios so I can't figure it out. When I run my game in Eclipse, everything is going smoothly and the game runs perfectly but after I export it, it collapses. I can open the game and move around in the menu but no sounds are playing and after I hit play, the game just freezes and it gives me this error with cmd (I can paste any class necessary but hopefully just the Audio class is necessary):

java.io.IOException: mark/reset not supported
    at java.util.zip.InflaterInputStream.reset(Unknown Source)
    at java.io.FilterInputStream.reset(Unknown Source)
    at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(Unknown Source)
    at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
    at com.neet.Audio.JukeBox.load(JukeBox.java:26)
    at com.neet.GameState.IntroState.<init>(IntroState.java:28)
    at com.neet.GameState.GameStateManager.loadState(GameStateManager.java:48)
    at com.neet.GameState.GameStateManager.setState(GameStateManager.java:72)
    at com.neet.GameState.GameStateManager.<init>(GameStateManager.java:31)
    at com.neet.Main.GamePanel.init(GamePanel.java:70)
    at com.neet.Main.GamePanel.run(GamePanel.java:75)
    at java.lang.Thread.run(Unknown Source)

And here is the Audio class: `

package com.neet.Audio;

import java.util.HashMap;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

public class JukeBox {

    private static HashMap<String, Clip> clips;
    private static int gap;
    private static boolean mute = false;

    public static void init() {
        clips = new HashMap<String, Clip>();
        gap = 0;
    }

    public static void load(String s, String n) {
        if(clips.get(n) != null) return;
        Clip clip;
        try {           
            AudioInputStream ais =
                AudioSystem.getAudioInputStream(
                    JukeBox.class.getResourceAsStream(s)
                );
            AudioFormat baseFormat = ais.getFormat();
            AudioFormat decodeFormat = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,
                baseFormat.getSampleRate(),
                16,
                baseFormat.getChannels(),
                baseFormat.getChannels() * 2,
                baseFormat.getSampleRate(),
                false
            );
            AudioInputStream dais = AudioSystem.getAudioInputStream(decodeFormat, ais);
            clip = AudioSystem.getClip();
            clip.open(dais);
            clips.put(n, clip);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void play(String s) {
        play(s, gap);
    }

    public static void play(String s, int i) {
        if(mute) return;
        Clip c = clips.get(s);
        if(c == null) return;
        if(c.isRunning()) c.stop();
        c.setFramePosition(i);
        while(!c.isRunning()) c.start();
    }

    public static void stop(String s) {
        if(clips.get(s) == null) return;
        if(clips.get(s).isRunning()) clips.get(s).stop();
    }

    public static void resume(String s) {
        if(mute) return;
        if(clips.get(s).isRunning()) return;
        clips.get(s).start();
    }

    public static void loop(String s) {
        loop(s, gap, gap, clips.get(s).getFrameLength() - 1);
    }

    public static void loop(String s, int frame) {
        loop(s, frame, gap, clips.get(s).getFrameLength() - 1);
    }

    public static void loop(String s, int start, int end) {
        loop(s, gap, start, end);
    }

    public static void loop(String s, int frame, int start, int end) {
        stop(s);
        if(mute) return;
        clips.get(s).setLoopPoints(start, end);
        clips.get(s).setFramePosition(frame);
        clips.get(s).loop(Clip.LOOP_CONTINUOUSLY);
    }

    public static void setPosition(String s, int frame) {
        clips.get(s).setFramePosition(frame);
    }

    public static int getFrames(String s) { return clips.get(s).getFrameLength(); }
    public static int getPosition(String s) { return clips.get(s).getFramePosition(); }

    public static void close(String s) {
        stop(s);
        clips.get(s).close();
    }

}`

Upvotes: 2

Views: 4600

Answers (3)

Phil Freihofner
Phil Freihofner

Reputation: 7910

@Jim Garrison gives a good analysis of the issues involved. But a cleaner solution is to use getResource() instead of getResourceAsStream(). With this, there is no need for a wrapping class.

In the Javadocs for AudioSystem.getAudioInputStream() there are multiple entries, each with a different input parameter.

Obtains an audio input stream from the provided input stream. The stream must point to valid audio file data. The implementation of this method may require multiple parsers to examine the stream to determine whether they support it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, and reset the stream's read pointer to its original position. If the input stream does not support these operation, this method may fail with an IOException.

Obtains an audio input stream from the URL provided. The URL must point to valid audio file data.

Thus, for a wav resource, the following should work:

URL url = Jukebox.class.getResource(s);
AudioInputStream = AudioSystem.getAudioInputStream(url);

I don't know how you were able to bring in mp3 files. They are not supported by javax.sound.sampled. Perhaps they worked for you because you employed a library for decoding mp3 files as an intermediary step?

Upvotes: 1

Jim Garrison
Jim Garrison

Reputation: 86774

From the Javadoc (my hilighting):

public static AudioInputStream getAudioInputStream(InputStream stream)
                                        throws UnsupportedAudioFileException,
                                               IOException

Obtains an audio input stream from the provided input stream. The stream must point to valid audio file data. The implementation of this method may require multiple parsers to examine the stream to determine whether they support it. These parsers must be able to mark the stream, read enough data to determine whether they support the stream, and, if not, reset the stream's read pointer to its original position. If the input stream does not support these operation, this method may fail with an IOException.

You appear to be running from a jar file that contains both the code and the sound files. The InputStream returned from getResourceAsStream() will not work as it will be backed (or implemented) by a ZipInputStream, which treats mark() as a no-op, and throws an IOException for reset().

To solve the problem you should only need to wrap the input stream in a BufferedInputStream.

AudioInputStream ais =
    AudioSystem.getAudioInputStream(
        new BufferedInputStream(
            JukeBox.class.getResourceAsStream(s)
        )
    };

Upvotes: 5

user1766089
user1766089

Reputation: 19

Thank you everyone for your help but I've figured out that only .mp3 files work and not anything else as it does not process and encode them properly. I knew it was something easy like that and I don't yet have the ability to make it take any kind of sound files so I'll just leave this here for people who have the same problem and haven't thought of the easiest answer which took me a long while to figure out. Thank you!

Upvotes: 0

Related Questions