打印
[STM32F4]

【分享】一个MP3解码程序

[复制链接]
3659|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
胡斯哲|  楼主 | 2016-11-27 15:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 胡斯哲 于 2016-11-27 16:04 编辑

刚开始以为MP3解码会很简单,搞成功后,没那么难,分享下
开发板是原子的探索者,需要例程综合实验中的AUDIOCODEC中的MP3文件和wav解码试验程序。1、将MP3文件考进“音乐 播放器实验”中
2、主程序不需要改动,将auioplay.c中的u8 audio_play_song(u8* fname)程序里头改为如下
//²¥·Åij¸öÒôƵÎļþ
u8 audio_play_song(u8* fname)
{
        u8 res;  
        res=f_typetell(fname);
        switch(res)
        {
//                case T_WAV:
//                        res=wav_play_song(fname);
//                        break;
<font color="#ff0000">                case T_MP3:
                        res=mp3_play_song(fname);</font>
                        break;
                default://ÆäËûÎļþ,×Ô¶¯Ìøתµ½ÏÂÒ»Çú
                        printf("can't play:%s\r\n",fname);
                        res=KEY0_PRES;
                        break;
        }
        return res;
}
加入mp3play.h的头文件
3、在mp3play.c中将u8 mp3_play_song(u8* fname)改动红色地方
u8 mp3_play_song(u8* fname)
{
        HMP3Decoder mp3decoder;
        MP3FrameInfo mp3frameinfo;
        u8 res,key;
        u8* buffer;                //ÊäÈëbuffer  
        u8* readptr;        //MP3½âÂë¶ÁÖ¸Õë
        int offset=0;        //Æ«ÒÆÁ¿
        int outofdata=0;//³¬³öÊý¾Ý·¶Î§
        int bytesleft=0;//buffer»¹Ê£ÓàµÄÓÐЧÊý¾Ý
        u32 br=0;
        int err=0;  
        
         mp3ctrl=mymalloc(SRAMIN,sizeof(__mp3ctrl));
        buffer=mymalloc(SRAMIN,MP3_FILE_BUF_SZ);         //ÉêÇë½âÂëbuf´óС
        audiodev.file=(FIL*)mymalloc(SRAMIN,sizeof(FIL));
        audiodev.i2sbuf1=mymalloc(SRAMIN,2304*2);
        audiodev.i2sbuf2=mymalloc(SRAMIN,2304*2);
        audiodev.tbuf=mymalloc(SRAMIN,2304*2);
        audiodev.file_seek=mp3_file_seek;
        
        if(!mp3ctrl||!buffer||!audiodev.file||!audiodev.i2sbuf1||!audiodev.i2sbuf2||!audiodev.tbuf)//ÄÚ´æÉêÇëʧ°Ü
        {
                myfree(SRAMIN,mp3ctrl);
                myfree(SRAMIN,buffer);
                myfree(SRAMIN,audiodev.file);
                myfree(SRAMIN,audiodev.i2sbuf1);
                myfree(SRAMIN,audiodev.i2sbuf2);
                myfree(SRAMIN,audiodev.tbuf);
                return AP_ERR;        //´íÎó
        }
        memset(audiodev.i2sbuf1,0,2304*2);        //Êý¾ÝÇåÁã
        memset(audiodev.i2sbuf2,0,2304*2);        //Êý¾ÝÇåÁã
        memset(mp3ctrl,0,sizeof(__mp3ctrl));//Êý¾ÝÇåÁã
        res=mp3_get_info(fname,mp3ctrl);  
        if(res==0)
        {
                printf("     title:%s\r\n",mp3ctrl->title);
                printf("    artist:%s\r\n",mp3ctrl->artist);
                printf("   bitrate:%dbps\r\n",mp3ctrl->bitrate);        
                printf("samplerate:%d\r\n", mp3ctrl->samplerate);        
                printf("  totalsec:%d\r\n",mp3ctrl->totsec);
               
                WM8978_I2S_Cfg(2,0);        //·ÉÀûÆÖ±ê×¼,16λÊý¾Ý³¤¶È
        I2S2_Init(I2S_Standard_Phillips,I2S_Mode_MasterTx,I2S_CPOL_Low,I2S_DataFormat_16bextended);        //·ÉÀûÆÖ±ê×¼,Ö÷»ú·¢ËÍ,ʱÖӵ͵çƽÓÐЧ,16λÀ©Õ¹Ö¡³¤¶È
         
                I2S2_SampleRate_Set(mp3ctrl->samplerate);                //ÉèÖòÉÑùÂÊ
                I2S2_TX_DMA_Init(audiodev.i2sbuf1,audiodev.i2sbuf2,mp3ctrl->outsamples);//ÅäÖÃTX DMA
                i2s_tx_callback=mp3_i2s_dma_tx_callback;                //»Øµ÷º¯ÊýÖ¸Ïòmp3_i2s_dma_tx_callback
                mp3decoder=MP3InitDecoder();                                         //MP3½âÂëÉêÇëÄÚ´æ
                res=f_open(audiodev.file,(char*)fname,FA_READ);        //´ò¿ªÎļþ
        }
        if(res==0&&mp3decoder!=0)//´ò¿ªÎļþ³É¹¦
        {
                f_lseek(audiodev.file,mp3ctrl->datastart);        //Ìø¹ýÎļþÍ·ÖÐtagÐÅÏ¢
                audio_start();                                                                //¿ªÊ¼²¥·Å
                while(res==0)
                {
                        readptr=buffer;        //MP3¶ÁÖ¸ÕëÖ¸Ïòbuffer
                        offset=0;                //Æ«ÒÆÁ¿Îª0
                        outofdata=0;        //Êý¾ÝÕý³£
                        bytesleft=0;        
                        res=f_read(audiodev.file,buffer,MP3_FILE_BUF_SZ,&br);//Ò»´Î¶ÁÈ¡MP3_FILE_BUF_SZ×Ö½Ú
                        if(res)//¶ÁÊý¾Ý³ö´íÁË
                        {
                                res=AP_ERR;
                                break;
                        }
                        if(br==0)                //¶ÁÊýΪ0,˵Ã÷½âÂëÍê³ÉÁË.
                        {
                                res=AP_OK;        //²¥·ÅÍê³É
                                break;
                        }
                        bytesleft+=br;        //bufferÀïÃæÓжàÉÙÓÐЧMP3Êý¾Ý?
                        err=0;                        
                        while(!outofdata)//ûÓгöÏÖÊý¾ÝÒì³£(¼´¿É·ñÕÒµ½Ö¡Í¬²½×Ö·û)
                        {
                                offset=MP3FindSyncWord(readptr,bytesleft);//ÔÚreadptrλÖÃ,¿ªÊ¼²éÕÒͬ²½×Ö·û
                                if(offset<0)        //ûÓÐÕÒµ½Í¬²½×Ö·û,Ìø³öÖ¡½âÂëÑ­»·
                                {
                                        outofdata=1;//ûÕÒµ½Ö¡Í¬²½×Ö·û
                                }else        //ÕÒµ½Í¬²½×Ö·ûÁË
                                {
                                        readptr+=offset;                //MP3¶ÁÖ¸ÕëÆ«ÒƵ½Í¬²½×Ö·û´¦.
                                        bytesleft-=offset;                //bufferÀïÃæµÄÓÐЧÊý¾Ý¸öÊý,±ØÐë¼õȥƫÒÆÁ¿
                                        err=MP3Decode(mp3decoder,&readptr,&bytesleft,(short*)audiodev.tbuf,0);//½âÂëÒ»Ö¡MP3Êý¾Ý
                                        if(err!=0)
                                        {
                                                printf("decode error:%d\r\n",err);
                                                break;
                                        }else
                                        {
                                                MP3GetLastFrameInfo(mp3decoder,&mp3frameinfo);        //µÃµ½¸Õ¸Õ½âÂëµÄMP3Ö¡ÐÅÏ¢
                                                if(mp3ctrl->bitrate!=mp3frameinfo.bitrate)                //¸üÐÂÂëÂÊ
                                                {
                                                        mp3ctrl->bitrate=mp3frameinfo.bitrate;
                                                }
                                                mp3_fill_buffer((u16*)audiodev.tbuf,mp3frameinfo.outputSamps,mp3frameinfo.nChans);//Ìî³äpcmÊý¾Ý
                                        }
                                        if(bytesleft<MAINBUF_SIZE*2)//µ±Êý×éÄÚÈÝСÓÚ2±¶MAINBUF_SIZEµÄʱºò,±ØÐë²¹³äеÄÊý¾Ý½øÀ´.
                                        {
                                                memmove(buffer,readptr,bytesleft);//Òƶ¯readptrËùÖ¸ÏòµÄÊý¾Ýµ½bufferÀïÃæ,Êý¾ÝÁ¿´óСΪ:bytesleft
                                                f_read(audiodev.file,buffer+bytesleft,MP3_FILE_BUF_SZ-bytesleft,&br);//²¹³äÓàϵÄÊý¾Ý
                                                if(br<MP3_FILE_BUF_SZ-bytesleft)
                                                {
                                                        memset(buffer+bytesleft+br,0,MP3_FILE_BUF_SZ-bytesleft-br);
                                                }
                                                bytesleft=MP3_FILE_BUF_SZ;  
                                                readptr=buffer;
                                        }         
                                         while(audiodev.status&(1<<1))//Õý³£²¥·ÅÖÐ
                                        {                        
                                                delay_ms(1000/200);
                                                mp3_get_curtime(audiodev.file,mp3ctrl);
                                                audiodev.totsec=mp3ctrl->totsec;        //²ÎÊý´«µÝ
                                                audiodev.cursec=mp3ctrl->cursec;
                                                audiodev.bitrate=mp3ctrl->bitrate;
                                                audiodev.samplerate=mp3ctrl->samplerate;
                                                audiodev.bps=16;//MP3½öÖ§³Ö16λ
                                                 if(audiodev.status&0X01)break;//ûÓа´ÏÂÔÝÍ£
                                        }
                                        if((audiodev.status&(1<<1))==0)//ÇëÇó½áÊø²¥·Å/²¥·ÅÍê³É
                                        {  
                                                res=AP_NEXT;//Ìø³öÉÏÉϼ¶Ñ­»·
                                                outofdata=1;//Ìø³öÉÏÒ»¼¶Ñ­»·
                                                break;
                                        }
                                        while(1)
                                        {
                                                key=KEY_Scan(0);
                                                if(key==WKUP_PRES)//ÔÝÍ£
                                                {
                                                        if(audiodev.status&0X01)audiodev.status&=~(1<<0);
                                                        else audiodev.status|=0X01;  
                                                }
                                                if(key==KEY2_PRES||key==KEY0_PRES)//ÏÂÒ»Çú/ÉÏÒ»Çú
                                                {
                                                        audio_stop_req(&audiodev);
                                                        res=key;
                                                                audio_stop();//¹Ø±ÕÒôƵÊä³ö
                                                                f_close(audiodev.file);
                                                
                                                MP3FreeDecoder(mp3decoder);                //ÊÍ·ÅÄÚ´æ        
                                                myfree(SRAMIN,mp3ctrl);
                                                myfree(SRAMIN,buffer);
                                                myfree(SRAMIN,audiodev.file);
                                                myfree(SRAMIN,audiodev.i2sbuf1);
                                                myfree(SRAMIN,audiodev.i2sbuf2);
                                                myfree(SRAMIN,audiodev.tbuf);
                                                return res;
                                                        //break;
                                                }
                                                mp3_get_curtime(audiodev.file,mp3ctrl);//µÃµ½×Üʱ¼äºÍµ±Ç°²¥·ÅµÄʱ¼ä
                                                audio_msg_show(mp3ctrl->totsec,mp3ctrl->cursec,mp3ctrl->bitrate);
                                                if((audiodev.status&0X01)==0)delay_ms(10);
                                                else break;
                                        }                                       
                                }                                       
                        }  
                }
                audio_stop();//¹Ø±ÕÒôƵÊä³ö
        }////////////////////////////////////////////////////////////////////////////////else res=AP_ERR;//´íÎó
        f_close(audiodev.file);
        MP3FreeDecoder(mp3decoder);                //ÊÍ·ÅÄÚ´æ        
        myfree(SRAMIN,mp3ctrl);
        myfree(SRAMIN,buffer);
        myfree(SRAMIN,audiodev.file);
        myfree(SRAMIN,audiodev.i2sbuf1);
        myfree(SRAMIN,audiodev.i2sbuf2);
        myfree(SRAMIN,audiodev.tbuf);
        return res=KEY0_PRES;
}

4.编译一下,会有两个错误,是综合试验中MP3play.c的两个延时到ucos的两个常量,统统改为delay_ms(5);
就这么简单,自己够不敢相信,自己绕了那么多弯路。
不过能听到声音也是蛮开心的
再加上wav文件那也简单了     2016.11.27


mp3.rar

1.53 MB

沙发
dentsgot| | 2016-11-27 19:27 | 只看该作者
应该有专门的解码芯片吧

使用特权

评论回复
板凳
734774645| | 2016-11-27 20:47 | 只看该作者
软件解码效果没有硬解码好吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:读书喝茶,不争朝夕

141

主题

1431

帖子

6

粉丝