MP3软件解码

2019-07-21 08:40发布

我在论坛里面找了个heilx软件解码的程序,数据是通过串口接收的,
程序查找同步字都成功了,解码函数也执行通过就是没有看到输出PCM数据,不知道PCM数据到底是在那里输出的

大家帮忙看看在那个位置输出PCM

/**
  * @brief  mp3_player 进行mp3文件解码、播放
  * @param  filename:要播放的文件路径
  * @retval none
  */
//static void mp3_player(const char *filename)
void mp3_player(void)
{
        int err,/* i,*/ outputSamps;//, current_sample_rate = 0;       

        int                                read_offset = 0;                                /* 读偏移指针                                */
        int                                bytes_left = 0;                                        /* 剩余字节数                                */       
        unsigned long        Frames = 0;                                            /* mP3帧计数                                */
        unsigned char        *read_ptr = buffer;                            /* 缓冲区指针                                */
        HMP3Decoder                Mp3Decoder;                                                /* mp3解码器指针                */
       

        //打开成功
        //初始化MP3解码器
        Mp3Decoder = MP3InitDecoder();       
       
        //获取输入数据流,调用helix库解码,输出PCM数据,约20ms完成一次循环
        //开始进入播放状态,期间中断会修改touch_even状态
        while(1)        //循环1, 如果touch_even不是切歌状态则继续呆在循环体里
        {
                //有时出现解码错误,错误后继续在本循环体内,继续播放
               
               
                //
                read_ptr  = buffer;
                bytes_left = 0;
               
                //
                Communication();
               
                if(UART1_Index3 < 1126)
                        break;
                read_ptr     = buffer;                                                                                //指向mp3输入流
                bytes_left   = UART1_Index3;                                                                //实际读到的输入流大小大小
                UART1_Index3 = 0;
                bufflag      = 0;
        //        UART1_Index3 = 0;
               
                //按帧处理       
                while(1)                       
                {

                        read_offset = MP3FindSyncWord(read_ptr, bytes_left);        //寻找帧同步,返回第一个同步字的位置
                        if(read_offset < 0)                                                                                //没有找到同步字
                        {
                                break;                                                                                                //跳出循环2,回到循环1       
                        }
                       
                        read_ptr   += read_offset;                                                                //偏移至同步字的位置
                        bytes_left -= read_offset;                                                                //同步字之后的数据大小       
               
                        //
                        err = MP3Decode(Mp3Decoder, &read_ptr, &bytes_left, outBuf[bufflag], 0);                                                //开始解码 参数:mp3解码结构体、输入流指针、输入流大小、输出流指针、数据格式
                        Frames++;                       
                       
                        if (err != ERR_MP3_NONE)                                                                                                //错误处理
                        {
                                switch (err)
                                {
                                        case ERR_MP3_INDATA_UNDERFLOW:
                                        //        printf("ERR_MP3_INDATA_UNDERFLOW ");
                                                read_ptr = buffer;
                                                //fres = f_read(&file, read_ptr, sizeof(buffer), &rw_num);
                                                bytes_left = rw_num;
                                                break;
                       
                                        case ERR_MP3_MAINDATA_UNDERFLOW:
                                                /* do nothing - next call to decode will provide more mainData */
                                        //        printf("ERR_MP3_MAINDATA_UNDERFLOW ");
                                                break;
                       
                                        default:
                                        //        printf("UNKNOWN ERROR:%d ", err);
                       
                                                // 跳过此帧
                                                if (bytes_left > 0)
                                                {
                                                        bytes_left --;
                                                        read_ptr ++;
                                                }       
                                                break;
                                }
                        }
                        else                //解码无错误,准备把数据输出到PCM
                        {
                                MP3GetLastFrameInfo(Mp3Decoder, &Mp3FrameInfo);                //获取解码信息                               

                                /* 输出到DAC */
                                outputSamps = Mp3FrameInfo.outputSamps;                                                        //PCM数据个数
                               
                                if (outputSamps > 0)
                                {
                                        //
                                        if(1 == Mp3FrameInfo.nChans)
                                                Convert_Mono(  &outBuf[bufflag][0]);
                                        else
                                                Convert_Stereo(&outBuf[bufflag][0]);
                                //        if (Mp3FrameInfo.nChans == 1)        //单声道
                                //        {
                                                //单声道数据需要复制一份到另一个声道
                                //                for (i = outputSamps - 1; i >= 0; i--)
                                        //        {
                                        //                outBuf[bufflag][i * 2] = outBuf[bufflag];
                                        //                outBuf[bufflag][i * 2 + 1] = outBuf[bufflag];
                                        //        }
                                        //        outputSamps *= 2;
                                //        }
                                //        else
                                //        {

                                //        }
                               
                                        //非单声道数据可直接由DMA传输到IIS交给DAC
                                        /* 等待DMA播放完,这段时间我们可以干其他的事,扫描事件进行处理 */
                                //        while((DMA1_Channel5->CCR&DMA_CCR1_EN) && !(DMA1->ISR&DMA1_IT_TC5))
                                //        {

                                //                static uint8_t i=0;
                                        //        if(i==0)
                                        //        {
                                                //  PCM1770_VolumeSet(voice);
                                        //          i++;
                                        //        }

//                                                        even_process();                                                       
                                        //        }
                                               
                                                /*DMA传输完毕*/
                                        // DMA_ClearFlag(DMA1_FLAG_TC5 | DMA1_FLAG_TE5);
                                        // DMA_I2S_Configuration((uint32_t)outBuf[bufflag], outputSamps);
                                        //        bufflag = 1 -bufflag;                                                                                                                                                        //切换buffer

                                }
                        }
                       
               
        //        if(file.fptr==file.fsize)                 //如果指针指向了文件尾,表示数据全部读完
        //        {
                //        printf("END ");
                //        if(play_index<file_num-1)                //自动开始下一首歌曲
                //        {
                        //        play_index++;
                        //        player_state = S_SWITCH;        //进入切歌状态,跳出
                        //}
                        //else
                        //{
                        //        play_index = 0;
                        //        player_state = S_SWITCH;
                        //}
                                       
                //        break;                                                                                 //跳出这首歌的播放状态        while break;
        //        }
         
        }
       
}

//        f_close(&file);                                                        //结束播放本歌曲,关闭文件
//        MP3FreeDecoder(Mp3Decoder);
//        I2S_Stop();
       
}




