Playing mp3s with libmad: no sound March 29, 2009 11:33PM | Registered: 14 years ago Posts: 188 |
#include#include #include #include #include #include #include #include #include #include #define SAMPLE_RATE 44100 #define FRAME_SIZE MAD_BUFFER_MDLEN //1024 #define RINGBUF_SIZE ((SAMPLE_RATE * 4) * 5) struct mad_decoder decoder; static void *xfb = NULL; static GXRModeObj *rmode = NULL; FILE *fmp3 = NULL; bool play_mp3 = 1; u8 *frame = NULL; u16 *samples_ringbuffer; u16 *samples_playbuf; int mad_ringbuffer_pos, aud_ringbuffer_pos; bool allow_play = 0; /*struct buffer { unsigned char const *start; unsigned long length; };*/ void voicecallback(s32 voice) { memcpy(samples_playbuf, &samples_ringbuffer[aud_ringbuffer_pos], (44100 * 4)); aud_ringbuffer_pos+=(SAMPLE_RATE * 4); ASND_AddVoice(voice, samples_playbuf, (SAMPLE_RATE * 4) + 16); if(aud_ringbuffer_pos > RINGBUF_SIZE * 10)aud_ringbuffer_pos = 0; } enum mad_flow input(void *data, struct mad_stream *stream) { int read_framelen = 0; //struct buffer *buffer = data; //if (!buffer->length) //return MAD_FLOW_STOP; //mad_stream_buffer(stream, buffer->start, buffer->length); //buffer->length = 0; if(!play_mp3 || fmp3==NULL)return MAD_FLOW_STOP; if(feof(fmp3)!=0) { ASND_StopVoice(8); return MAD_FLOW_STOP; } memset(frame, 0, FRAME_SIZE); read_framelen = fread(frame, 1, FRAME_SIZE, fmp3); mad_stream_buffer(stream, frame, read_framelen); return MAD_FLOW_CONTINUE; } /* * The following utility routine performs simple rounding, clipping, and * scaling of MAD's high-resolution samples down to 16 bits. It does not * perform any dithering or noise shaping, which would be recommended to * obtain any exceptional audio quality. It is therefore not recommended to * use this routine if high-quality output is desired. */ inline signed int scale(mad_fixed_t sample) { /* round */ sample += (1L << (MAD_F_FRACBITS - 16)); /* clip */ if (sample >= MAD_F_ONE) sample = MAD_F_ONE - 1; else if (sample < -MAD_F_ONE) sample = -MAD_F_ONE; /* quantize */ return sample >> (MAD_F_FRACBITS + 1 - 16); } /* * This is the output callback function. It is called after each frame of * MPEG audio data has been completely decoded. The purpose of this callback * is to output (or play) the decoded PCM audio. */ enum mad_flow output(void *data, struct mad_header const *header, struct mad_pcm *pcm) { unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; /* pcm->samplerate contains the sampling frequency */ nchannels = pcm->channels; nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; while (nsamples--) { signed int sample; /* output sample(s) in 16-bit signed little-endian PCM */ sample = scale(*left_ch++); //putchar((sample >> 0) & 0xff); //putchar((sample >> 8) & 0xff); samples_ringbuffer[mad_ringbuffer_pos] = sample; mad_ringbuffer_pos++; if(mad_ringbuffer_pos * 2 > RINGBUF_SIZE)mad_ringbuffer_pos = 0; if (nchannels == 2) { sample = scale(*right_ch++); //putchar((sample >> 0) & 0xff); //putchar((sample >> 8) & 0xff); samples_ringbuffer[mad_ringbuffer_pos] = sample; mad_ringbuffer_pos++; if(mad_ringbuffer_pos * 2 > RINGBUF_SIZE)mad_ringbuffer_pos = 0; } } if(!allow_play) { allow_play = 1; memcpy(samples_playbuf, &samples_ringbuffer[aud_ringbuffer_pos], (SAMPLE_RATE * 4)); aud_ringbuffer_pos+=(44100 * 4); if(ASND_SetVoice(8, VOICE_STEREO_16BIT, SAMPLE_RATE, 0, samples_playbuf, (SAMPLE_RATE * 4) + 16, 175, 175, voicecallback)==SND_INVALID)printf("ASND_SetVoice returned SND_INVALID.\n"); if(aud_ringbuffer_pos > RINGBUF_SIZE)aud_ringbuffer_pos = 0; } return MAD_FLOW_CONTINUE; } /* * This is the error callback function. It is called whenever a decoding * error occurs. The error is indicated by stream->error; the list of * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h) * header file. */ enum mad_flow error(void *data, struct mad_stream *stream, struct mad_frame *frame) { //struct buffer *buffer = data; fprintf(stderr, "decoding error.\n"); /*fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n", stream->error, mad_stream_errorstr(stream), stream->this_frame - buffer->start);*/ /* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ return MAD_FLOW_CONTINUE; } int main(int argc, char **argv) { // Initialise the video system VIDEO_Init(); // This function initialises the attached controllers WPAD_Init(); // Obtain the preferred video mode from the system // This will correspond to the settings in the Wii menu rmode = VIDEO_GetPreferredMode(NULL); // Allocate memory for the display in the uncached region xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); // Initialise the console, required for printf console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); // Set up the video registers with the chosen mode VIDEO_Configure(rmode); // Tell the video hardware where our display memory is VIDEO_SetNextFramebuffer(xfb); // Make the display visible VIDEO_SetBlack(FALSE); // Flush the video register changes to the hardware VIDEO_Flush(); // Wait for Video setup to complete VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); iprintf("\x1b[2;2HMadPlayMp3 - test playing mp3 from /play.mp3 from SD.\n"); if(!fatInitDefault()) { printf("Failed to init FAT.\n"); while(1) { WPAD_ScanPads(); if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0); } } printf("Old frame size %d %x\n", MAD_BUFFER_MDLEN, MAD_BUFFER_MDLEN); samples_ringbuffer = (u16*)malloc(RINGBUF_SIZE); if(samples_ringbuffer==NULL) { printf("Samples ring buffer memory allocation error.\n"); return 1; } memset(samples_ringbuffer, 0, RINGBUF_SIZE); frame = (u8*)malloc(FRAME_SIZE); if(frame==NULL) { printf("Frame memory allocation error.(%d %x)\n", FRAME_SIZE, FRAME_SIZE); return 1; } memset(frame, 0, FRAME_SIZE); samples_playbuf = (u16*)memalign(32, (SAMPLE_RATE * 4) + 16); if(samples_playbuf==NULL) { printf("Samples play buf memory allocation error.\n"); return 1; } memset(samples_playbuf, 0, (SAMPLE_RATE * 4) + 16); mad_ringbuffer_pos = 0; aud_ringbuffer_pos = 0; allow_play = 0; play_mp3 = 1; fmp3 = fopen("/play.mp3", "rb"); if(fmp3==NULL) { printf("Failed to open /play.mp3\n"); free(frame); while(1) { WPAD_ScanPads(); if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0); } } printf("Playing /play.mp3...\n"); /* configure input, output, and error functions */ ASND_Init(); ASND_Pause(0); mad_decoder_init(&decoder, 0/*&buffer*/, input, 0 /* header */, 0 /* filter */, output, error, 0 /* message */); mad_decoder_run(&decoder, MAD_DECODER_MODE_ASYNC); while(1) { WPAD_ScanPads(); if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) { mad_decoder_finish(&decoder); free(frame); free(samples_ringbuffer); free(samples_playbuf); fclose(fmp3); exit(0); } if (WPAD_ButtonsDown(0) & WPAD_BUTTON_B)play_mp3 = !play_mp3; if (WPAD_ButtonsDown(0) & WPAD_BUTTON_MINUS)play_mp3 = 0; if (WPAD_ButtonsDown(0) & WPAD_BUTTON_PLUS)play_mp3 = 1; } return 0; }
Re: Playing mp3s with libmad: no sound March 30, 2009 06:47AM | Registered: 14 years ago Posts: 703 |
void MP3Player_Init(); void MP3Player_Stop(); BOOL MP3Player_IsPlaying(); void MP3Player_Volume(u32 volume); s32 MP3Player_PlayBuffer(const void *buffer,s32 len,void (*filterfunc)(struct mad_stream *,struct mad_frame *)); s32 MP3Player_PlayFile(void *cb_data,s32 (*reader)(void *,void *,s32),void (*filterfunc)(struct mad_stream *,struct mad_frame *));
Re: Playing mp3s with libmad: no sound March 31, 2009 05:02AM | Registered: 14 years ago Posts: 188 |
Re: Playing mp3s with libmad: no sound March 31, 2009 08:40AM | Registered: 14 years ago Posts: 703 |
Re: Playing mp3s with libmad: no sound March 31, 2009 06:20PM | Registered: 14 years ago Posts: 441 |
Re: Playing mp3s with libmad: no sound April 01, 2009 02:24AM | Registered: 14 years ago Posts: 188 |
Re: Playing mp3s with libmad: no sound April 01, 2009 09:57PM | Registered: 14 years ago Posts: 188 |
s32 mp3player_input(void* cb_data, void* ReadStart, s32 ReadLen) { int read_framelen = 0; //struct buffer *buffer = data; //if (!buffer->length) //return MAD_FLOW_STOP; //mad_stream_buffer(stream, buffer->start, buffer->length); //buffer->length = 0; if(!play_mp3 || fmp3==NULL)return 0; if(feof(fmp3)!=0) { //ASND_StopVoice(8); return 0; } memset(frame, 0, ReadLen); read_framelen = fread(ReadStart, 1, ReadLen, fmp3); //read_framelen = fread(frame, 1, FRAME_SIZE, fmp3); //mad_stream_buffer(stream, frame, read_framelen); /*if(feof(fmp3)!=0) { //ASND_StopVoice(8); return 0; }*/ return read_framelen; } int main(int argc, char **argv) { ... //ASND_Init();//Adding these don't help. //ASND_Pause(0); MP3Player_Init(); MP3Player_PlayFile(&buffer, mp3player_input, 0); ... }
Re: Playing mp3s with libmad: no sound April 02, 2009 01:03AM | Registered: 14 years ago Posts: 441 |
Re: Playing mp3s with libmad: no sound April 04, 2009 07:55PM | Registered: 14 years ago Posts: 188 |
Re: Playing mp3s with libmad: no sound April 05, 2009 05:58PM | Registered: 14 years ago Posts: 441 |
Re: Playing mp3s with libmad: no sound April 07, 2009 07:38PM | Registered: 14 years ago Posts: 188 |
Re: Playing mp3s with libmad: no sound August 27, 2009 07:38PM | Registered: 13 years ago Posts: 60 |
Re: Playing mp3s with libmad: no sound August 28, 2009 01:31PM | Registered: 14 years ago Posts: 157 |
#include#include #include #include #include #include #include //needed for mp3 #include #include //not used here #include //mp3 #include "grrlib/GRRLIB.h" //graphics drawing lib #include "test_mp3.h" #include "gfx/bg.h" #include "gfx/point.h" #include "gfx/font.h" #include "gfx/button.h" #include "gfx/message.h" //Needed by GRRLIB Mtx GXmodelView2D; //video static u32 *xfb; static GXRModeObj *rmode; //ir variable ir_t ir; // function for initialising video, called at start of main() void Initialise() { VIDEO_Init(); rmode = VIDEO_GetPreferredMode(NULL); xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); VIDEO_Configure(rmode); VIDEO_SetNextFramebuffer(xfb); VIDEO_SetBlack(FALSE); VIDEO_Flush(); VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); //used to have these in Initialise, but wouldn't allow turning on and off in while //loop from main (), for some reason //ASND_Init(); //MP3Player_Init(); //if (!MP3Player_IsPlaying()) MP3Player_PlayBuffer(test_mp3,test_mp3_size,NULL); //MP3Player_Stop(); //Wiimote activation WPAD_Init(); WPAD_SetVRes(0, 640, 480); WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR); //Initialiases GRRLIB, needed to begin loading and drawing GRRLIB_Init(); } int main() { //calls Initialise function, no reason really. Initialise(); //dunno what this does printf("\x1b[2;OH"); //loads bg texture and assigns it to tex_background GRRLIB_texImg tex_background = GRRLIB_LoadTexture(bg); //Draws background, probably not needed here GRRLIB_DrawImg(0, 0, tex_background, 0, 1, 1, 0xffffffff); //loads other textures GRRLIB_texImg tex_point = GRRLIB_LoadTexture(point); GRRLIB_texImg tex_button = GRRLIB_LoadTexture(button); GRRLIB_texImg tex_message = GRRLIB_LoadTexture(message); //makes graphics appear GRRLIB_Render(); //variables used to track ir movement, positioned to keep cursor off screen before //wiimote is synched. Poss leaving these undefined would stop issue with it appearing //slightly on screen still. int cursor_x = 0; int cursor_y = 0; //Initialises sound and mp3 things ASND_Init(); MP3Player_Init(); //If no music playing, play test.mp3 (underworld) if (!MP3Player_IsPlaying()) MP3Player_PlayBuffer(test_mp3,test_mp3_size,NULL); //then immediately stop. Loading in the while loop wasn't working, so done here then stopped. MP3Player_Stop(); //main loop for tracking input while(1) { //Checks wiimote button input WPAD_ScanPads(); //assigns the variable pressed to record when a button is held u32 pressed = WPAD_ButtonsDown(0); //checks wiimote ir input WPAD_IR(0, &ir); //sets these variables to match ir position cursor_x = ir.x; cursor_y = ir.y; //We fill the screen in white(RGBA format) GRRLIB_FillScreen(0xFFFFFFFF); //draw images (in correct order!) GRRLIB_DrawImg(0, 0, tex_background, 0, 1, 1, 0xffffffff); GRRLIB_DrawImg(445, 55, tex_button, 0, 1, 1, 0xffffffff); GRRLIB_DrawImg (176, 367, tex_message, 0, 1, 1, 0xffffffff); //Cursor offset as seems to set ir at 0,0 of the png GRRLIB_DrawImg((cursor_x - 40), (cursor_y - 40), tex_point, 0, 1, 1, 0xffffffff); //makes images appear GRRLIB_Render(); //handles turning music on and off if (pressed & WPAD_BUTTON_A) { //if a is pressed, and the cursor is over the button, and music is not playing, play music if ((ir.x >= 449 && ir.x <= 495 && ir.y >=59 && ir.y <= 75) & (!MP3Player_IsPlaying())) MP3Player_PlayBuffer(test_mp3, test_mp3_size, NULL); //otherwise, if it is playing, stop it else if ((ir.x >= 449 && ir.x <= 495 && ir.y >=59 && ir.y <= 75) & (MP3Player_IsPlaying())) MP3Player_Stop(); } //return to loader if (pressed & WPAD_BUTTON_HOME) { if (MP3Player_IsPlaying()) { MP3Player_Stop(); exit(0); } exit(0); } } //Good practice, apparently. GRRLIB_Exit(); return 0; }
Re: Playing mp3s with libmad: no sound August 28, 2009 06:01PM | Registered: 13 years ago Posts: 60 |
Re: Playing mp3s with libmad: no sound August 28, 2009 06:10PM | Registered: 14 years ago Posts: 157 |
#--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- $(OUTPUT).dol: $(OUTPUT).elf $(OUTPUT).elf: $(OFILES) #--------------------------------------------------------------------------------- # This rule links in binary data with the .mp3 extension #--------------------------------------------------------------------------------- %.mp3.o : %.mp3 #--------------------------------------------------------------------------------- @echo $(notdir $<) $(bin2o) -include $(DEPENDS) #--------------------------------------------------------------------------------- endif #---------------------------------------------------------------------------------