gdxmodplug experimental library

An experimental version of AndModPlug for libgdx - GdxModPlug??

BASIC INFO

This is an example of using my tracker music player code with libgdx.

AndModPlug is a package intended to interface Android Java games/apps with the MOD/XM "tracker" music player libmodplug. This modified version here expands on that to add support for libgdx's desktop projects on Windows, Linux, and Mac computers.

libmodplug itself was originally created by Olivier Lapicque and now maintained by a team of tracker music enthusiast coders.

libmodplug is public domain. My Java & JNI code to interface with it is not public domain, however. But don't worry, you can do whatever you want with it, modify it, use it in paid apps or games, anything really.

I just ask that you give me a mention in your app/game's credits or on your website or a similar place.

The Java & JNI code consists of only three files: PlayerThread.java, MODResourcePlayer.java and jni_stubs.cpp. Log.java is also included, but is just a simple class to mimic Android's Log output using standard Java System.out calls

Note that the name AndModPlug comes from a combination of Android & libmodplug. However with this experimental code created to work with libgdx, perhaps I should name it GdxModPlug or something, which is what I've tentatively done below.

See below to find zip archives of the ModPlug-for-libgdx javadocs and a simple example libgdx project 'dropmodplug'.

How to use AndModPlug with libgdx

AndModPlug for use with libgdx currently consists of a jar file with the Java classes and a few native libraries (compiled C++ code) for each platform:

Android: libmodplug.so

Note that the armeabi, armeabi-v7a, and x86 versions of the library have the same name, but are unique builds of the library.

Windows: libmodplug.dll, libmodplug64.dll

Linux: libmodplug.so, libmodplug64.so

OSX: libmodplug.jnilib, libmodplug64.jnilib

These haven't been tested since I don't have a Mac. Hopefully, they work since libmodplug is fairly portable across platforms.

iOS??: I'm not an expert in library formats, but since iOS devices are ARM-based, perhaps the same Android native libraries will work on iOS. Especially since they don't use any platform specific APIs. It's worth a try at least. Try them with the standard 'libmodplug.so' names and/or rename them to 'libmodplug.jnilib' (since OSX uses the .jnilib extension, so maybe iOS would, too?)

The above desktop libraries with 64 in the name are the 64bit complements to the 32bit libraries. The Java classes MODResourcePlayer & PlayerThread automatically load the correct library by detecting the system they are running on at startup time.

How to use this example project

First, use the new gdx-setup.jar tool to make a project called dropmodplug.

Fill in the fields like this:

Name: dropmodplug

Package: com.example.dropmodplug

Game class: DropModplug

Destination: [anywhere you like] since we'll import it into Eclipse, etc. afterwards.

Android SDK: [point to where your Android SDK is installed] or uncheck the Android Sub Project box to just play around with a desktop build.

Sub Projects: check Desktop, and Android (my modplug code currently only supports those two)

Extensions: uncheck all the boxes since we don't need any of them for this simple example game.

Click the "Advanced" button and check Eclipse so that it makes an Eclipse compatible project. The other IDEs will likely also work, but may take some tinkering.

Then click "Generate" button and wait a bit.

Importing into Eclipse

NOTE: with this example project below, you likely cannot simply import it into Eclipse until I figure out how to deliver it cleanly integrated with Gradle. For now, make a new project as described above, import THAT project and modify it with the JAR, native libraries and classes from the example project downloadable below.

Click File->Import then select General and Existing Projects into Workspace and the Next button.

For "Select Root Directory" click the Browse button and navigate to the directory you selected above (the Destination line in the

gdx-setup.jar tool)

Then make sure all three sub-projects show up and are checked (dropmodplug-android, dropmodplug-core and dropmodplug-desktop) and check the "Copy projects into workspace" box and then click Finish.

After downloading and uncompressing the example project archive, you can use your OS UI to copy the src, libs, assets, etc. folders from the example project and then paste them over top the project in your workspace to merge the extra stuff included here, e.g. the actual DropModplug class in dropmodplug-core, the compiled libraries (.so, .dll, etc.) in dropmodplug-desktop/libs, etc.

Then Refresh the projects and subdirectories, and Clean the projects.

You'll also need to add the gdxmodplug JAR library to the dropmodplug-core and dropmodplug-android by right-clicking them, selecting Properties, Java Build Path, the Libraries tab and Add JAR, navigate to dropmodplug-core/libs and select gdxmodplug-0.1.1.jar. Then in the Order and Export tab, check the box to export gdxmodplug-0.1.1.jar. Do this for both dropmodplug-core and dropmodplug-android and note that for dropmodplug-android, you'll actually be pointing to the jar in dropmodplug-core/libs

Finally, you'll want to make a run configuration to run the desktop project (refer to the images below). Click the Run Configurations menu (in Eclipse, the drop-down menu from the triangle next to the Green-Circle-Play-Button looking icon). Select Run Configurations, Java Application, then click the new button (the page with a +), give it a name like run_dropmodplug-desktop, in the Main Class text box type main and then click the Search button and select "DesktopLauncher - com.example.dropmodplug.desktop" and Apply the changes.

Then click the Arguments tab and put:

-Djava.library.path=${workspace_loc:dropmodplug-core/libs}

in the VM arguments area.

For Working Directory, select Other, click the Workspace button, and navigate to dropmodplug-android/assets. Apply this and Run it.

After doing this, from now on you can just click the dropmodplug-desktop project and hit Ctrl-F11 to run the desktop project game.

See the run_conf_main.png and run_conf_args.png images for a picture of how to setup the run configuration described above.

If you find the code useful in your projects and would like to say thanks you can donate a few dollars.

