Welcome! Log In Create A New Profile

Advanced

Playing sound files

Posted by diego_pmc 
Playing sound files
September 29, 2009 03:16PM
Can anyone please tell me if there is any way I could play sound files other than MOD in my Wii Homebrew application? I have some MP3 files that I want to put in my application.

Below I have included the code that allows me to play MOD files, but is there any way to play any other kind of files (especially MP3)? (Code snipped from CodeMii.)
	FILE *f = fopen("/loop.mod", "rb");
	
	if (f == NULL) {
		fclose(f);
	} else {
		fseek (f , 0, SEEK_END);
		mod_size = ftell (f);
		rewind(f);
		
		// allocate memory to contain the whole file:
		buffer = (char*) malloc (sizeof(char)*mod_size);
		if (buffer == NULL) { perror ("Memory error\n"); }
		
		// copy the file into the buffer:
		result = fread (buffer,1,mod_size,f);
		if (result != mod_size) { perror ("Reading error\n"); }
		
		fclose(f);
		
		MODPlay_SetMOD(&play, buffer);
		MODPlay_Start(&play);
	}
Re: Playing sound files
September 29, 2009 04:19PM
There are a lot post about this topic, here is the one that helped me: [forum.wiibrew.org]
Re: Playing sound files
September 29, 2009 11:15PM
[arikadosblog.blogspot.com]

Only method I know of that works to play MP3s smoothly and without crashing.
Re: Playing sound files
October 01, 2009 05:19AM
Arikado, (or anyone with the mp3 skillz!) I followed your blog to try to add mp3 from sd support in my app. did the following:

FILE *BGM = 0;
long lSize;
char * mbuffer;
size_t mresult;
bool mp3isready = false;

up at the top.

down in the body of my code put this in under my "when A is pressed"

					BGM = fopen("test.mp3", "rb");
					fseek (BGM , 0 , SEEK_END);
					lSize = ftell (BGM);
					rewind (BGM);
	
					mbuffer = (char*) malloc (sizeof(char)*lSize);
					mresult = fread (mbuffer,1,lSize,BGM);
	
					fclose(BGM);
					MP3Player_PlayBuffer(mbuffer, lSize, NULL);

You'll note i had to rename to mbuffer and mresult just because I was already using buffer and result.

IOn my sd card in the folder with boot.dol is test.mp3

I tried the loopthemp3 function method as well but since i'm just trying to get it to play once, i commented all that out so i could just test it playing once. Obviously because of that, the mp3isready part isn't needed so we'll ignore that.

Anyway, start up app, press A and get the nice stack dump. Anything you notice off the bat that is my prob?

This is my first attempt at loading something off of the SD card so totally new to fopen fseek fread etc.

Compiles with no problems, just crashes when i press A

The ASND_Init(); and MP3Player_Init(); are also in there and that all happens before the A code is run... and that part is working because all my other music and snd fx still work.



Edited 2 time(s). Last edit at 10/03/2009 04:47AM by mdbrim.
Re: Playing sound files
October 03, 2009 04:47AM
no love huh?

oh well.
Re: Playing sound files
October 03, 2009 07:36AM
can you paste bin the the code and I'll take a look.
Re: Playing sound files
October 03, 2009 06:36PM
Quote
mdbrim
no love huh?

oh well.
I need to see the full source.
Re: Playing sound files
October 04, 2009 04:50AM
full source is 4308 lines long... but i can paste the related items.


#include asndlib.h
#include mp3player.h

FILE *BGM = 0;
long lSize;
char * mbuffer;
size_t mresult;

int main() {

ASND_Init();
MP3Player_Init();
while(1){
    Scanpads
    WHEN A IS PRESSED {
        BGM = fopen("test.mp3", "rb");
        fseek (BGM , 0 , SEEK_END);
        lSize = ftell (BGM);
        rewind (BGM);
        mbuffer = (char*) malloc (sizeof(char)*lSize);
        mresult = fread (mbuffer,1,lSize,BGM);
        fclose(BGM);
        MP3Player_PlayBuffer(mbuffer, lSize, NULL);
    }
}
}
No compile errors, just dump when i press A
I'm thinking i don't have the "read from sd card" commands set up correctly.



Edited 3 time(s). Last edit at 10/04/2009 04:55AM by mdbrim.
Re: Playing sound files
October 04, 2009 05:45AM
You need fatInitDefault(); before you do anything with files.



