Tutorial 12: Using Mod music / sound

In this tutorial you’ll learn about adding music/sounds to the Wii. It’s a fairly simple thing to do and we’ll use Mod files. I assume everyone knows MP3s but you might not know about Mod files which are a little bit like midi files. Mod files in a sense have “samples” which can be used in different ways to produce sounds. You can grab the PDF of this tutorial here: codemii-tutorial-12

There are two ways which you can load music, either from the SD card or from your source. If you aren’t going to allow users to change your music or sounds, I’d recommend loading from your source, it just saves time and it’s nicer not have lots of files on the SD card.

Let’s get started. You’ll need to add –lmodplay to LIBS: in your makefile and also add #include in your main.c file.

So now you have a standard main.c file and your modified makefile like this zip file: tutorial12-makefile.zip. Copy this loop.mod file to your SD card’s root or use ftpii to transfer it across.

Loading mods from the SD card

Before we begin, we need to also add libfat to our libraries in the makefile as below.

LIBS	:=	-lwiiuse -lbte -lfat -logc -lmodplay –lm

We also need to include fat.h in our source code.

As well as the standard initialisation of the SD card:

if (!fatInitDefault()) {
printf("Unable to initialise FAT subsystem, exiting");
exit(0);
}

We have to initialise modplay, so we add the below in our initialise function.

void Initialise() {
. . .
AUDIO_Init(NULL);
MODPlay_Init(&play);
}

Now we can move on to the source code which will load one MOD file from the SD card as the background music.

// Modplay
static MODPlay play;
long mod_size;
char * buffer;
size_t result; 

Above we just assign some globals. Play is the object which we will reference when wanting to play our mod file. mod_size will store the file size of our mod file, buffer will point to where the file is stored in memory and result is sort of just like mod_size except it will check to make sure the whole file is copied successfully to memory.

FILE *f = fopen("/loop.mod", "rb"); // change to “SD:/loop.mod” if using r16

if (f == NULL) {
fclose(f);
}
else {
fseek (f , 0, SEEK_END);
mod_size = ftell (f);
rewind(f); 

So firstly we open the file that we have in our SD card’s root directory. We do the usual check to make sure the file exists and then use ftell to give us the file size of the loop.mod file.

	// allocate memory to contain the whole file:
buffer = (char*) malloc (sizeof(char)*mod_size);
if (buffer == NULL) { perror ("Memory error\n"); }

As you might recall buffer is the pointer to where the file will be stored in memory. We use malloc to assign a block of memory the size of our mod file and do a check to make sure the memory was assigned properly.

	// copy the file into the buffer:
result = fread (buffer,1,mod_size,f);
if (result != mod_size) { perror ("Reading error\n"); }

fclose(f); 

If everything was fine, we copy the entire mod file into memory using fread to store it to the buffer. Result stores the number of bytes read. If result matches mod_size this means that it successfully read the entire file. We can then close the file.

	MODPlay_SetMOD(&play, buffer);
MODPlay_Start(&play);
}

Now the important part, we have our file loaded in buffer and we use MODPlay_SetMOD to make reference to our play global variable that contains which mod file is loaded to it which we set our buffer to. MODPlay_Start is then used to start playing our mod file; again we make reference to the play variable.

while(1) {
. . .
if (pressed & WPAD_BUTTON_HOME) {
MODPlay_Stop(&play);
exit(0);
}
. . .
}

Our mod file will keep on playing in a loop until we specific to stop playing the mod file with MODPlay_Stop(&play) and that’s that. You can view the complete source and try out tutorial12-mod-sdcard.zip

Loading Mods from source

Now we can move onto loading mod files from our source which I find easier.

You need to modify your makefile to add a rule which will convert all your .mod files in a specific folder to a ‘compiled’ state which is usable; it also generates a header file (an include file) which we will use.

Below is what you need to add to your makefile after “# main targets” as below.

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT).dol: $(OUTPUT).elf
$(OUTPUT).elf: $(OFILES)