程序已经执行到了红 {MOD}区域了,输出PCM个数是2304个PCM,但是我查看outbuf缓存区全部00不知道是怎么回事
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
8条回答
ricefat
1楼-- · 2019-07-21 12:36
爱好单片机
2楼-- · 2019-07-21 14:40
ricefat 发表于 2016-1-6 14:12
http://www.openedv.com/thread-21204-1-1.html希望能给你帮助

谢谢的的回答,我看了你的程序,但是不知道你的PCM数据是不是放到,buffer1和,buffer2缓存区里面的,是不是红 {MOD}区域的代码,PCM数据就已经出错到,buffer缓存区里面的
/**
  * @brief  Start wave player
  * @param  None
  * @retval None
  */
void WavePlayerStart(void)
{
  u32 br;
        FRESULT res;
        uint16_t i;
       
        char path[] = "0:/";

  //buffer_switch = 1;
       
        hMP3Decoder=MP3InitDecoder();//初始化MP3解码器

  /* Get the read out protection status */
  if (f_opendir(&dir, path)!= FR_OK)
  {
    while(1)
    {
      STM_EVAL_LEDToggle(LED5);
      Delay(10);
    }   
  }
  else
  {
    if (WaveRecStatus == 1)
    {
      WaveFileName = REC_WAVE_NAME;
    }
    else
    {
      WaveFileName = "0:audio.mp3";//WAVE_NAME; 名字改下
    }
    /* Open the wave file to be played */
    if (f_open(&fileR, WaveFileName , FA_READ) != FR_OK)
    {
      STM_EVAL_LEDOn(LED5);
      Command_index = 1;
    }
    else
    {  


      //复位计数器
                bytesLeft=0;
                readPtr=readBuf;                                       
                res=f_read(&fileR,readBuf,READBUF_SIZE,&br);
                bytesLeft += br;                                       
                //if(res!=FR_OK||br==0) break;
                XferCplt=1;
                buffer_switch=0;
                init=0;
                WavePlayerInit((u32)44100);
                while(1)
                {
                        offset=MP3FindSyncWord(readPtr, bytesLeft);//寻找下一帧头        assume EOF if no sync found
                        if(offset<0)break;
                        readPtr+=offset; //data start point
                        bytesLeft-=offset; //in buffer
                        if(bytesLeft<READBUF_SIZE)
                        {
                                memmove(readBuf,readPtr,bytesLeft);
                                res=f_read(&fileR,readBuf+bytesLeft,READBUF_SIZE-bytesLeft,&br);
                                if((res)||(br==0)) break;                                               
                                if(br<READBUF_SIZE-bytesLeft)
                                memset(readBuf+bytesLeft+br,0,READBUF_SIZE-bytesLeft-br);
                                bytesLeft=READBUF_SIZE;
                                readPtr=readBuf;               
                        }
                        MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo);
从这里开始是不是PCM已经转换完成了,准备送往DA转换

//                        if(init==0)//根据MP3帧信息初始化音频接口  //
//                        {
//                                WavePlayerInit((u32)mp3FrameInfo.samprate);
//                                init=1;
//                        }                                                       




                        while(XferCplt==0);
                        XferCplt=0;                                                       
                        if(buffer_switch == 0)
                        {
                               
                                Audio_MAL_Play((u32)buffer2,BUFF_SIZE*2);       


                                //Decbuf=buffer1;
                                MP3Decode(hMP3Decoder,&readPtr,&bytesLeft,buffer1,0);
                                //Convert_Stereo(buffer1);
                                buffer_switch = 1;
                        }
                        else
                        {   
                                Audio_MAL_Play((u32)buffer1,BUFF_SIZE*2);
                                //Decbuf=buffer2;
                                MP3Decode(hMP3Decoder,&readPtr,&bytesLeft,buffer2,0);
                                //Convert_Stereo(buffer2);
                                buffer_switch = 0;
                        }
                }
                       
    }   
  }
}
ricefat
3楼-- · 2019-07-21 19:25
爱好单片机 发表于 2016-1-6 14:30
谢谢的的回答,我看了你的程序,但是不知道你的PCM数据是不是放到,buffer1和,buffer2缓存区里面的,是不 ...

解码是这句,前面只是读取mp3文件用的,
MP3Decode(hMP3Decoder,&readPtr,&bytesLeft,buffer1,0);
MP3Decode(hMP3Decoder,&readPtr,&bytesLeft,buffer2,0);
解码完成的PCM数据放在buffer1,2中,Audio_MAL_play实际是开启buffer到外部DAC的DMA通道
爱好单片机
4楼-- · 2019-07-22 00:39
ricefat 发表于 2016-1-6 14:36
解码是这句,前面只是读取mp3文件用的,
MP3Decode(hMP3Decoder,&readPtr,&bytesLeft,buffer1,0);
MP3D ...

奥,我在看看,不知道为我执行过解码函数MP3Decode,buffer缓存区没有数据全部是00
爱好单片机
5楼-- · 2019-07-22 01:51
 精彩回答 2  元偷偷看……
ricefat
6楼-- · 2019-07-22 03:53
爱好单片机 发表于 2016-1-6 18:41
问题还是没有找到,解码进入这个函数,我单步调试没有发现向buffer缓存区写PCM数据的,只有出错清空buf ...

如果清空缓冲区 说明mp3帧错误,你看看decode这个函数返回的什么值

一周热门 更多>