Under the hood - AndModPlug

Want to say thanks?

If you find my work useful in your projects and would like to say thanks, you can click the button below to see how to donate (via PayPal or just by buying one of the very affordable games :)

Make a small donation with PayPal

($2 to $5 is really helpful with dev costs! Especially since this is currently my only source of income)

Donate with Paypal.

Building and modifying AndModPlug and libmodplug

Here's how to build libmodplug & Java wrapper classes "from scratch" if you want to modify the libmodplug C++ code or the classes yourself.

Ask questions and support the work

If you have questions, follow me on Twitter (@peculiargames) and ask away! BTW, Twitter mentions are always appreciated! Try out the tweet button above to say you were here. Or click the "Support an Indie Developer" button to the right, go to the Android Market for my apps and find the "email developer" link.

Why should you care about tracker music as a developer?

Because it can reduce the size of your soundtrack by a factor of 10. See the Soundtracks page for an example of this - an Android apk that uses libmodplug to play the full soundtracks of my games Voyage to Farland and RGBbot! (44 songs in 1.2MB)

ModPlayer2.zip below is a sample apk file with source code. If you're just looking for a pre-built library and jar, see AndModPlug.

Here's info for how to compile libmodplug with the Android NDK and use it in your games.

I got the idea to try building libmodplug with the Android NDK from sasq's cool modplayer app "Droidsound", which is also available in the Android Market here!

NOTE:

The Android team has done an awesome job with the latest NDK releases. You don't need cygwin any more and can build without it. I'll update this info in the coming days with the latest build instructions. In the mean time, with the latest Android NDK rev 8 you can edit the custom builder -- right click Project in Eclipse, select Properties, then Builders, click on Native_Builder and then Edit and use these:

Location:

C:\android-ndk-r8\ndk-build.cmd

(or wherever your ndk is installed)

Working Directory:

${project_loc}

Arguments:

APP_ABI=all

(to build libraries for ARM, MIPS and x86)

Stay tuned for fully updated instructions.

- Patrick May 24, 2012

CAVEAT (for Android NDKs older than rev 7):

- I'm using cygwin on Windows Vista per the Android NDK docs suggestions (the very latest Android NDK rev 7 has an experimental feature where you can build ARM binaries without using cygwin - you could give it a try also).

Basic steps for compiling libmodplug:

1) Install the Android NDK and cygwin (if you're on Windows) and verify that they work. A working cygwin installation may take a while (in particular, you may have to hand-install make and a few other tools).

2) Grab the latest version (0.8.8.4 as of September 2011) of libmodplug from here:

http://modplug-xmms.sourceforge.net/

3) Make a jni sub-directory in your Android project directory. Note that the example project in ModPlayer2.zip below has jni_stubs.cpp (jni interface code for libmodplug) and an Android.mk makefile (which will build the libmodplug source along with the JNI stub code).

4) Extract just the libmodplug/src directory into <yourproject>/jni. In my configuration, I have all the .cpp and .h files (and the libmodplug sub-directory with 3 header files) in <myproject>/jni

5) Add the PlayerThread.java class to your project, and code up your activity to use it. Something like this (see the zip file for a real example - newer AndModPlug version has a MODResourcePlayer class that allows you to simply pass a raw resource and it'll do the rest):

// to get player instance (in topmost activity that will use music)

player = new PlayerThread();

//

// read in your MOD file from a resource

modfileInStream = getResources().openRawResource(R.raw.amazingsong);

try {

modsize = modfileInStream.read(modData,0, PlayerThread.MAXMODSIZE);

} catch (IOException e) {

e.printStackTrace();

}

// to call libmodplug's Load() function with the MOD data

//

player.LoadMODData(modData);

player.start();

//

// then for transition to another MOD song

player.PausePlay();

player.UnLoadMod();

//

// to load in the new mod file

player.LoadMODData(newmodfiledata);

player.UnPausePlay();

// repeat...

6) Build the JNI header file from your modplug interface class (I call mine PlayerThread.java) from your project base directory:

javah -classpath bin/classes -jni com.peculiargames.modplayer2.PlayerThread

NOTE: if you're using a version of ADT (Android Development Tools Plugin for Eclipse) older than revision 14, the classes are stored in the project's bin directory (not bin/classes) so for older ADTs:

javah -classpath bin -jni com.peculiargames.modplayer2.PlayerThread

or

javah -classpath bin -jni com.peculiargames.andmodplug.PlayerThread

if you're building the new AndModPlug code here.

7) Add that header and the jni.h header to your jni interface code (in my example, jni_stubs.cpp)

#include <jni.h>

#include "com_peculiargames_modplayer2_PlayerThread.h"

8) Start up a cygwin shell (for Windows), go to your project directory and:

ndk-build

hopefully everything compiles OK, and the NDK reports this:

SharedLibrary : libmodplug.so

Install : libmodplug.so => /cygdrive/c/Users/<yourusername>/workspace/ModPlayer2/libs/armeabi

Or instead of building by hand, you could direct Eclipse (or whatever IDE) to build the native source automatically using this method (thanks Robert!), which is how I do it in the new AndModPlug version.

The example project in ModPlayer2.zip below has a builder like this - just right click the project name in Eclipse, select Builders and then check the box for NativeMod2_Builder. Eclipse should then rebuild libmodplug.so whenever you save changes to anything in the jni/ directory!

9) Now build your apk in Eclipse (or wherever) and enjoy!

NOTES:

I store my mod files in res/raw. Eclipse doesn't mind the .xm extensions but might complain about other tracker format extensions - in that case, just rename them from e.g. "awesometune.mod" to "awesometune".

Good luck,

- crow