Libogc's MP3Player is nice in that it allows the programmer to play MP3 files loaded externally from the SD Card, or loaded internally from the RAM as a buffer. While I've always had surefire success with the latter method, the former has been hit or miss. When I have gotten it to work, I've always been unable to get the .mp3s to play on a loop. Any calls relating to the FILE holding the .mp3's freezes the Wii forcing me to physically get up from my chair and unplug the Wii. To that end, it's quite a conundrum to have such a wonderful MP3Player_PlayBuffer() function and such an unstable MP3Player_PlayFile() function.
However, to this day, I still haven't given up trying to play externally loaded MP3 files with libogc's MP3 Player. And today, I'm pleased to post on my blog that I've finally found a very stable, working, solution. The solution is, to put it plainly, to load an external MP3 file, turn it into a buffer, and then play the buffer with the MP3 Player. The rest of this post will detail the exact the code I used to get this to work.
First, in your makefile, under LIBS:, include the libasnd.a libmad.a libraries:
-lasnd -lmad
Now, wherever necessary, include asnd and the libogc MP3Player:
#include (asndlib.h)
#include
And of course, initialize asnd and the libogc MP3Player before you do anything with them:
ASND_Init();
MP3Player_Init();
Let's declare all of the variables we're going to use:
FILE *BGM = 0;//This will store an MP3 on the SD Card
long lSize;//This will store the size of the FILE BGM
char * buffer;//This is our buffer that will take the place of the external MP3
size_t result;//This is the size of the buffer
bool mp3isready = false;//This keeps the music from trying to loop before the buffer is made
And now prototype a simple function that will keep the MP3 looping:
void LoopTheMP3();
Now let's load an MP3 file:
mp3isready = false;//Keeps LoopTheMP3() from working before the buffer is ready
BGM = fopen("sd:/MUSIC/bgm.mp3", "rb");
Let's obtain the size of said file:
fseek (BGM , 0 , SEEK_END);
lSize = ftell (BGM);
rewind (BGM);//Return to the beginning of the MP3 for good measure
Create the Buffer:
buffer = (char*) malloc (sizeof(char)*lSize);//Allocate memory to contain the whole file
result = fread (buffer,1,lSize,BGM);//Copy the file into the buffer
Play the Buffer:
fclose(BGM);//Since we no longer need BGM, get rid of it
MP3Player_PlayBuffer(buffer, lSize, NULL);//Play the buffer
mp3isready = true;//Let LoopTheMP3() know it can start working
If you're going to change songs, be sure to clear the buffer beforehand:
free(buffer);
Lastly, heres the code for our function to keep the MP3 Playing continuously:
void LoopTheMP3(){
if(mp3isready && !MP3Player_IsPlaying())
MP3Player_PlayBuffer(buffer, lSize, NULL);
}
As is the nature of programming, this code will probably need to be adapted and changed a bit to suit the flow of your program. However, I assure you that it does work and is the most stable way I've encountered yet to play externally loaded MP3 files. I have pastied the exact code I am using in Wii Shooting Gallery here to show you an example of that. I have another app (with source of course) made just to demonstrate the functionality here.
Special thanks go out to scanff who, without his support, I would've given up on libogc's MP3Player before ever even trying a buffer (that means there would've been no sound in WiiBreaker without his help :-O). Thanks to him, I've managed to continually expand my knowledge and bring you the solution I found; detailed in this post.
Excellent post - Thanks.
ReplyDeletehi
ReplyDeleteI do not have much knowledge before reading this article about it but after reading the whole article I got very nice information from it.
ReplyDeletemp3 player
Hey and thanks for this helpful article!
ReplyDeleteHow would I go about pausing an MP3?
My idea was to stop it and then use PlayBuffer to continue playing from the point where it stopped - but how would I determine that point?
Hi Arikado,
ReplyDeleteThanks for this informative article.
I tried using your code but when I run it on the console I get a code dump. Is there something wrong with the code.?
cheers
Violino
if(cycle == 1)
BGM = fopen("sd:/apps/mp3demo/data/bgm.mp3", "rb");
if(cycle == 2){
fseek (BGM , 0 , SEEK_END);
lSize = ftell (BGM);
rewind (BGM);//Return to the beginning of the MP3 for good measure
}
if(cycle == 3){
buffer = (char*) malloc (sizeof(char)*lSize);//Allocate memory to contain the whole file
result = fread (buffer,1,lSize,BGM);//Copy the file into the buffer
}
if(cycle == 4){
fclose(BGM);//Since we no longer need BGM, get rid of it
MP3Player_PlayBuffer(buffer, lSize, NULL);//Play the buffer
mp3isready = true;//Let LoopTheMP3() know it can start working
}
LoopTheMP3();
if(cycle > 0 && cycle < 4){
sleep(1);
cycle++;
}
Hm ... Its been awhile since I went through all of this. If you could send me your code ( castlevania7689@yahoo.com ) I'll run through it and try to get back to you before the holidays. Cheers.
ReplyDelete