%.mod.o	:	%.mod
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)

-include $(DEPENDS) 

You now need to specify the folder in which your mods will be stored, so modify or add the below line after “SOURCES :=” and make sure you create the /data subdirectory where your makefile is located.

DATA		:=	data

So now you have our standard main.c file again and your newly modified makefile like this zip file: tutorial12-makefile2.zip. Once extracted, go ahead and compile the project. You’ll see there is a loop.mod file in the /data directory. Once compiled, go to the build folder and you can see loop_mod.o and loop_mod.h, which shows the mod file converted to a ‘compiled’ state and the header file.

Again, we have to initialise modplay, so we add the below in our initialise function.

void Initialise() {
. . .
AUDIO_Init(NULL);
MODPlay_Init(&play);
}

We can now edit our source code as below.

#include "loop_mod.h"

Since we have the header file loop_mod.h, we just need to include that in our source code.

// Modplay
static MODPlay play; 

We add the play variable as a global like last time.

MODPlay_SetMOD(&play, loop_mod);
MODPlay_Start(&play); 

Then simply we can play the file as we did previously, this time having the loop variable when calling SetMOD. We don’t need any more code as this mod file is already in memory.

The next thing you can do is add more .mod files to your /data directory and re-compile. When you wish to change the mod file being played all you need to do is run MODPlay_Stop(&play); and then run MODPlay_SetMOD(&play, different-sound_mod); and MODPlay_Start(&play); as usual. You can view the complete source and try out tutorial12-mod-embedded.zip

And this concludes our tutorial about using Mod files, easy wasn’t it?

Others things you can try out is and make a different sound play every time a button is pressed on the Dpad, playing a mod file and pressing a button to stop and if you combine these tutorials making a sound when a button is pressed.

