DS
DS Programming Guide

Back to Index

Here is a guide to step through the basics of installation/usage in a DS project. This tutorial will assume that you are using the default ARM7 program from devkitPro along with the default ARM9 template.

Linking

This is probably the hardest part of this tutorial (but it's still very simple).

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

#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS    := -lmm9 -lnds9

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 -d

Don't forget the -d flag! This flag makes the soundbank file suitable for a DS project. Now the soundbank file should be generated and linked into the project automatically. Load the audio folder with a few modules to test with!

By the way, this section assumes you want to load the entire soundbank into memory. If you want to use the filesystem instead, do not tell the makefile to link the soundbank in, just generate the soundbank file only.

Setup

Now it's time to initialize Maxmod. maxmod9.h has the definitions for the ARM9 side, include it in your source files. Also, include the generated soundbank header too.

#include <maxmod9.h>    // Maxmod definitions for ARM9
#include "soundbank.h"  // Soundbank definitions

There are multiple ways of setting up Maxmod to fit your needs. The easiest way is to use the mmInitDefault(Mem) functions. mmInitDefault is for when your soundbank is in the filesystem, mmInitDefaultMem is for when your soundbank is loaded into memory (as described above).

void main( void )
{
    // Use this if you have the soundbank loaded into memory
    mmInitDefaultMem( (mm_addr)soundbank_bin );
    
    // OR, use this if you have it in the filesystem
    //mmInitDefault( "soundbank.bin" );
}

Playing Music

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

#define SFX_BLASTER     0
#define SFX_PHASER      1
#define SFX_BONK        2
#define MOD_TITLE       0
#define MOD_INGAME      1
#define MOD_CREDITS     2
#define MOD_ONEMORESONG 3
#define MSL_NSONGS      4
#define MSL_NSAMPS      156
#define MSL_BANKSIZE    160

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 alternate setup process).

Before playing a song, the song must be loaded into memory. Use mmLoad to load songs into memory (or acknowledge their existence in memory).

mmLoad( MOD_TITLE );

Now that MOD_TITLE is loaded. You may begin playing it with mmStart.

mmStart( MOD_TITLE, MM_PLAY_LOOP );

There are two modes for playback: MM_PLAY_ONCE and MM_PLAY_LOOP. If MM_PLAY_ONCE is used, then the module will stop playing after it finishes the last pattern. If MM_PLAY_LOOP is used, then the module will start playing again from its restart position if it reaches the end.

When you are finished with a module, unload it from memory with mmUnload.

mmUnload( MOD_TITLE );

Sound Effects

To load a sound effect into memory, use mmLoadEffect.

mmLoadEffect( SFX_BLASTER );

Now it can be played with mmEffect.

// Play a sound at its default frequency
mmEffect( SFX_BLASTER );

mmEffectEx is a more flexible version of mmEffect. It will let you specify all of the attributes for the sound.

// 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 );

Both mmEffect and mmEffectEx return a sound effect handle that can be used later to modify the sound.

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 );

If the effect isn't so important, you can mark it for interruption. This means it can be overridden by music and other effects (if there are no other channels available).

// Allow effect to be interrupted
mmEffectRelease( mysound );

You can stop a sound effect like this:

// Stop sound effect
mmEffectCancel( mysound );

When you are done using a sound effect, you can unload it from memory with mmUnloadEffect.

// Unload sound from memory
mmUnloadEffect( SFX_BLASTER );

Closing

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