Edited 1 time(s). Last edit at 10/04/2009 05:45AM by scanff.
Re: Playing sound files
October 04, 2009 03:06PM
Did you link in and include libfat and call fatInitDefault()?

Edit: scanff beat me to it :-P

Edit 2: Also, if you only have one sound file, the only function you need to call is MP3Player_PlayBuffer() when A is pressed. All of the other work could be done outside of the A button press (your code would be much more efficient that way).

Also, add this into your code:
if(WPAD_ButtonsDown(WPAD_CHAN_0)&WPAD_BUTTON_B){
if(MP3Player_IsPlaying())
MP3Player_Stop();
}



Edited 2 time(s). Last edit at 10/04/2009 03:12PM by Arikado.
Re: Playing sound files
October 04, 2009 03:23PM
AWESOME!

it was the fatinitdefault(); line.

works like a charm now

I also moved all the stuff except the play buffer line out of the "press A" code like you suggested... got rid of the 2 second frozen cursor i got while it was loading in the buffer...

thanks guys!



Edited 3 time(s). Last edit at 10/04/2009 03:37PM by mdbrim.
Re: Playing sound files
October 04, 2009 03:34PM
I'm not sure about the mb/second rate, but if you look at that Wii Shooting Gallery Beta I posted, you can probably do a little bit of guesstimation. None of the songs cause the game to hang longer than about 5 seconds, none of them reach the 4mb mark though IIRC.

Actually, the song being started before it is fully loaded was a weird problem I encountered (especially if you put a function that loops the music on a thread). When it occurs, everything is fine except that the sound simply doesn't play (note that I haven't had this happen since updating to devkitPROr17, so the results may be different for that build).

I love questions :-)
Re: Playing sound files
October 04, 2009 03:44PM
oops, i edited out my questions because i asked them before i tested :D

Yeah, i think your guesstimations are pretty close. My 3MB sound file took about 3 seconds to load (based on how long my cursor was frozen). Then i removed the load portions from my press A code and like you mentioned and it does all that in the background while i'm navigating to the audio menu :D

yeah i was worried about starting it before the song finished loading all the way, but I'll just be sure to load it before it needs it type deal.

thanks again man, external mp3 playing was the last piece of my "playing audio" puzzle!



Edited 1 time(s). Last edit at 10/04/2009 03:51PM by mdbrim.
Re: Playing sound files
October 04, 2009 03:51PM
Yeah, no problem :-)

Does your "playing audio puzzle" include sound effects? If so, do they work properly with the background audio?
Re: Playing sound files
October 04, 2009 03:53PM
Quote

Does your "playing audio puzzle" include sound effects? If so, do they work properly with the background audio?

yes it does and yes they do!

even have multiple sound effects playing at the same time with the looping audio... (GetFirstUnusedVoice is my friend!!)
Re: Playing sound files
October 04, 2009 04:05PM
I will have to take a look at your source as soon as it is released then! My "audio puzzle" is missing the sound effects piece...
Re: Playing sound files
October 04, 2009 04:45PM
so you don't have to wait for my source, here's what i did:

i wanted the ability to play the same sound effect but be able to pick at which frequency it played at based on game play.
Example: when you lay a poker chip down it made a standard chip down sound... but when you laid a STACK of chips down, it played the same sound effect but with a deeper tone (lower frequency) so you got multiple sounds but only used one pcm file.

So i made my own function:

void playsfx(int freq, void *pcm, s32 pcmsize) {
	ASND_SetVoice(SND_GetFirstUnusedVoice(), 3, freq, 0, pcm, pcmsize, soundvol, soundvol, NULL);
}

The GetFirstUnusedVoice part was the key to having multiple sounds playing at once, it would just find the first open "audio slot" and assign the sound to that and play it... thus not disturbing any other sound being played.

The 3 just corresponds to 16bit stereo:
a 0 = 8bit mono
a 1 = 16bit mono
a 2 = 8bit stereo

so you'll want your pcm files to be in that format (or match up with whatever format you pick)

