Java MOD/XM Playback

After a long delay, and prompted by the mysterious disappearance of the Ana-mp project, I am pleased to announce the initial release of the kbmod and kbxm java module players.

These are going to need a little bit of work before they are totally suitable for game development, but I suppose you have to start somewhere.

You can download the players from http://www.geocities.com/sunet2000/

Regards,
Martin

Ooooh XM ;D

Micromod was already really nice but this is a really sweet surprise… and it isn’t even xmas :slight_smile:

Right now it’s LGPLed, wich doesn’t really work for Java (the license itself is absolutely ok for C/C++ stuff). Since most people doesn’t like having legal gray areas involved, it might be a good idea to switch to a more appropriated license (BSD style or something similar to the license of lwjgl).

See this thread:
http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=announcements;action=display;num=1081963711

Oh and welcome to the board :slight_smile:

Just checked it with some modules. It’s really great :slight_smile:

Unfortunately one of the modules caused kbxm to bomb out (at the very end of the track) for some weird reason.


 KBXM Fast Tracker 2 Replay ALPHA 0.7
 Copyright (C)2004 Martin Cameron (sunet2000@yahoo.com)
 Website - http://www.geocities.com/sunet2000/

 Filename : Spr-stil.xm
 Song Name: still with me?      
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 35
      at kbxm.Sequencer.setrow(Sequencer.java:87)
      at kbxm.Sequencer.tick(Sequencer.java:80)
      at kbxm.KBXM.getAudio(KBXM.java:94)
      at xmplayer.XMPlayer.main(XMPlayer.java:45)

Here is the file:
–deleted many moons ago-- (~1.8mb)

Hmm,

i tested it with serveral .mod’s from Amiga Demo Archiv, but no one was falid, i allways get the “No Vaild Mod” Exception.

Stay Tuned,
Jens

Try this one:
–deleted many moons ago-- (~246kb)

The mod player is somewhat restricted. 4 channel NoiseTracker and most ProTracker modules.

edit: yabb doesnt like urls with spaces :stuck_out_tongue:
edit²: I guess I could have used %20 aswell (instead of renaming on the server) :>

Hi there!

I’ll look into it!

Well, I didn’t call it alpha for no reason! At least it let you hear the tune before crashing :slight_smile: It looks like a bad module with an invalid pattern break (I don’t do a lot of checking for things like that). I’ll fix it.

Well, my collection is 100% 4 channel amiga mods, so that’s what I focused on. I wasn’t sure if anybody used the “multichannel” mod formats like FTK (I added support to micromod after 1 request). Also the extra panning command added to FTK conflicts with some of my amiga mods which used the effect for video synchronization.
Adding FTK support with panning etc is literally about 10 lines of code. I’ll put that on my todo list :slight_smile: Thanks onyx!

This might be a stupid question, but are you trying to load .mods into kbxm? You need to use kbmod to play mods. I’ve got a good reason for splitting the two players up. XM is really not very similar to MOD and each format has it’s own quirks. It’s much better for good playback to use separate code. I suppose I should be reusing some of the common bits like the mixer and front end. That’s a job for later I suppose.

Cheers!
Martin

I’ll look into it!

Thanks :slight_smile:

I’ll fix it.

Thanks again :smiley:

Playing mods is great! I used to love listening to them on my Amiga. This sounds like it would be better than trying to use rmf files.

Keep it up!

Regards,
Aaron R>

It’s great! ;D Now we await an implementation of the famous MicroMod-realTimePlayBack. :wink: I modified the code to use normal java-buffering without blocking, but the test-animation would take some small regular pauses from time to time…

What garbage collection algorithm were you using? Try the incremental collector or -XX:+UseConcMarkSweepGC.

That might eliminate any pauses if they were GC related.

Hi!

Garbage collection tweaking will not help with this problem unfortunately. It is caused by the fact that JavaSound is a load of crap. You can only do blocking writes to the sound device because the available() and getMicroSecondPosition() methods of DataLine are too inaccurate (they return values that only change when the buffer is half full).

I solved this in MicroMod by using a timer that estimated the amount of data that could be written to the buffer without blocking, and mixed only the amount of samples that were required. This meant that you could calculate the audio in the graphics thread, eg every frame. This required some quite complicated code because of things like volume ramping.

The current players are simplified as much as possible, and so this is not implemented. The best you can try right now is reducing the buffer size to about 20ms (which is the default “tick” length in MOD).

In the next version (when I get around to it!), I will put this feature back in. I’m also planning on getting it integrated into a gaming library and converting it to use integer arithmetic for J2ME :slight_smile:

Regards,
Martin

Also, about GC, I’m very careful not to allocate objects during playback, so my player should never trigger a garbage collection.

[quote]…prompted by the mysterious disappearance of the Ana-mp project
[/quote]
I’m sorry about that… The explanation is simple: My old university account finally expired. The new home of ana-mp is at http://ana-mp.sourceforge.net/

Any new versions coming up?.. :wink:

Oh… there’s another mod lib :o

It’s also LGPL mmh :-/

Y’know the LGPL is somewhat scary for the java folks, because it doesn’t fit. I read the license several times and followed alot of discussions and I’m still not sure what I should think of it.

Please consider another license (BSD style is preferred for java stuff these days ;)).

Btw the the download links are broken. They contain an additonal ‘’, which doesn’t belong there.

