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
|
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 );
...
}
|
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)
|
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
mmFrame();
// Wait for new frame (SWI 5)
VBlankIntrWait();
// ..update graphical data..
}
|
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 );
|
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
mm_sound_effect sound;
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 );
|
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 );
|
To stop an effect that's playing:
// Stop sound effect
mmEffectCancel( mysound );
|
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)
|
Closing
For a better understanding, please have a look at the source code for the GBA examples.