the freq part is passed into the function (which freq you want)
the 0 is how much of a delay
the pcm is passed into the function (which sound to play)
the pcmsize is passed into the function (size of sound)
the soundvol is defined by the user in my settings section and is just the volume (it's done twice, first is left speaker, second is right speaker)
the NULL has something to do with the CALLBACK... not sure what it is for, i just left it NULL!

so then whenever i want to play a sound effect i just do this:

playsfx(44100, (char *) click_pcm, click_pcm_size);

that's it, it'll play my click_pcm sound effect at a freq of 44100

the click_pcm is included at the top with the rest of my sound effects.

#include "click_pcm.h"

you'll need the #include asndlilb.h and the -lasnd in your makefile of course.

then all i do is put my click.pcm file that i created and let my makefile use bin2o to convert it into a .h

the only other key is to actually put your sound effect (the click.pcm) into the right format.

I've been using Goldwave to save them as raw file type and then "PCM signed 16 bit, big endian, stereo" (when you click save as and change the file type to raw, you'll find that big endian stuff in the attributes menu). That format lines up nicely with "3" and seems to be the popular choice based on all of my searches back when i was learning.

Hope that helps. Let me know if you get it to work / if that's what you need. I'll be happy to fine tune, go into more detail on what i did.



Edited 5 time(s). Last edit at 10/04/2009 05:01PM by mdbrim.
Re: Playing sound files
October 05, 2009 10:10PM
excellent thread - just about to start some adding some audio code and this will be extremely useful for both the MP3 and the sound effects bit!

Thanks - much appreciated!
Re: Playing sound files
October 07, 2009 04:05AM
no problem man, hope it helps... when you start trying it out, let me / us know if you have any problems.

You can obviously create your own custom sound function (or not use one at all and just call each effect individually with separate ASND_SetVoice functions)

I just found it easier to have one ASND_SetVoice part and send varying freqs and sound files to it.
Re: Playing sound files
October 10, 2009 04:45PM
Thanks for the help, and sorry I didn't reply sooner. I partly got the game to play an MP3 music file when it opens, but there is a problem. When I start the game, the music plays okay for a little while, and then it starts making one of those weird sounds when the game is blocked on a single note and keeps repeating it over and over. This happens seemingly at random points in game; it could start 2 seconds after I open the game, or it could start after 20 or so seconds.

I posted the code below; also, here's the Homebrew directory for my application, if you want to check the error yourself. (When the error occurs, take the SD card out of the console, and press a button on the Wii Remote so that the Error() function would be called and the application would exit safely, so you don't have to unplug your Wii.)


#include mp3player.h // lmad in MakeFile
#include asndlib.h // lasnd in MakeFile

int main()
{
    PlayMP3("data/music/RPB-WoPiMedley.mp3");
}

void PlayMP3(const std::string filename) {
    /* Sources:
      1. [arikadosblog.blogspot.com]
      2. [www.pastie.org]
     */
    ASND_Init();
    MP3Player_Init();
    FILE* f = OpenFile(filename, "rb");
    long size = FileSize(f);
	
    // allocate memory to contain the whole file:
    char* buffer;
    buffer = (char*) malloc (sizeof(char)*size);
    if (buffer == NULL) Error("cannot allocate memory for file '" + filename + "'");
	
    // copy the file into the buffer:
    long result = fread (buffer, 1, size, f);
    if (result != size) Error ("cannot store file '" + filename + "' in memory");
    fclose(f); // file is stored so we can close it now
	
    // play the buffer
    MP3Player_PlayBuffer(buffer, size, NULL);
}

FILE* OpenFile(const std::string filename, std::string fam) 
{
    FILE* file = NULL;
    if(!fatInitDefault()) Error("cannot initialize FAT system");
    file = fopen(filename.c_str(), fam.c_str()); // fam = file access mode
    if (file == NULL) Error("cannot open file '" + filename + "'");
    return file;
}

long FileSize(FILE* f) {
    /* Sources:
       1. [arikadosblog.blogspot.com]
       2. [www.pastie.org]
     */
    long size;
    fseek (f, 0, SEEK_END);
    size = ftell(f);
    rewind(f);
    return size;
}

void Error(const std::string message) {
    printf("\x1b[2J"); // clear the screen
    printf("\nError: "); printf("%s", message.c_str());
    WaitWiiButton(); // wait for any button to be pressed on the wiimote
    exit(1);
}



Edited 3 time(s). Last edit at 10/11/2009 08:37AM by diego_pmc.
Sorry, only registered users may post in this forum.

Click here to login