9 Replies - 9908 Views - Last Post: 08 October 2011 - 10:15 PM Rate Topic: -----

#1 gfcf14  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 90
  • Joined: 19-January 11

Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 03 October 2011 - 04:50 PM

Hello to all. I've been programming a game since the beginning of the year, and I have it pretty much complete (it's very simple) so I tried building a JAR out of it. But when I did all the sources I used (text docs, pictures, sound files) were excluded so the game didn't work properly. I tried to include these sources as in my project as far as I could understand the people helping me (see here http://www.dreaminco...4-jar-problem/), but I couldn't do it. What I did notice was that the JAR I used to play MP3s (http://introcs.cs.princeton.edu/java/faq/mp3/mp3.html) was included in the build process, since I had added it to the project library, and because Command Prompt (I use Windows and tried running the jar through it) printed out a NullPointer Exception (because of the files' abscence) from the MP3 class that used libraries from it. So I have put all of my source files in JARs using IZArc, and so far have been able to load pictures (thanks to Dogstopper's tutorial http://www.dreaminco...art-1-loading/) and text files (using http://www.rgagnon.c...java-0077.html), but I couldn't do the same thing with my MP3 JAR, so I tried using the Java Media Framework (JMF) to play mp3 files. I downloaded the setup files for both the JMF and its MP3 plug-in for Windows, and installed them. Then I found this tutorial (http://codeidol.com/java/swing/Audio/Add-MP3-Support-to-JMF/), so I tried to first play an mp3 WITHOUT using a jar, straight from an address, and it worked! But since I have my sources on a JAR I had to do it that way. I copied the whole class and modified it some to look like this:

package racemaster;

import javax.media.*;

//To run this class, JMF and its MP3 plug-in must be installed in the PC

public class SoundFile {
    String filename;

    public SoundFile(String filename) {
        this.filename = filename;
    }
    
    public void play() throws Exception {
            MediaLocator mrl = new MediaLocator(getClass().getResource(filename));            
            Player player = Manager.createPlayer(mrl);
            player.start();            
    }
    
    public String getFileName(){
        return filename;
    }
}



So that the mp3 (and even wav) could be called declaring a SoundFile variable with a String representing the file name and using its play() method.

I then ran my program, only to find that when the sound is attempted to be played, I get

javax.media.NoPlayerException: Cannot find a Player for :jar:file:/F:/RaceMaster/src/racemaster/Music.jar!/readysetgo.mp3


Is it normal for the IDE (I use NetBeans) to read the JAR address as .jar! ? Anyways the error points to the line

MediaLocator mrl = new MediaLocator(getClass().getResource(filename));


So after searching some more I tried adding the .getClassLoader() method to see if it could play, but instead of getting the NoPlayerException I get a NullPointerException, yet I don't know which variable is null, since the filename variable is passed correctly. I've seen another tutorial where they recommend to add a "file:///" to the MediaLocator parameter, so I change it to this:

MediaLocator mrl = new MediaLocator("file:///" + getClass().getClassLoader().getResource(filename).getFile());


And get a NullPointerException. I tried like this:

MediaLocator mrl = new MediaLocator("file:///" + getClass().getClassLoader().getResource(filename));


And get
java.io.IOException: File Not Found
for the SoundFile to be played, and

javax.media.NoPlayerException: Error instantiating class: com.sun.media.protocol.file.DataSource : java.io.IOException: File Not Found


so I'm really not sure how to get around this. Please let me know if anyone knows anything, I think I'm pretty close to get it all done =D Any help or thoughts are very welcome and appreciated! (sorry if it was too long, but I wanted to explain everything to avoid any confusion)

Is This A Good Question/Topic? 0
  • +

Replies To: Java Media Framework (JMF) problem playing mp3 from a JAR

#2 Greltam  Icon User is offline

  • D.I.C Head

Reputation: 90
  • View blog
  • Posts: 225
  • Joined: 29-January 09

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 03 October 2011 - 06:25 PM

From my experience and the help I've gotten from people on DIC, I've learned you can't point to a file within a jar. This probably has to do with the JAR being compressed, which is like having your program point to a file within a .zip. What you can do is have the JRE get an inputstream for the data you want to access in your jar, using getResourceAsStream. Another workaround would be to install your files outside of the jar which would allow for File useage.

I haven't used your mp3 player jar, but I've had good success using getResourceAsStream to load text files, images(imageIO), and sounds(using AudioSystem) from within a jar.
Was This Post Helpful? 0
  • +
  • -

#3 gfcf14  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 90
  • Joined: 19-January 11

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 03 October 2011 - 07:15 PM

You're right, maybe I'm overdoing it relying on the JMF, but if there was a way to do it with it it would be cool. Anyways I did think about the getResourceAsStream(), but as you can see from these classes http://introcs.cs.pr...3/MP3.java.html , and http://www.anyexampl..._sound_file.xml I would need to convert the resulting InputStream into a FileInputStream or an AudioInputStream. Do you happen to know? Please do let me know
Was This Post Helpful? 0
  • +
  • -

#4 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8334
  • View blog
  • Posts: 31,857
  • Joined: 06-March 08

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 03 October 2011 - 07:17 PM

getClass().getRessource(String name);
returns an URL not a File, and you can't make a File object out of it
getClass().getRessourceAsStream(String name);
returns an InputStream. You will have to access the file content of the "File" through that InputStream.
Was This Post Helpful? 1
  • +
  • -

#5 Greltam  Icon User is offline

  • D.I.C Head

Reputation: 90
  • View blog
  • Posts: 225
  • Joined: 29-January 09

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 04 October 2011 - 07:47 AM

AudioSystem.getAudioInputStream() accepts a plain InputStream as one of it's arguments.
For FileInputStream, no. That works with Files. However, you pass that stream to a BufferedInputStream, which accepts any inputStream, and I believe it would work with the stream returned from class.getResourceAsStream().
//Class MP3
    public void play() {
        try {
            InputStream is = /*class*/.getResourceAsStream(filename);
            BufferedInputStream bis = new BufferedInputStream(is);
            player = new Player(bis);
        }
        catch (Exception e) {
            System.out.println("Problem playing file " + filename);
            System.out.println(e);
        }
//Class AePlayWave
    public void run() { 
        /*Remove this, no need for files if using streams
        File soundFile = new File(filename);
        if (!soundFile.exists()) { 
            System.err.println("Wave file not found: " + filename);
            return;
        }
        */
 
        AudioInputStream audioInputStream = null;
        try { 
            audioInputStream = AudioSystem.getAudioInputStream(
                /*class*/.getResourceAsStream(fileName));//Pass inputStream to AudioSystem
        } catch (UnsupportedAudioFileException e1) { 
            e1.printStackTrace();
            return;
        } catch (IOException e1) { 
            e1.printStackTrace();
            return;
        } 


Was This Post Helpful? 1
  • +
  • -

#6 gfcf14  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 90
  • Joined: 19-January 11

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 07 October 2011 - 04:17 PM

Thank you! I tried the mp3 sounds at first and they seemed to loop and that gave me an exception specific to the JAR I'm using for the mp3 files, but it was because they were played within an actionPerformed() method, so it was an easy fix. The sounds that are not working are the wavs, even if they are not repeated over and over. I did my WAV class as you showed me, like this:

package racemaster;

import java.io.IOException; 
import javax.sound.sampled.AudioFormat; 
import javax.sound.sampled.AudioInputStream; 
import javax.sound.sampled.AudioSystem; 
import javax.sound.sampled.DataLine; 
import javax.sound.sampled.FloatControl; 
import javax.sound.sampled.LineUnavailableException; 
import javax.sound.sampled.SourceDataLine; 
import javax.sound.sampled.UnsupportedAudioFileException; 
 
public class WAV extends Thread { 
 
    private String filename;
 
    private Position curPosition;
 
    private final int EXTERNAL_BUFFER_SIZE = 524288; // 128Kb 
 
    enum Position { 
        LEFT, RIGHT, NORMAL
    };
 
    public WAV(String wavfile) { 
        filename = wavfile;
        curPosition = Position.NORMAL;
    } 
 
    public WAV(String wavfile, Position p) { 
        filename = wavfile;
        curPosition = p;
    } 
 
    public void run() { 
 
        AudioInputStream audioInputStream = null;
        try { 
            audioInputStream = AudioSystem.getAudioInputStream(WAV.class.getResourceAsStream(filename));
        } catch (UnsupportedAudioFileException e1) { 
            e1.printStackTrace();
            return;
        } catch (IOException e1) { 
            e1.printStackTrace();
            return;
        } 
 
        AudioFormat format = audioInputStream.getFormat();
        SourceDataLine auline = null;
        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
 
        try { 
            auline = (SourceDataLine) AudioSystem.getLine(info);
            auline.open(format);
        } catch (LineUnavailableException e) { 
            e.printStackTrace();
            return;
        } catch (Exception e) { 
            e.printStackTrace();
            return;
        } 
 
        if (auline.isControlSupported(FloatControl.Type.PAN)) { 
            FloatControl pan = (FloatControl) auline
                    .getControl(FloatControl.Type.PAN);
            if (curPosition == Position.RIGHT) 
                pan.setValue(1.0f);
            else if (curPosition == Position.LEFT) 
                pan.setValue(-1.0f);
        } 
 
        auline.start();
        int nBytesRead = 0;
        byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
 
        try { 
            while (nBytesRead != -1) { 
                nBytesRead = audioInputStream.read(abData, 0, abData.length);
                if (nBytesRead >= 0) 
                    auline.write(abData, 0, nBytesRead);
            } 
        } catch (IOException e) { 
            e.printStackTrace();
            return;
        } finally { 
            auline.drain();
            auline.close();
        } 
 
    } 
} 



But whenever I play a wav file in the game (when I bump the car or the winning/losing sounds) I get this IOException:

java.io.IOException: mark/reset not supported
	at java.util.zip.InflaterInputStream.reset(InflaterInputStream.java:286)
	at java.io.FilterInputStream.reset(FilterInputStream.java:226)
	at com.sun.media.codec.audio.mp3.JS_MP3FileReader.getAudioFileFormat(JS_MP3FileReader.java:226)
	at com.sun.media.codec.audio.mp3.JS_MP3FileReader.getAudioInputStream(JS_MP3FileReader.java:131)
	at com.sun.media.codec.audio.mp3.JS_MP3FileReader.getAudioInputStream(JS_MP3FileReader.java:93)
	at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1111)
	at racemaster.WAV.run(WAV.java:39)



pointing at line 39 of the WAV class

 audioInputStream = AudioSystem.getAudioInputStream(WAV.class.getResourceAsStream(filename)); 


which in turn points to the AudioSystem's getAudioInputStream method:

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

        List providers = getAudioFileReaders();
        AudioInputStream audioStream = null;

        for(int i = 0; i < providers.size(); i++ ) {
            AudioFileReader reader = (AudioFileReader) providers.get(i);
            try {
                audioStream = reader.getAudioInputStream( stream ); // throws IOException
                break;
            } catch (UnsupportedAudioFileException e) {
                continue;
            }
        }



referring to line 1111 of the class, being

 audioStream = reader.getAudioInputStream( stream ); // throws IOException 


but I looked further and, though it seems redundant, the FilterInputStream class says that the reset method

public synchronized void reset() throws IOException {
        in.reset();
    }


"Tests if this inputstream supports the mark and return methods", and that it simply performs the markSupported() method . Exactly what would be wrong with the WAV class that makes my sounds not support mark and reset? I could always try and convert my sounds to mp3 but I'd really like to run wavs properly. Please let me know if you have any idea on how to make my wav sounds mark and reset supported.
Was This Post Helpful? 0
  • +
  • -

#7 Greltam  Icon User is offline

  • D.I.C Head

Reputation: 90
  • View blog
  • Posts: 225
  • Joined: 29-January 09

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 08 October 2011 - 08:27 AM

Haha oh jeese. This sounds like one of those super quirks you need an experienced Java Sound person to handle. It appears as though your AudioInputStream loading is going through
com.sun.media.codec.audio.mp3.JS_MP3FileReader.getAudioInputStream(JS_MP3FileReader.java:93)

(Is that the JAR you're using for mp3's?). That might be the problem, Java might be trying to get an MP3 stream instead of a WAV stream? as when I load .wav it appears to be going through
com.sun.media.sound.WaveFileReader.getAudioInputStream(Unknown Source);


Although, I have only ever touched Clips by using:
  clip = AudioSystem.getClip();
  clip.open(AudioSystem.getAudioInputStream(
    this.getClass().getResourceAsStream(filePath)));



Again, might want to find someone experience with Java Sound, or this could be something you end up having to solve yourself.

**Update**
I copied your code and it works for me. I put a file named Teleport.wav in the same folder, wrote a main method that did
WAV sound = new WAV("Teleport.wav");
sound.start();

and it played
So at this point I'd have to assume you need to figure out some way to get media.sound.WaveFileReader to open your stream.

This post has been edited by Greltam: 08 October 2011 - 08:49 AM

Was This Post Helpful? 1
  • +
  • -

#8 gfcf14  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 90
  • Joined: 19-January 11

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 08 October 2011 - 02:12 PM

Thank you again =) I did look around and it seems even the Oracle page recommends using a Clip file to play wavs (http://download.oracle.com/javase/tutorial/sound/playing.html), but I still got the mark and reset error in the IOException. And well I really wanna get this done to start doing other games (namely from other genre besides racing), so I used WavePad (http://www.nch.com.au/wavepad/index.html) to convert my wav files (just 3) to mp3. I did expect them to work, and they did, even the bump sound which now repeats over and over without an error, but I certainly didn't expect the conversion to give me shorter files! (I always thought all mp3s would be bigger than wavs but apparently not in this case) I'll try to ask a question to the Oracle guys about this issue so that wave sounds from JAR files can get properly played, and when I get something from them, I'll make sure to post it here. Anyways, thank you so much for the help, I am now gonna iron out some bugs in my game to get it done once and for all. Can I ask, if I wanted to make a topic to thank to you and the other users who helped me through this game, what section would be better for it?
Was This Post Helpful? 0
  • +
  • -

#9 Greltam  Icon User is offline

  • D.I.C Head

Reputation: 90
  • View blog
  • Posts: 225
  • Joined: 29-January 09

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 08 October 2011 - 07:01 PM

I don't know about the other people that have helped you, but there is a Game programming section on DIC you could put up some details/screenshots of your game. I check it out every so often.

I'm intrigued by your problem playing .wav files. I copied both your WAV and MP3 classes into a file, supplied valid files for them to play, and they both,well, played( I did extract the jl1.0 jar's contents to the folder though). If you'd like, I could take a look at your project and see if I can surmise some way of fixing it.

Also, thank you for pointing me to a Java friendly Mp3 player. I believe it will be useful in the future.
Was This Post Helpful? 0
  • +
  • -

#10 gfcf14  Icon User is offline

  • D.I.C Head

Reputation: 0
  • View blog
  • Posts: 90
  • Joined: 19-January 11

Re: Java Media Framework (JMF) problem playing mp3 from a JAR

Posted 08 October 2011 - 10:15 PM

Yeah so far it's better than having to go through the handling of the JMF. But I think that my wav sounds are not working because I tried to load them straight off the JAR. Did you do it in the same way, or did you have the sounds in the same directory of the project/executable jar of your project?

It may be silly, but since I wanted to re-implement the save and load feature of my game, I tried loading whatever was in the same directory of the project, and it worked, then built a JAR of it, and tried saving a game (basically a notepad file) which created itself in the same directory of the JAR (so if the JAR was on drive C:/ then the notepad file saved itself there). Then when I loaded it I called it from the path where I saved it, without using getResource(), and it loaded. So if that worked, if I had my wavs in C:/ and had tried calling them with that path then they probably would've played normally. The fact that I could have all my source files outside of the JAR, but in the same path, makes all my effort to load from JAR pointless, but at least this way everything is together and there's no risk to lose any resource and create an Exception in the middle of playing the game.

If you would like to see the JAR I can send it to you, so let me know. Although the game is pretty much all finished, there are still some bugs that I have to fix, but since I've been solving some pretty nasty exceptions before by myself, I'll just ask you for help if I'm really stuck =)
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1