Buy one of my games!

Or donate with Paypal!

Example Project

More Info

If you just download the gdxmodplug-0.1.1.zip instead of the example project (dropmodplug), read on for a bit of explanation about where things go so you can add the JAR and libraries to your own project.

libgdx games generally have a base project (now called 'core') and then additional projects for each platform. The example code in this archive has a modified version of the well-known "Drop" example game, where you catch raindrops in a bucket.

I've modified the game, however, by removing the background sound and replacing it with an xm tracker song (from my Android game, Microchip Monsters) to demonstrate using AndModPlug in a libgdx game.

So where to put the libraries?

I'm a libgdx newbie, but here's what I've found works:

  • put the Android armeabi, armeabi-v7a and x86 libraries in the android project's libs/ folder, e.g. dropmodplug-android/libs for this example game. Simply copy armeabi/libmodplug.so to your own game's Android project libs/armeabi/ directory, as well as the respective armeabi-v7a & x86 builds of libmodplug.so.

  • put the desktop libraries in the desktop sub project's libs/ folder. There's likely a better way to do this without having to set the java.library.path to point to them (described above) but for now, this will work OK.

  • put gdxmodplug.jar in the core project's libs/ directory and add it to the build path for the core project (for example in Eclipse, right-click the 'dropmodplug' project, then select Properties, Java Build Path, then the Libraries tab and the Add JARs button, navigate to your base project's libs/ folder, select gdxmodplug.jar and add it. Also be sure to click the Order and Export tab and check the box for gdxmodplug.jar there as well. Note that it currently seems you have to do the same for the android sub project in order for the Modplug Java classes to be included in the APK.

That's pretty much it!

Eclipse can be finicky - you may have to Clean the projects or refresh them with F5 to have all changes picked up.

Some limitations

AndModPlug is meant for single use in an app or game, so you currently

cannot use more than one instance to play two or more MOD songs at

once. I hope to remove this limitation in the future.

Also a WARNING ABOUT LINUX MACHINES and libgdx's AudioDevice (which AndModPlug uses). I fought for a couple of days trying to figure out

why the songs played badly when I booted my PC in Ubuntu Linux and tried dropmodplug.

Eventually I found this libgdx issue:

https://github.com/libgdx/libgdx/issues/2252

that details the fact that OpenAL on Linux is non-optimal, so you effectively can't use CD quality playback rates (44100KHz) under Linux (or perhaps it depends on the machine's specs?). At any rate, it doesn't run well on my old notebook computer running Ubuntu, so in the example project, in dropmodplug-core's DropModplug class, you'll see comments about how I have to lower the rate for Linux. There's code in place to detect Linux and lower the rate from 44100Hz (which is fine for Android/Windows) to 16000Hz for Linux...

UPDATE:

A fellow modplug enthusiast did some research and got in touch with this very useful info:

"I ... found out that you can change the LwjglApplicationConfiguration config -file's audio parameters in DesktopLauncher.java. By adding these parameter changes

config.audioDeviceBufferSize = 2048; config.audioDeviceBufferCount = 6;

before launching your core application, the issue seems to be gone! [One] can play music just fine with low CPU usage and 44100 playback rate."

Which seems like a fantastic solution to the linux problem!

Future work

AndModPlug works pretty well. I've used it in three Android games so far and a few other apps.

This "gdxmodplug" port is experimental, but should actually work pretty well also. The compiled library in particular is pretty solid.

I DID see that in the Android app for this example 'DropModplug' game, the Android system complained about text blocks or something in the library. I'll look into this in the future.

Docs

Currently, there's only this example game as a reference on how to use AndModPlug (gdxmodplug).

However, you can find the Java Docs below for the classes. Check them out for info about other methods available in the PlayerThread class and the MODResourcePlayer class which extends it.

Finally

Anyway, hopefully this code is useful to people!

Below are three zip archives:

(Click the down blue arrow at the far rightto download an archive.)

  • an example libgdx game project 'dropmodplug' in the archive dropmodplug_project.zip

  • an archive with only the JAR and native compiled libmodplug libraries gdxmodplug-0.1.1.zip

  • java docs for the AndModPlug library modified to work with libgdx in the archive gdxmodplug_javadocs.zip

UPDATE:

I added a fourth archive today (June 19, 2017) with all of the libraries for each architecture currently supported for Android with the Android NDK (Native Development Kit). Please see

"GdxModPlug_Android_libs_all_archs_061917.zip"

below.

This archive of libraries hopefully also fixes a problem

where they would fail on android SDK 20 devices or lower

due to srand (random) functions not being linked properly.

i.e. this set of libraries was compiled with the

Android NDK APP_PLATFORM setting set to android-19

(which should hopefully be backward compatible with

most older Android versions).

So these are:

  • arm64-v8a

  • armeabi

  • armeabi-v7a

  • mips

  • mips64

  • x86

  • x86_64

Note that the current GdxModPlug Java code expects to load the libraries via the name [lib]modplug_ARMlinux[.so] (where the stuff in brackets is filled in automatically by the OS when loading a library), so all the libraries have the "_ARMlinux" name.

Which is silly... Since they all aren't ARM processor architectures. But for now, it should do. One could tweak the PlayerThread.java code to load libraries named "modplug_AndroidLinux" perhaps. I'll leave that for later.

Also, I haven't tested these -- just putting them up for people to use if they need the other architectures.

The original libraries are still in the dropmodplug_project.zip archive, with the builds for armeabi and armeabi-v7a (the most common Android architectures, I believe -- although the Chromebooks ability to use Android apps lately may change that).

Have fun!