Maxmod
Loading...
Searching...
No Matches
GBA Programming Guide

Here is a guide to step through the basics of installation/usage of Maxmod in a GBA project. This tutorial will assume that you are using the default GBA template (makefile) from devkitPro.

Linking

Firstly, libmm must be added to your library references. Add -lmm to the LIBS in your makefile.

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lmm -lgba

Next, you need to tell the makefile to make a soundbank file for you. What is a soundbank file? It's a file that contains all the samples and modules for your project!

Add a new directory to your project; I'll call it "audio". Add a variable to the directory section of the makefile.

#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
# AUDIO is a list of directories containing sound and music files
#---------------------------------------------------------------------------------
TARGET := $(shell basename $(CURDIR))
BUILD := build
SOURCES := gfx source data
INCLUDES := include build
AUDIO := audio

Next, you need to build a list of the files in the audio directory. Also add the soundbank output file to your binary file list.

CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.bin))) soundbank.bin
# build audio file list, include full path
export AUDIOFILES := $(foreach dir,$(notdir $(wildcard $(AUDIO)/*.*)),$(CURDIR)/$(AUDIO)/$(dir))

Finally, you need a rule to make the soundbank file with the Maxmod Utility. Scroll down to the bottom somewhere and add something like this. You also need a rule to convert the output binary so it can be linked in.

#-------------------------------------------------------------
# rule for converting the output into an object file
#-------------------------------------------------------------
%.bin.o: %.bin
#-------------------------------------------------------------
@$(bin2o)
#-------------------------------------------------------------
# rule for generating soundbank file from audio files
#-------------------------------------------------------------
soundbank.bin: $(AUDIOFILES)
#-------------------------------------------------------------
@mmutil $^ -osoundbank.bin -hsoundbank.h

Now the soundbank file should be generated and linked into the project automatically. Load the audio folder with a few modules (and maybe some WAV files) to test with!

Setup

Now it's time to initialize Maxmod. maxmod.h has the definitions for a GBA project, include it in your source files. Also, include the generated soundbank header too.

#include <maxmod.h> // Maxmod definitions for GBA
#include "soundbank.h" // Soundbank definitions
Global include of Maxmod for GBA.

Maxmod may be initialized now. The GBA library is customizable, so you can configure how many channels or what mixing rate to use, but for this example, we will just use the easy method. mmInitDefault. It's two parameters are the soundbank address, and the number of channels to allocate. It sets up everything for us (including VBlank IRQ [with libgba]) and uses 16KHz mixing rate.

#include <maxmod.h>
#include "soundbank.h"
#include "soundbank_bin.h" // Soundbank binary reference
int main( void ) {
// Initialize maxmod with default settings
// pass soundbank address, and allocate 8 channels.
mmInitDefault( soundbank_bin, 8 );
...
}
void mmInitDefault(mm_addr soundbank, mm_word number_of_channels)
Initialize Maxmod with default settings.

Playing Music

Let's have a look at the soundbank header generated by the Maxmod Utiltiy.

#define MOD_SONG1 0
#define MOD_SONG2 1
#define MOD_CREDITS 2
#define MOD_ANOTHER 3
#define MOD_SECRET 4
#define SFX_BLASTER 179
#define SFX_PHASER 180
#define MSL_NSONGS 5
#define MSL_NSAMPS 181
#define MSL_BANKSIZE 186

Definitions prefixed by MOD_ are module IDs. Definitions prefixed by SFX_ are sample IDs. MSL_NSONGS is the total number of modules in the soundbank, MSL_NSAMPS is the total number of samples, and MSL_BANKSIZE is the total number of modules plus samples (useful for DS projects).

Use mmStart() to play a song.

mmStart( MOD_SONG2, MM_PLAY_LOOP );
// Song is playing now (well... almost)
void mmStart(mm_word id module_ID, mm_pmode mode)
Begins playback of a module.
@ MM_PLAY_LOOP
Loop module forever (until stopped).
Definition mm_types.h:141

Not just yet! The actual song playback (and software mixing) occurs when you call mmFrame(). This must be called every frame (60hz) (in your main loop).

while (1) {
// ..process game logic..
// Update Maxmod
// Wait for new frame (SWI 5)
VBlankIntrWait();
// ..update graphical data..
}
void mmFrame(void) __attribute((long_call))
This is the main routine-function that processes music and updates the sound output.

Sound Effects

The simplest way to play a sound is with mmEffect().

// Play SFX_BLASTER at default pitch with full volume and center panning
mmEffect( SFX_BLASTER );
mm_sfxhand mmEffect(mm_word sample_ID)
Plays a sound effect with default settings.

If you need more control; use mmEffectEx() to specify rate, volume, and panning (and more).

// Play sound at half playback rate, 200/255 volume, and center panning
sound.id = SFX_BLASTER; // sample ID (make sure it is loaded)
sound.rate = 0x400/2; // playback rate, 1024 = original sound
sound.handle = 0; // 0 = allocate new handle
sound.volume = 200; // 200/255 volume level
sound.panning = 128; // centered panning
mmEffectEx( &sound );
mm_sfxhand mmEffectEx(mm_sound_effect *sound)
Plays a sound effect with custom settings.
Information for playing a sound effect.
Definition mm_types.h:206
mm_byte panning
Panning level. Ranges from 0 (far-left) to 255 (far-right).
Definition mm_types.h:228
mm_byte volume
Volume level. Ranges from 0 (silent) to 255 (normal).
Definition mm_types.h:225
mm_word id
ID of sample to be played. Values are defined in the soundbank header.
Definition mm_types.h:210
mm_hword rate
Playback rate. 6.10 fixed point number. (1024 = original sound)
Definition mm_types.h:218
mm_sfxhand handle
Handle of previous sound effect. If a valid handle is given, it will be recycled.
Definition mm_types.h:222

mmEffect() and mmEffectEx() both return an mm_sfxhand type. This can be used to modify the sound effect while it's playing.

mysound = mmEffect( SFX_BLASTER );
// Change pitch to +1 octave
mmEffectRate( mysound, 1024*2 );
// Change volume to half level (128/255)
mmEffectVolume( mysound, 128 );
// Change panning to far-right
mmEffectPanning( mysound, 255 );
void mmEffectRate(mm_sfxhand handle, mm_word rate)
Changes the playback rate for a sound effect.
void mmEffectVolume(mm_sfxhand handle, mm_word volume)
Changes the volume of a sound effect.
void mmEffectPanning(mm_sfxhand handle, mm_byte panning)
Changes the panning of a sound effect.

To stop an effect that's playing:

// Stop sound effect
mmEffectCancel( mysound );
mm_word mmEffectCancel(mm_sfxhand handle)
Stops a sound effect. The handle will be invalidated.

Sometimes the effect you just played isn't so important. You can mark it as a background effect with mmEffectRelease().

mmEffectRelease( mysound );
// Now the sound is allowed to be interrupted by other effects/music (if the need arises)
void mmEffectRelease(mm_sfxhand handle)
Marks a sound effect as unimportant.

Closing

For a better understanding, please have a look at the source code for the GBA examples.