42 Responses to “Tutorial 12: Using Mod music / sound”

  1. Tutorial Men says:

    Thanks for tutorial, 1 exemple is more than 1000 words

  2. holy_artefact says:

    I assume that I’m missing something if I’ve got references error like these :
    c:/devkitPro/libogc/lib/wii\libmodplay.a(gcmodplay.o): In function `SndBufStop’:
    gcmodplay.c:(.text.SndBufStop+0x24): undefined reference to `ASND_StopVoice’
    c:/devkitPro/libogc/lib/wii\libmodplay.a(gcmodplay.o): In function `SndBufStart’:
    gcmodplay.c:(.text.SndBufStart+0x1a0): undefined reference to `ASND_SetVoice’
    gcmodplay.c:(.text.SndBufStart+0x1bc): undefined reference to `ASND_Pause’
    c:/devkitPro/libogc/lib/wii\libmodplay.a(gcmodplay.o): In function `dmaCallback’:
    gcmodplay.c:(.text.dmaCallback+0xbc): undefined reference to `ASND_AddVoice’
    c:/devkitPro/libogc/lib/wii\libmodplay.a(gcmodplay.o): In function `MODPlay_Init’:
    gcmodplay.c:(.text.MODPlay_Init+0x24): undefined reference to `ASND_Pause’
    gcmodplay.c:(.text.MODPlay_Init+0x2c): undefined reference to `ASND_StopVoice’
    collect2: ld returned 1 exit status

    • teknecal says:

      Can you check you compiling tutorial12-mod-embedded.zip and also make sure you have gcmodplay.h in C:\devkitPro\libogc\include\?

      • holy_artefact says:

        OK. I’ll try later but thanks for the fast reply

        • holy_artefact says:

          Well, I’m trying right now on another computer with the latest devkitPpc/libogc updates, I have the header file you specified and its doing the same error. And yes I’m trying to compile the tutorial12-mod-embedded.zip.
          The problem isn’t because it can’t find the lib, because they are in the same folder as I can see….

          I tried to change the LIBDIRS :=
          line in the makefile with my C:\devkitPro\libogc\include\ folder, but it changed nothing.

  3. Ansfeld says:

    I think there is an sourcecode displaying issue. There are a lot of &amp;amp;amp instead of & in the example.

  4. fishears says:

    can I have the PDF version please?

  5. Vasco says:

    Yes… where is the pdf? Love your tut!

  6. Pvt_Ryan says:

    PDF version will go up this weekend if I get a chance to write it. My Missus is in and out of hospital at the moment in the final few weeks of pregnancy so I don’t have much personal time.

  7. Emil says:

    Try to include -lasnd in your makefile and see if it makes any difference.

    This is how mine looks like:
    LIBS := -lpng -ljpeg -lz -lmodplay -lfat -lwiiuse -lbte -lasnd -logc -lm -lmad

  8. Pvt_Ryan says:

    I’ve sent the PDF versions so they should be available soon. Sorry for the delay.

  9. Blaise says:

    is it possible to play non midi file (like mp3) on the wii remote using devkit. I know its possible since games do it all the time I just wonder how?

  10. Tribasic says:

    Has anyone here had any problems playing their .MOD files? I find quite a few of my .MOD files have scratchy or distorted sound. It’s almost as if some of the sound samples are being read from an incorrect memory bank or something.

    I’ve searched all over the place for an answer, but was only able to find this thread:

    http://www.tehskeen.com/forums/showthread.php?t=4612

    I tried changing the buffersize like the thread suggests, but wasn’t sure what I was suppose to change. Does anyone know how to fix this?

    By the way… These Wii coding tutorials are AMAZING!!! I’m really having fun learning how to program!! THANKS!

  11. Timptation says:

    I’ve got it compiling, but no sound can be heard. Using printf() to give me some debugging options, i know the sound is loading correctly, and the program runs and exits correctly. I also know i hit the play function. Just weird. Anyone else having problems?

  12. Timptation says:

    Ok, disregard my last comment. It seems that the play.buf.loaded boolean is still false after the MODPlay_SetMOD() call. Everything along the way worked though. I don’t know what is wrong internally, or even know how to look into it. Any thoughts? (NOTE, im not doing the .h way)

  13. Tribasic says:

    Hey Timptation,

    I had the same problem. I spent a few days thinking that I was doing something wrong but it seems to be a problem with the latest Libogc library.

    I ended up downloading ‘Libogc 1.7.0’, to get my sound working. I think it’s a bug in Libogc 1.7.1, although I’m just speculating.

    Anyway, just download the file, and when you unzip it, make sure you overwrite the files in ‘C:/Devkitpro/Libogc/’. Don’t delete any of the files in ‘C:/Devkitpro/Libogc/’, just overwrite the files that are already there, and it will work. Here’s a link to Libogc 1.7.0

    http://voxel.dl.sourceforge.net/sourceforge/devkitpro/libogc-1.7.0.tar.bz2

    Good Luck!!

  14. Cyrus Sanii says:

    My code works!
    I have multiple MOD’s playing (in sequence…not at same time) in my game. Now my question is how do I create my own MOD file? Thusfar I have been using posted MOD’s but if I want to sample a sound and make it into a MOD file is there a tool that people recommend and/or is there a way to convert an MP3 or WAV file into a basic play once MOD file?

  15. Tribasic says:

    To make a .MOD file, you need an Audio Tracker program. There are lots of them out there.

    I like using this one:

    ftp://ftp.scenesp.org/pub/skale/skale081.zip

  16. Timptation says:

    Tribasic…. I love you man… Now does anyone know where to get an audio converter that converts TO .mod? Preferably a free one….

  17. Tribasic says:

    Hey Timptation, I’m glad that it worked for you!

  18. Tribasic says:

    I decided to install the latest version of Devkitpro, last night and ran into some problems with playing Audio. Once I got things compiling properly, I just wasn’t getting any audio. I ran into this problem before when I upgraded to Libogc1.7.1, and I know a few people who have been following the tutorials on this website have ran into similar issues.

    I finally figured out how to make things work and I thought I would share the info.

    In my MAKEFILE, I had to make sure that I had ‘-lasnd’ in my LIBS section. The order is important. It wouldn’t work for me unless I put it before ‘-logc’. So your LIBS section should look something like this:

    LIBS := -lwiiuse -lbte -lasnd -logc -lmodplay -lm

    The next thing I needed to do was to include ‘asndlib.h’, into my MAIN.C.

    #include {asndlib.h}

    Make sure you put the ‘greater than’ and ‘less than’, signs on either side of asndlib.h, instead of the brackets that I used. For some reason, the ‘Greater than’, and ‘Less than’ symbols don’t show up when I post the message!!

    And finallly, I replaced the line AUDIO_Init(NULL); with the following:

    ASND_Init(NULL);

    And now I have audio again! I hope this helps people out.

  19. Charlatan says:

    Thanks – that worked, so I can compile now. (I’m rather new to this)

    However, it does sound like the player is playing MODs incorrectly. Arpeggio doesn’t appear to work. It makes chiptunes sound really bad.

    I’m using the latest devkitpro. I have not tried an earlier version of libogc. Any ideas?

  20. Tribasic says:

    Hi Charlatan,

    I have the same problem with my MODs. I’ve been searching for a solution for about a month now. Unfortunately, I haven’t recieved any answers yet.

    I know the Wii should be able to play those MOD files. I had a look at the source code for ‘Dragon Media Player’, because it can play my MOD files perfectly. I noticed in the source code, the guy isn’t using GCMODPLAY, to play the MODs. It looks like he compiled his own MOD playing library from MIKMOD and DUMB source code. I’ve been trying to compile my own library from the DUMB source code, but I haven’t had any success yet. Since I’m new to programming, I’m not sure what the proper way is to compile a library for the Wii.

    Hopefully someone who knows why the MODs aren’t playing will see our messages. This has been bugging me for a while 🙂

    • Charlatan says:

      Hi Tribasic,

      Thanks for your reply. Yeah, I did a bit of searching myself and I only saw posts from you about this. 😉

      What I would love to see is a XM/IT player… maybe someone nice will port MikMod over. 🙂

      • Tribasic says:

        Hey Charlatan. It was nice to actually see some activity in this thread again!

        If I find out anything I’ll let you know!

        Good luck! 🙂

        • Charlatan says:

          Have you ever tried SDL to play modules? I noticed that there is a Wii port, but I’ve never used SDL before.

          • Tribasic says:

            No, I haven’t tried SDL to play modules. I will take a look at it tonight when I get home from work.

            Thanks! I didn’t even know about SDL for the Wii! I hope it works!!

            • Tribasic says:

              Hey Charlaton. I wondered if you had any success with SDL on the Wii. I messed around with it for a while last night but had no luck. However, this morning before work, I managed to actually get a sample audio program to compile for me! Unfortunately, I didn’t have time to test the compiled .DOL on my Wii because I had to leave for work , so I won’t know if it plays audio or not, until I get home tonight and try it out on my Wii. But the good news, is that it actually compiled!! So it might actually work! I’ll keep you posted.

  21. Tribasic says:

    Unfortunately I wasn’t able to get anything to work. I was able to get things to compile, but my SDL programs would always cause my Wii to crash.

    It’s too bad because I really enjoy my ‘chip’ music!!

    • Charlatan says:

      Same here — it would crash everytime I would try to load a mod.

      I wish gcmodplay was improved… the code in this tutorial works beautifully…just doesn’t play stuff correctly. 🙁

      • Tribasic says:

        Yeah, I totally agree. GCMODPLAY needs to be improved.

        I get the feeling that not many people know how to fix the problem because whenever I ask any questions about it I usually recieve 0 replies to my message.

        We need to talk to the guy who created the GCMODPLAY library! I think he’s our only hope!

Leave a Reply