jar support for ogg loader

I noticed that the sound loaders are not “jar friendly” which means they don’t try to load a sound file from a jar. I tried to add it. I put the following lines at the beginning of OggLoader.load(String filename):


        try {
            file = new VorbisFile(filename);
            oggBitStream_ = new FileInputStream(filename);
        } catch (JOrbisException ex) {
            try {
                oggBitStream_ = getClass().getClassLoader().getResource(filename).openStream();
                file = new VorbisFile(oggBitStream_, null, 0);
            } catch (JOrbisException e) {
                throw new IOException(e.getMessage());
            }
        }

This loads from a file and falls back to loading from a jar. A clean implementation should put this in the load(URL) method.

This leads to other problems, although it seams to load the file :


javax.sound.sampled.LineUnavailableException: Failed to allocate clip data.
        at com.sun.media.sound.MixerClip.implOpen(MixerClip.java:551)
        at com.sun.media.sound.MixerClip.open(MixerClip.java:161)
        at com.xith3d.sound.drivers.javasound.SoundSourceImpl.setBuffer(SoundSourceImpl.java:82)
        at com.xith3d.sound.drivers.javasound.SoundSourceImpl.setContainer(SoundSourceImpl.java:100)
        at com.xith3d.scenegraph.View.processSoundNode(View.java:1175)
        at com.xith3d.scenegraph.View.renderNode(View.java:908)
        at com.xith3d.scenegraph.View.renderNode(View.java:991)
        at com.xith3d.scenegraph.View.getRenderFrame(View.java:824)
        at com.xith3d.scenegraph.View.renderOnce(View.java:717)
        at com.xith3d.scenegraph.View.renderOnce(View.java:655)
        at game.Game.run(Game.java:216)
        at game.Game.main(Game.java:270)
java.lang.Error: javax.sound.sampled.LineUnavailableException: Failed to allocate clip data.
        at com.xith3d.sound.drivers.javasound.SoundSourceImpl.setContainer(SoundSourceImpl.java:103)
        at com.xith3d.scenegraph.View.processSoundNode(View.java:1175)
        at com.xith3d.scenegraph.View.renderNode(View.java:908)
        at com.xith3d.scenegraph.View.renderNode(View.java:991)
        at com.xith3d.scenegraph.View.getRenderFrame(View.java:824)
        at com.xith3d.scenegraph.View.renderOnce(View.java:717)
        at com.xith3d.scenegraph.View.renderOnce(View.java:655)
        at game.Game.run(Game.java:216)
        at game.Game.main(Game.java:270)
Caused by: javax.sound.sampled.LineUnavailableException: Failed to allocate clip data.
        at com.sun.media.sound.MixerClip.implOpen(MixerClip.java:551)
        at com.sun.media.sound.MixerClip.open(MixerClip.java:161)
        at com.xith3d.sound.drivers.javasound.SoundSourceImpl.setBuffer(SoundSourceImpl.java:82)
        at com.xith3d.sound.drivers.javasound.SoundSourceImpl.setContainer(SoundSourceImpl.java:100)
        ... 8 more

Anybody knowing what’s going on here?

It’s not high priority for me, but I’d still be happy to solve this issue. :slight_smile:

getResourceAsStream instead of getResource guessing :slight_smile:

I wrote openStream(), so this is not a mistake.

Imho it’s not that easy. JOrbis isn’t jar friendly. They only support loading from a file (filename as String), not from an URL. I tried to work around this by using an InputStream. However this doesn’t work for Jars. I made a number of trials and they failed. This means we can’t use ogg files, if we need jar files for distribution. :-/ Does anybody have an idea? Are there other Ogg Vorbis players out there?

I also want to mention that Ogg support is one of the most wished features of the JRE: http://developer.java.sun.com/developer/bugParade/bugs/4499904.html

Btw. Unreal Tournament is using Ogg files, too. ;D It’s fully documented and patent free, so I don’t know why it should not be in the JRE.

Are there other Ogg Vorbis players out there?

Dunno… but JOrbis is fine :slight_smile:

Cas had used it for AF, too. Therefore the loading from jars just has to work somehow.

Hmyea seems to be also a part of SPGL

Check the source of:
src/com/shavenpuppy/jglib/sound/OggVorbis.java

right you are.

The file is here:
http://cvs.sourceforge.net/viewcvs.py/spgl/spgl/src/com/shavenpuppy/jglib/sound/OggVorbis.java?view=markup


            if (url.startsWith("classpath:")) {
                  // Load directly from the classpath
                  input = new BufferedInputStream(getClass().getClassLoader().getResourceAsStream(url.substring(10)));
            } else {
                  // Load from a URL
                  input = new BufferedInputStream(new URL(url).openStream());
            }


 * Code in here adapted from JOrbis example code. Thanks guys.

however there is a metric ton of code in that method (fortunatally it is nicly commented :)) It seems odd that that much code is needed just to play an Ogg, I would have thought the OGG API could have abstracted some of it.

Maybe we should just ask princec :slight_smile:

Will.

Eh?

It Just Works. Don’t ask me how it works :wink:

Cas :slight_smile:

I just realised that Cas’ and Davids implementation are similar to the example decoder of JOrbis. I don’t know why JOrbis didn’t abstract this code out.

Anyway, I’m near to having jar support. I have only one issue with calculating the decoded length of the audio output, but I hope I can solve this.

