Module Music on iPhone/iPad with ChibiXM
Module music was once a staple in video game development but has since been mostly replaced by streamed audio formats like MP3 and OGG. The reason is straightforward – streamed audio is production environment agnostic whereas module music requires specific production tools and constraints. However, one of the interesting things about creating games for limited profiles like iOS devices is that many game development practises in use ten to fifteen years ago become relevant again. There are some big advantages to using mod music for an iOS game.
In a module file each instrument is stored as a single sample while the music is stored as sequenced data. You can think of it as a piano roll, where each notch plays back one of the samples at a specified frequency. Mod’s have many advantages over MP3 audio for games on iOS:
- File size does not scale directly with the play time of the music. Each instrument in the song is stored once as a sample and that data can be reused over and over as the note sequence is processed.
- Seamless looping and loop points. Many songs benefit from a loop back to just after the intro or infinitely looping an ominous ending phrase.
- More control over playback. If the timer is low, you can increase the speed of playback without affecting pitch to create an organic frenzied feeling. If Mario gets on a Yoshi you can dynamically mute/un-mute an extra drum channel.
- Fine grained optimisation. With an MP3 you have to deal with the quality of the entire audio clip as a whole when adjusting for quality. With a module file you can decrease or increase the fidelity of specific samples to get the best quality for your memory and size constraints.
Unfortunately, many existing and popular solutions for playback on iOS come with licensing fees, but there are alternatives that will do the job. Chibi XMPlay, a lightweight module playback library created by Juan Linietsky and myself, is one of them.
It’s used for playing a type of module file known as XM (eXtended Module) on limited platforms like the iOS or Nintendo DS. Best of all it’s completely open source, licensed under new BSD, and free to use for both commercial and non-commercial applications.
Using ChibiXM Play
Chibi XMPlay was written with portability in mind. As a client it’s your responsibility to populate memory, file i/o, and mixer function tables for the OS you’re using. Lucky for you, I’ve done this work already for Trudy’s Mechanicals. I’ve also added functionality to the wrapper to play sound effects which is possibly useful as a low latency alternative to Apple’s numerous methods. To use ChibiXM do the following:
- Make sure you have the “AudioToolbox” framework imported
- Download the ChibiXM source w/Objective C wrapper and include it
- The following code will play an XM file (provided ‘song.xm’ is part of your project):
[[ChibiXM sharedInstance] play:song]; // Starts playback and retains the XMFile
player.song = nil; // Releases the XMFile
XMSample* sample = [[XMSample alloc] initWithName:@"cacodemon.wav"];
[[ChibiXM sharedInstance] playSample:sample onChannel:0 withVolume:1.0 andPanning:0.0 andPitch:1.0];
If you just want to see ChibiXM in action here’s a complete XCode project you can compile and deploy that shows some graphics and let’s you switch between some songs with a touch. Note that the project was created in XCode version 3.13 of the SDK. To compile under the latest just go to Project Info and change Base SDK to 4.x
Where To Go From Here?
The wrapper is a simple way to play module music and sound effects, but I encourage you to look further into ChibiXM’s capabilities. It has functionality to share a pack of samples among many songs and other goodies that allow easy programmability and control over music playback and mixing. It’s also pretty easy to extend if you wish to add DSP effects to playback.
Here are some links to help you explore this approach to putting music into your game:
Chibi XmPlay – Berlios project page for Chibi XmPlay
Milky Tracker – Multi-platform tracking software that can create XM modules
ModArchive – Massive repository of tracked music
IndieGameMusic.com – Website designed to connect game developers to game musicians
Follow me on twitter! @infey
** UPDATE **
Dave Rempel points out that you may run into an issue if you load many songs into memory at once using xm_song_alloc() as the ChibiXM built-in software mixer (which the iOS code uses) has a statically sized pool of memory for storing samples for all songs currently loaded. The easiest way to avoid running into the issue is to only load the songs into memory you absolutely need for playback. However, if you wish to change the size of this buffer based on the requirements of your app you can modify the size of this buffer in xmplay.c, line 113:
#define _XM_SW_MAX_SAMPLES 256