Eg:
https://sourceforge.net/project/showfi\les.php?group_id=103725

instead of:

https://sourceforge.net/project/showfiles.php?group_id=103725

[quote]It’s also LGPL mmh
[/quote]
Yes, it is :slight_smile: I use the lgpl simply because I want modifications to it to be free, while I don’t really care about software that only uses (links to) it. If you know of a (non-obscure) license that let me express the same thing, please let me know. I suspect though, that If I had to change the license, I’d go for the gpl, not something bsd’ish.

[quote]Btw the the download links are broken.
[/quote]
Thanks for pointing that out. A little copy/paste accident…

Yes, I know. LGPL sounds great - theoretically. However, how it has to be applied to java is pretty much undefined, which means it’s a risk.

GPL would prevent 95% or even more from using it. It’s highly unlikely that I’ll ever use any GPLed lib.

BSD sounds like a bad deal at the first glace… but y’know there is common sense. If I find a bug or a way to improve it, I’ll let those guys know about it. Everything else would be plain silly, because I would have to change each upcoming version again and again and again - there is really no benefit doing so :wink:

Or let’s say I need some kind of flag for changing the behaviour of parts of a lib for one special case. Let’s also asume that no one else could use something like that or that it’s a very cheap thing. A forced release of this oddly forked lib wouldn’t do any good.

Hi,

Firstly great work on kbmod :slight_smile:

I seem to have a problem though. I want load my .mod’s from their own .jar. This is so I can update my game code (in another .jar) whenever I like and users don’t need to redownload the music files.

I have written some code to perform this, but for some reason I always have a corrupt inputstream, the music plays ok to begin with (just), then gets worse.

Any ideas where i’m going wrong on this (code below)?

Ideally, however, I would like to use some other .mod code that I have already within my game (it’ll be a nightmare to switch to kbmod at this point). This, however, uses RandomAccessFile for loading the .mod, not streams.

I understand from trying to do this all day that I can’t use that directly as the file is in .jar, and a seperate one from the playback code, at that, so streams, I was informed was the only way to go. Then I found kbmod and tried to get it working.

Is there an easy way to make JNLP work with RandomAccessFile at all? Somebody suggested extracting the file on execution and using that, but I don’t see an easy way to do that.

Is there something obvious i’m overlooking for using RandomAccessFiles within JNLP jar’s?

On a side note I gave a shareware JNLP creator a whirl and it seemed to fix up my original (definately non-JNLP compatible - playing the .mods from the same .jar, however) code somehow. Still a big step ahead of me (who currently sees no easy way to play .mods with JNLP/JARs). :frowning:


public class Player {

      JarFile jar = null;
      InputStream entryStream = null;
      Module m = null;
      SourceDataLine line = null;
      JarEntry entry = null;

      public Player()
      {

            PlayStream();

      }

      public void PlayStream()
      {

            try
            {
                  m = new Module(this.load());
            }
            catch (Exception e)
            {}

            KBMod player = new KBMod( m );
            System.out.println( " Song Name : " + m.name );

            // Allocate the output buffers.
            float[] lBuf = new float[3600];
            float[] rBuf = new float[3600];
            byte[] output = new byte[14400];

            AudioFormat format = new AudioFormat( 44100, 16, 2, true, false );
            DataLine.Info lineInfo = new DataLine.Info( SourceDataLine.class, format );
            try
            {
                  line = (SourceDataLine)AudioSystem.getLine(lineInfo);

                  line.open( format );
                  line.start();
            }
            catch (Exception e)
            {
            }

            while( true )
            {
                  int len = player.getAudio( lBuf, rBuf );
                  int outpos = 0;
                  for( int n=0; n<len; n++ )
                  {
                        short l = (short)( lBuf[n]*32767 );
                        short r = (short)( rBuf[n]*32767 );
                        lBuf[n] = 0;
                        rBuf[n] = 0;
                        output[outpos++] = (byte)(l&0xFF);
                        output[outpos++] = (byte)(l>>8);
                        output[outpos++] = (byte)(r&0xFF);
                        output[outpos++] = (byte)(r>>8);
                  }
                  line.write( output, 0, len<<2 );
            }
      }

      public InputStream load()
      {

            try
            {
                  jar = new JarFile("Music.jar");
            }
            catch (Exception e)
            {}
            Enumeration entries = jar.entries();

            // Get the next entry.
            entry = (JarEntry) entries.nextElement();

            // Get an input stream for the entry.

        try
        {
              entryStream = jar.getInputStream(entry);
            }
            catch (Exception e){}

            return entryStream;
      }

      public static void main( String[] args ) throws Exception
      {
            Player p = new Player();
      }
}

kbmod outputs these errors:

Instrument 1 : 903 samples missing!
Instrument 3 : 365 samples missing!

LGPL has lots of stupid little clauses that slip your attention but actually prevent a lot of commercial applications from using LGPL code.
One example is that programs that use LGPL code must be released under a licence that permits reverse engineering.

[quote] If you know of a (non-obscure) license that let me express the same thing, please let me know.
[/quote]
I think the Apache Licence does what you want.
I use it for all my (free) projects.
I’m pretty sure (98%) that modifications have to be released under the same licence.
Anybody who knows better, please correct me.

Would it be possible to use the modplayer in a applet?