Jar support for ogg loader is now committed to Xith3D CVS. :slight_smile:

(Testcase for loading an ogg file from a jar added as com.xith3d.test.Xith3DOggLoaderJarTest and demo/ogg_jar_test.jar. Please test.)

It looks like they left it to the likes of us to abstract it out for them. Strange really as it’s a really common bit of code I should think.

Something that streams OGGs into an OpenAL double buffered arrangement would be a great addition too. It’s not really wise to load a whole 3mb OGG and decompress it into memory to play it…

Cas :slight_smile:

[quote]Jar support for ogg loader is now committed to Xith3D CVS. :slight_smile:

(Testcase for loading an ogg file from a jar added as com.xith3d.test.Xith3DOggLoaderJarTest and demo/ogg_jar_test.jar. Please test.)
[/quote]
Thanks - nice going.

Just in time for todays xith.org JWS update ;D

Will.

JWS online:

http://xith.org/jws/jws-com.xith3d.test.Xith3DOggLoaderJarTest.jnlp

I get an error but that may be my sound setup.


JavaSound sound driver initialized with 61 availble sources
java.lang.NullPointerException
      at com.xith3d.sound.drivers.javasound.SoundSourceImpl.setContainer(SoundSourceImpl.java:100)
      at com.xith3d.scenegraph.View.processSoundNode(View.java:1184)
      at com.xith3d.scenegraph.View.renderNode(View.java:917)
      at com.xith3d.scenegraph.View.renderNode(View.java:1015)
      at com.xith3d.scenegraph.View.getRenderFrame(View.java:824)
      at com.xith3d.scenegraph.View.renderOnce(View.java:717)
      at com.xith3d.scenegraph.View.renderOnce(View.java:655)
      at com.xith3d.test.Xith3DOggLoaderJarTest.<init>(Xith3DOggLoaderJarTest.java:126)
      at com.xith3d.test.Xith3DOggLoaderJarTest.main(Xith3DOggLoaderJarTest.java:65)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:324)
      at com.sun.javaws.Launcher.executeApplication(Launcher.java:837)
      at com.sun.javaws.Launcher.executeMainClass(Launcher.java:797)
      at com.sun.javaws.Launcher.continueLaunch(Launcher.java:675)
      at com.sun.javaws.Launcher.handleApplicationDesc(Launcher.java:390)
      at com.sun.javaws.Launcher.handleLaunchFile(Launcher.java:199)
      at com.sun.javaws.Launcher.run(Launcher.java:167)
      at java.lang.Thread.run(Thread.java:534)

The demo needs a file “birds_jar.ogg” (open the ogg_jar_test.jar with e.g Ark to see this). This is a copy of birds.ogg. I had to make a copy, because otherwise you can’t know wether it loads the file from the jar or not. birds_jar.ogg is not in your resource.jar. ogg_jar_test.jar is there, but I don’t think Java searches for nested jar files.

Jens,

I have corrected the problem (changed the jws build task to accommodate for the .jar file) and it now works for me.

Your improvement is most appreciated by us folk distributing by JWS - thanks. Now all I need are some sounds :wink:

new resource.jar is uploaded - link is as before:
http://xith.org/jws/jws-com.xith3d.test.Xith3DOggLoaderJarTest.jnlp

I’ll update the demo/ page soon.

Can you correct the “SoundTest” demo using your new method? (com.xith3d.test.SoundTest) currently it won’t work with JWS. Currently both other sound demo’s listed on xith.org arn’t operational.

Cheers,

Will.

I committed the changed demos to CVS. The joal demo did never work for me.

[quote]I committed the changed demos to CVS. The joal demo did never work for me.
[/quote]
now it doesn’t load it from the file - can you get it to first try to load it direct and then from a jar if that fails?

Also if you’re editing things - a file not found exception (with a message) would be kinder than the current null pointer exception :slight_smile:


java.lang.NullPointerException
        at com.xith3d.sound.drivers.javasound.SoundSourceImpl.setContainer(SoundSourceImpl.java:100)

The joal demo doesn’t work here caus I havn’t installed joal - maybe I should do that :slight_smile:

Cheers,

Will.

InputStream loading compatibility is also broken now - MediaContainer.java throws NPE at line 94 because of no sound object created for InputStream.

At least WAV loader should be created to maintain compatibility with the older code:

      } else if(inputStream != null) {
          sound = new WavLoader();
          // what do to here?
      }

Anyway, I think we should separate content-type detection mechanism from the node itself to allow pluggable loaders for different sound formats.

I am thinking about generic support for image/sound loading using imageio/sound APIs [this is just an idea, nothing formalized for a moment, and, anyway, additional layer of abstraction that will isolate Xith3D from these APIs would be also good].

Yuri

You’re right of course (sorry), although I think it’s not a good solution to simple use a WavLoader, if we don’t know what the format is. As a simple solution for now, do you think an additional constructor MediaContainer(InputStream inputStream, String format) would do the job (or possibly a constant instead of a string)? Wav could still be the default.

Agree on additional constructor.

String should be OK, at least because of TextureLoader also accepts String as image format identifier.

Yuri

Changes are committed now.

It’s good that you said this Yuri, because I wanted to ask how to handle format detection with InputStreams anyway. Don’t know why I didn’t do it. I added also some documentation and error handling. If it is not correct please tell me (via private message if it’s a specific thing). Code formatting, error handling and logging conventions would be useful in my opinion.