野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15596|回复: 26

MP3软件解码没有输出PCM数据

[复制链接]
发表于 2016-1-6 19:09:33 | 显示全部楼层 |阅读模式
/**
  * @brief  mp3_player 进行mp3文件解码、播放
  * @param  filename:要播放的文件路径
  * @retval none
  */
static void mp3_player(const char *filename)
{
        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解码器指针                */
       

       
        //打开音频文件
        fres = f_open (&file, filename, FA_READ );
       
        //打开失败
        if (fres!=FR_OK)
        {
                printf("read file %s error  ! open another file\r\n",filename);
                fres = f_close (&file);
               
                if (++play_index>=file_num)        //索引值加1
                {
                                play_index=0;                                                //归0,所以如果所有文件都打开失败会一直循环
                }                               
                return ;                                                                                //文件无法打开,终止解码。进入下一次循环,读取下一个文件
        }
               
        //打开成功
        //初始化MP3解码器
        Mp3Decoder = MP3InitDecoder();       
       
        //获取输入数据流,调用helix库解码,输出PCM数据,约20ms完成一次循环
        //开始进入播放状态,期间中断会修改touch_even状态
        while(player_state != S_SWITCH)        //循环1, 如果touch_even不是切歌状态则继续呆在循环体里
        {
                //有时出现解码错误,错误后继续在本循环体内,继续播放
               
                //显示播放图标
                Lcd_GramScan(1);
                LCD_Clear(12,88,8,145,BACKGROUND);
                Lcd_show_bmp(320-(103+((play_index-((current_page-1)*8))*18)),240-20,"/mp3player/ui_playing.bmp");
               
                //读取mp3文件
                fres = f_read(&file, buffer, sizeof(buffer), &rw_num);
                if(fres != FR_OK)
                {
                        printf("读取%s失败! %d\r\n",filename,fres);
                        break;
                        //return;
                }
                read_ptr = buffer;                                                                        //指向mp3输入流
                bytes_left = rw_num;                                                                //实际读到的输入流大小大小

                //按帧处理       
                while(player_state != S_SWITCH)                        //循环2,循环本过程播放音频,直到按了下一首、上一首       
                {
                        if (player_state == S_STOP)
                        {                                                               
                                even_process();                                                                        //检查是否有事件需要处理
                                continue;                                                                                                //暂停的时候结束本次循环
                        }
                               
                        player_state = S_PLAY;                                                //状态更新为正在播放
                       
                        read_offset = MP3FindSyncWord(read_ptr, bytes_left);        //寻找帧同步,返回第一个同步字的位置
                        if(read_offset < 0)                                                                                                                                                //没有找到同步字
                        {
                                break;                                                                                                                                                                                        //跳出循环2,回到循环1       
                        }
                       
                        read_ptr += read_offset;                                        //偏移至同步字的位置
                        bytes_left -= read_offset;                                        //同步字之后的数据大小       
                        if(bytes_left < 1024)                                                        //补充数据
                        {
                                /* 注意这个地方因为采用的是DMA读取,所以一定要4字节对齐  */
                                i=(uint32_t)(bytes_left)&3;                                                                        //判断多余的字节
                                if(i) i=4-i;                                                                                                                //需要补充的字节
                                memcpy(buffer+i, read_ptr, bytes_left);        //从对齐位置开始复制
                                read_ptr = buffer+i;                                                                                //指向数据对齐位置
                                fres = f_read(&file, buffer+bytes_left+i, sizeof(buffer)-bytes_left-i, &rw_num);//补充数据
                                bytes_left += rw_num;                                                                                //有效数据流大小
                        }
                        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\r\n");
                                                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\r\n");
                                                break;
                       
                                        default:
                                                printf("UNKNOWN ERROR:%d\r\n", err);
                       
                                                // 跳过此帧
                                                if (bytes_left > 0)
                                                {
                                                        bytes_left --;
                                                        read_ptr ++;
                                                }       
                                                break;
                                }
                        }
                        else                //解码无错误,准备把数据输出到PCM
                        {
                                MP3GetLastFrameInfo(Mp3Decoder, &Mp3FrameInfo);                //获取解码信息                               

                                /* 根据解码信息设置采样率 */
                                if (Mp3FrameInfo.samprate != current_sample_rate)        //采样率
                                {
                                        current_sample_rate = Mp3FrameInfo.samprate;

                                        printf(" \r\n Bitrate       %dKbps", Mp3FrameInfo.bitrate/1000);
                                  printf(" \r\n Samprate      %dHz", current_sample_rate);
                                        printf(" \r\n BitsPerSample %db", Mp3FrameInfo.bitsPerSample);
                                        printf(" \r\n nChans        %d", Mp3FrameInfo.nChans);
                                        printf(" \r\n Layer         %d", Mp3FrameInfo.layer);
                                        printf(" \r\n Version       %d", Mp3FrameInfo.version);
                                        printf(" \r\n OutputSamps   %d", Mp3FrameInfo.outputSamps);

                                        if(current_sample_rate >= I2S_AudioFreq_Default)        //I2S_AudioFreq_Default = 2,正常的帧,每次都要改速率
                                        {
                                                I2S_Freq_Config(current_sample_rate);                                                //根据采样率修改iis速率
                                        }
                                }
                               
                                /* 输出到DAC */
                                outputSamps = Mp3FrameInfo.outputSamps;                                                        //PCM数据个数
                               
                                if (outputSamps > 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;
                                        }
                               
                                        //非单声道数据可直接由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 (outputSamps > 0)
                        }//else 解码正常
                       
               
                if(file.fptr==file.fsize)                 //如果指针指向了文件尾,表示数据全部读完
                {
                        printf("END\r\n");
                        if(play_index<file_num-1)                //自动开始下一首歌曲
                        {
                                play_index++;
                                player_state = S_SWITCH;        //进入切歌状态,跳出
                        }
                        else
                        {
                                play_index = 0;
                                player_state = S_SWITCH;
                        }
                                       
                        break;                                                                                 //跳出这首歌的播放状态        while break;
                }
         
        }//循环2                内 while(player_state != S_SWITCH)       
       
}//循环1          外 while(player_state != S_SWITCH)

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

程序执行到红色代码区域,但是没有看到outBuf缓存区有数据,outBuf缓存区全部是00输出PCM个数是2304不知道为啥






回复

使用道具 举报

 楼主| 发表于 2016-1-6 19:10:10 | 显示全部楼层
本帖最后由 时光虫子 于 2016-1-6 19:12 编辑

解码函数MP3Decode我仿真跟踪发现没有看到有出错PCM数据的地方
/**********************************************************
* Function:    MP3Decode
*
* Description: decode one frame of MP3 data
*
* Inputs:      valid MP3 decoder instance pointer (HMP3Decoder)
*              double pointer to buffer of MP3 data (containing headers + mainData)
*              number of valid bytes remaining in inbuf
*              pointer to outbuf, big enough to hold one frame of decoded PCM samples
*              flag indicating whether MP3 data is normal MPEG format (useSize = 0)
*                or reformatted as "self-contained" frames (useSize = 1)
*
* Outputs:     PCM data in outbuf, interleaved LRLRLR... if stereo
*                number of output samples = nGrans * nGranSamps * nChans
*              updated inbuf pointer, updated bytesLeft
*
* Return:      error code, defined in mp3dec.h (0 means no error, < 0 means error)
*
* Notes:       switching useSize on and off between frames in the same stream
*                is not supported (bit reservoir is not maintained if useSize on)
**********************************************************/
int MP3Decode(HMP3Decoder hMP3Decoder, unsigned char **inbuf, int *bytesLeft, short *outbuf, int useSize)
{
        int offset, bitOffset, mainBits, gr, ch, fhBytes, siBytes, freeFrameBytes;
        int prevBitOffset, sfBlockBits, huffBlockBits;
        unsigned char *mainPtr;
        MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;

        if (!mp3DecInfo)
                return ERR_MP3_NULL_POINTER;

        /* unpack frame header */ // 解析帧包头
        fhBytes = UnpackFrameHeader(mp3DecInfo, *inbuf);
        if (fhBytes < 0)        
                return ERR_MP3_INVALID_FRAMEHEADER;                /* don't clear outbuf since we don't know size (failed to parse header) */ //不知道帧头无法解析 //
        *inbuf += fhBytes;
        
        
/* unpack side info */
        siBytes = UnpackSideInfo(mp3DecInfo, *inbuf);
        if (siBytes < 0)
        {
                MP3ClearBadFrame(mp3DecInfo, outbuf);
                return ERR_MP3_INVALID_SIDEINFO;
        }
       *inbuf += siBytes;
        *bytesLeft -= (fhBytes + siBytes);

        
        /* if free mode, need to calculate bitrate and nSlots manually, based on frame size */
        if (mp3DecInfo->bitrate == 0 || mp3DecInfo->freeBitrateFlag)
        {
                if (!mp3DecInfo->freeBitrateFlag)
                {
                        /* first time through, need to scan for next sync word and figure out frame size */
                        mp3DecInfo->freeBitrateFlag = 1;
                        mp3DecInfo->freeBitrateSlots = MP3FindFreeSync(*inbuf, *inbuf - fhBytes - siBytes, *bytesLeft);
                        if (mp3DecInfo->freeBitrateSlots < 0)
                        {
                                MP3ClearBadFrame(mp3DecInfo, outbuf);
                                return ERR_MP3_FREE_BITRATE_SYNC;
                        }
                        freeFrameBytes = mp3DecInfo->freeBitrateSlots + fhBytes + siBytes;
                        mp3DecInfo->bitrate = (freeFrameBytes * mp3DecInfo->samprate * 8) / (mp3DecInfo->nGrans * mp3DecInfo->nGranSamps);
                }
                mp3DecInfo->nSlots = mp3DecInfo->freeBitrateSlots + CheckPadBit(mp3DecInfo);        /* add pad byte, if required */
        }

        /* useSize != 0 means we're getting reformatted (RTP) packets (see RFC 3119)
         *  - calling function assembles "self-contained" MP3 frames by shifting any main_data
         *      from the bit reservoir (in previous frames) to AFTER the sync word and side info
         *  - calling function should set mainDataBegin to 0, and tell us exactly how large this
         *      frame is (in bytesLeft)
         */
        if (useSize)
        {
                mp3DecInfo->nSlots = *bytesLeft;
                if (mp3DecInfo->mainDataBegin != 0 || mp3DecInfo->nSlots <= 0)
                {
                        /* error - non self-contained frame, or missing frame (size <= 0), could do loss concealment here */
                        MP3ClearBadFrame(mp3DecInfo, outbuf);
                        return ERR_MP3_INVALID_FRAMEHEADER;
                }

                /* can operate in-place on reformatted frames */
                mp3DecInfo->mainDataBytes = mp3DecInfo->nSlots;
                mainPtr = *inbuf;
                *inbuf += mp3DecInfo->nSlots;
                *bytesLeft -= (mp3DecInfo->nSlots);
        }
        else
        {
                /* out of data - assume last or truncated frame */
                if (mp3DecInfo->nSlots > *bytesLeft)
                {
                        MP3ClearBadFrame(mp3DecInfo, outbuf);
                        return ERR_MP3_INDATA_UNDERFLOW;        
                }
                /* fill main data buffer with enough new data for this frame */
                if (mp3DecInfo->mainDataBytes >= mp3DecInfo->mainDataBegin)
                {
                        /* adequate "old" main data available (i.e. bit reservoir) */
                        memmove(mp3DecInfo->mainBuf, mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes - mp3DecInfo->mainDataBegin, mp3DecInfo->mainDataBegin);
                        memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBegin, *inbuf, mp3DecInfo->nSlots);


                        mp3DecInfo->mainDataBytes = mp3DecInfo->mainDataBegin + mp3DecInfo->nSlots;
                        *inbuf += mp3DecInfo->nSlots;
                        *bytesLeft -= (mp3DecInfo->nSlots);
                        mainPtr = mp3DecInfo->mainBuf;
                }

                else
                {
                        /* not enough data in bit reservoir from previous frames (perhaps starting in middle of file) */
                        memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes, *inbuf, mp3DecInfo->nSlots);
                        mp3DecInfo->mainDataBytes += mp3DecInfo->nSlots;
                        *inbuf += mp3DecInfo->nSlots;
                        *bytesLeft -= (mp3DecInfo->nSlots);
                        MP3ClearBadFrame(mp3DecInfo, outbuf);
                        return ERR_MP3_MAINDATA_UNDERFLOW;
                }
        }
        bitOffset = 0;
        mainBits = mp3DecInfo->mainDataBytes * 8;

        /* decode one complete frame */
       for (gr = 0; gr < mp3DecInfo->nGrans; gr++)
        {
                for (ch = 0; ch < mp3DecInfo->nChans; ch++)
                {
                       
/* unpack scale factors and compute size of scale factor block */
                        prevBitOffset = bitOffset;
                        offset = UnpackScaleFactors(mp3DecInfo, mainPtr, &bitOffset, mainBits, gr, ch);

                        sfBlockBits = 8*offset - prevBitOffset + bitOffset;
                        huffBlockBits = mp3DecInfo->part23Length[gr][ch] - sfBlockBits;
                        mainPtr += offset;
                        mainBits -= sfBlockBits;

                        if (offset < 0 || mainBits < huffBlockBits)
                        {
                                MP3ClearBadFrame(mp3DecInfo, outbuf);
                                return ERR_MP3_INVALID_SCALEFACT;
                        }

                        /* decode Huffman code words */
                        prevBitOffset = bitOffset;
                        offset = DecodeHuffman(mp3DecInfo, mainPtr, &bitOffset, huffBlockBits, gr, ch);

                        if (offset < 0)
                        {
                                MP3ClearBadFrame(mp3DecInfo, outbuf);
                                return ERR_MP3_INVALID_HUFFCODES;
                        }

                        mainPtr += offset;
                        mainBits -= (8*offset - prevBitOffset + bitOffset);

                }
                /* dequantize coefficients, decode stereo, reorder short blocks */
                if (Dequantize(mp3DecInfo, gr) < 0)
                {
                        MP3ClearBadFrame(mp3DecInfo, outbuf);
                        return ERR_MP3_INVALID_DEQUANTIZE;                        
                }

                /* alias reduction, inverse MDCT, overlap-add, frequency inversion */
                for (ch = 0; ch < mp3DecInfo->nChans; ch++)
                        if (IMDCT(mp3DecInfo, gr, ch) < 0)

                        {
                                MP3ClearBadFrame(mp3DecInfo, outbuf);
                                return ERR_MP3_INVALID_IMDCT;                        
                        }

                /* subband transform - if stereo, interleaves pcm LRLRLR */
                if (Subband(mp3DecInfo, outbuf + gr*mp3DecInfo->nGranSamps*mp3DecInfo->nChans) < 0)
                {
                        MP3ClearBadFrame(mp3DecInfo, outbuf);
                        return ERR_MP3_INVALID_SUBBAND;                        
                }
        }
       return ERR_MP3_NONE;
}
我仿真一直跟踪没有看到一个地方是输出PCM数据的就是你的outBuf缓存区,不知道为啥,是不是那里出错没有执行到,如果出错就会跳出这个函数的,我是整个函数顺利执行完成的
回复 支持 反对

使用道具 举报

发表于 2016-1-6 20:24:52 | 显示全部楼层
把程序的栈空间设置大一点
回复 支持 反对

使用道具 举报

发表于 2016-1-7 07:07:17 | 显示全部楼层
我昨天也开始学习这个MP3播放器了。比较复杂啊。呵呵。我测试了一下,教程的例程是可以正常播放MP3的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-7 09:01:46 | 显示全部楼层
flyleaf 发表于 2016-1-6 20:24
把程序的栈空间设置大一点

static uint8_t  buffer[1024*4];                         // 文件缓冲区
//static short   outBuf[2][2500];                            // PCM流缓冲,使用两个缓冲区
//static short   outBuf[2][4608];                            // PCM流缓冲,使用两个缓冲区
static short outBuf[2304 * 3];

栈空间我已经设置很大了,不知道为啥
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-7 09:06:28 | 显示全部楼层
qduwg 发表于 2016-1-7 07:07
我昨天也开始学习这个MP3播放器了。比较复杂啊。呵呵。我测试了一下,教程的例程是可以正常播放MP3的。

谢谢,不知道是不是我的代码问题,那你能帮我看看你的正确播放MP3输出PCM程序,PCM输出缓存区outBuf是在那一段代码开始写入的,我好重点查看写入的代码,
现在问题是我看了解码函数 MP3Decode(Mp3Decoder, &read_ptr, &bytes_left, outBuf, 0);都不知道在这个函数那个位置开始输出PCM的,都找不到根源
回复 支持 反对

使用道具 举报

发表于 2016-1-7 11:15:37 | 显示全部楼层
通过跟踪看到,这个PCM数据的缓冲区是通过memcpy函数来赋值的。参数是MP3DecInfo结构体的成员mainbuf。    *mp3DecInfo = (MP3DecInfo *)hMP3Decoder;
MP31.jpg


但是跟踪MP3DecInfo结构体初始化函数,发现没有源文件。不知道怎么把这个结构体初始化的。
最后跟踪到这里,#define        AllocateBuffers                STATNAME(AllocateBuffers)
不知道allocatebuffer是怎么调用的。
回复 支持 反对

使用道具 举报

发表于 2016-1-7 11:59:10 | 显示全部楼层
时光虫子 发表于 2016-1-7 09:01
static uint8_t  buffer[1024*4];                         // 文件缓冲区
//static short   outBuf[2][2500];                            // PCM流 ...

栈空间是在startup汇编启动文件里配置的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-7 16:17:57 | 显示全部楼层
flyleaf 发表于 2016-1-7 11:59
栈空间是在startup汇编启动文件里配置的

那估计我估计我搞错了,我在看看,谢谢了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-7 16:21:27 | 显示全部楼层
flyleaf 发表于 2016-1-7 11:59
栈空间是在startup汇编启动文件里配置的

我是直接用3.5库里面的启动代码
回复 支持 反对

使用道具 举报

发表于 2016-1-7 16:38:47 | 显示全部楼层
时光虫子 发表于 2016-1-7 16:21
我是直接用3.5库里面的启动代码

你对比一下我们的mp3例程的启动代码和你自己写的mp3工程的启动代码,栈空间不一样的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-7 17:10:14 | 显示全部楼层
qduwg 发表于 2016-1-7 11:15
通过跟踪看到,这个PCM数据的缓冲区是通过memcpy函数来赋值的。参数是MP3DecInfo结构体的成员mainbuf。     ...

再次感谢你的回答,你用红色横线标识的位置,我的程序也执行到那里了,这里应该不是输出PCM数据,我看了mainBuf缓存区在这里写入381个数据,这个
数据是第一帧数据主数据,去掉FF FB 90 64 这个帧头 + 32个帧边信息,mainBuf缓存区里面的数据就主数据,刚好是一帧数据 = (417 + 调整) - 帧头4byte + 帧边32byte
Outbuf缓存区还是没有数据的,
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-7 17:11:57 | 显示全部楼层
qduwg 发表于 2016-1-7 11:15
通过跟踪看到,这个PCM数据的缓冲区是通过memcpy函数来赋值的。参数是MP3DecInfo结构体的成员mainbuf。     ...

#define        AllocateBuffers                STATNAME(AllocateBuffers)


我跟踪了,发现在buffers.c   
MP3DecInfo *AllocateBuffers(void)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-7 18:24:36 | 显示全部楼层
flyleaf 发表于 2016-1-7 16:38
你对比一下我们的mp3例程的启动代码和你自己写的mp3工程的启动代码,栈空间不一样的

                                                
; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

                PRESERVE8
                THUMB

我是用了你们的启动文件
回复 支持 反对

使用道具 举报

发表于 2016-1-8 15:50:25 | 显示全部楼层
时光虫子 发表于 2016-1-7 18:24
;  Heap Configuration
;     Heap Size (in Byte ...

你所指的PCM数据,是MP3文件里面的原始主数据呢还是经过解码之后的那个数据呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-8 17:26:07 | 显示全部楼层
qduwg 发表于 2016-1-8 15:50
你所指的PCM数据,是MP3文件里面的原始主数据呢还是经过解码之后的那个数据呢?

是解码输出来的数据,我现在的程序里面就不知道MP3输出的PCM数据在那里,火哥的MP3解码程序,输出PCM数据是在outBuf缓存区但是我的没有输出没有数据

        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;
        }
回复 支持 反对

使用道具 举报

发表于 2016-1-8 18:38:00 | 显示全部楼层
时光虫子 发表于 2016-1-8 17:26
是解码输出来的数据,我现在的程序里面就不知道MP3输出的PCM数据在那里,火哥的MP3解码程序,输出PCM数据 ...

请问你的例程运行的正常不?就是能播放出来MP3吗?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-9 08:31:33 | 显示全部楼层
qduwg 发表于 2016-1-8 18:38
请问你的例程运行的正常不?就是能播放出来MP3吗?

运行正常,程序直接执行到输出PCM函数,我没有喇叭,我是直接仿真看有没有输出PCM数据的,我程序里面没有输出PCM,outBuf缓存区没有数据不知道为啥,问题就是不知道程序
是在那个函数开始对这个outBuf写入数据的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-9 10:38:55 | 显示全部楼层
qduwg 发表于 2016-1-8 18:38
请问你的例程运行的正常不?就是能播放出来MP3吗?

我想知道你程序里面的MP3解码输出PCM是不是在outBuf双缓存区里面,如果是的话我还想知道这个outBuf双缓冲是在那个函数开始写如数据的,先谢谢!
回复 支持 反对

使用道具 举报

发表于 2016-1-10 22:19:34 | 显示全部楼层
时光虫子 发表于 2016-1-9 10:38
我想知道你程序里面的MP3解码输出PCM是不是在outBuf双缓存区里面,如果是的话我还想知道这个outBuf双缓冲 ...

老弟,我已经找到问题的根本了哦。今天通过跟踪终于发现了写到outbuf的函数了。竟然是用thumb写的代码。全是汇编的啊。哈哈。


MP3解码算法1.jpg

MP3解码算法2.jpg

MP3解码算法3.jpg

MP3解码算法4.jpg





回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-12 08:33:36 | 显示全部楼层
qduwg 发表于 2016-1-10 22:19
老弟,我已经找到问题的根本了哦。今天通过跟踪终于发现了写到outbuf的函数了。竟然是用thumb写的代码。 ...

非常感谢!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-13 08:40:57 | 显示全部楼层
qduwg 发表于 2016-1-10 22:19
老弟,我已经找到问题的根本了哦。今天通过跟踪终于发现了写到outbuf的函数了。竟然是用thumb写的代码。 ...

非常感谢哥们你的热心帮助,我仿真看了,程序也执行到了你那一步,就是没有数据输出,我换了个MP3结果有数据输出,不知道是不是我的语音文件问题,
你能帮我附件里面的MP3解码看看吗http://pan.baidu.com/s/1skgaI4X
看看是不是语音文件问题
回复 支持 反对

使用道具 举报

发表于 2016-1-13 10:31:56 | 显示全部楼层
时光虫子 发表于 2016-1-13 08:40
非常感谢哥们你的热心帮助,我仿真看了,程序也执行到了你那一步,就是没有数据输出,我换了个MP3结果有 ...

我抽空给你看看昂。呵呵。有的MP3文件不是很规范的哦。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-13 17:38:15 | 显示全部楼层
qduwg 发表于 2016-1-13 10:31
我抽空给你看看昂。呵呵。有的MP3文件不是很规范的哦。

万分感谢!
回复 支持 反对

使用道具 举报

发表于 2016-1-14 08:16:30 | 显示全部楼层
本帖最后由 qduwg 于 2016-1-14 09:20 编辑
时光虫子 发表于 2016-1-13 08:40
非常感谢哥们你的热心帮助,我仿真看了,程序也执行到了你那一步,就是没有数据输出,我换了个MP3结果有 ...


老兄你好,我今天经过跟踪测试,发现你的MP3文件是好的啊。完全没有问题可以解压缩出来PCM。请参考下图。您这是搞一个公交报站系统啊?哈哈。需要手动操作一个按钮,然后才能报站?每到一站都需要司机按一下按钮吗?我看我们这里的公交车都是自动的呢?不知道是靠GPS还是什么来判断到站标志。


解压缩MP3获得PCM3.jpg

PS:能不能改一下你的头像?有点像小哥,吓人啊。


回复 支持 反对

使用道具 举报

发表于 2016-1-14 08:55:05 | 显示全部楼层
我怎么突然发现你这个MP3_PLAYER函数跟我的有点不太一样啊?你是用的哪个版本的函数?我是ISO-V2里面C盘例子里面的函数。你是什么地方函数?奇怪了。文件打开调用的函数不同啊。你比较一下看看。

static void mp3_player(char *filename)
{
  char utfcode_buf[100];
        int err, i, outputSamps, current_sample_rate = 0;                                       
        HMP3Decoder                Mp3Decoder;                                                  /* mp3解码器指针                */
  FIL name_file;
  char music_name[MUSIC_NAME_LEN];       
  
  int        read_offset = 0;                                /* 读偏移指针                                */
  int        bytes_left = 0;                                        /* 剩余字节数                                */       
  read_ptr = buffer;                            /* 缓冲区指针*/
  
  f_open (&name_file, "0:mp3player/lcdlist.txt", FA_READ);
  
  fres = f_lseek (&name_file, play_index*FILE_NAME_LEN);                        //文件中的歌曲名按FILE_NAME_LEN来偏移

  fres = f_read(&name_file, music_name, MUSIC_NAME_LEN, &rw_num);                //只读取MUSIC_NAME_LEN长度的字符,太长的话LCD不够空间显示

  //在中上的位置显示新的正在播放的歌曲
  music_name[MUSIC_NAME_LEN-1]='\0';                                                                                                //把最后一个元素设置为'\0'防止没有结束符号而溢出

  LCD_Add_ChEn(music_name,utfcode_buf); //转换汉字为UTF8码查表法
  
  TEXT_SetText(hText[0],utfcode_buf);
  
  //帧数初始化为0
  Frames=0;
  //打开音频文件
        fres = f_open (&file, filename, FA_READ );
  
  //打开失败,回到音乐扫描主程序
        if (fres!=FR_OK)
        {
                printf("read file %s error  ! open another file\r\n",filename);
                fres = f_close (&file);
               
                if (++play_index>=file_num)        //索引值加1
                {
                                play_index=0;                                                //归0,所以如果所有文件都打开失败会一直循环
                }                               
                return ;                                                                                //文件无法打开,终止解码。进入下一次循环,读取下一个文件
        }

  //打开成功
  //初始化MP3解码器
        Mp3Decoder = MP3InitDecoder();
  
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-1-14 12:36:52 | 显示全部楼层
qduwg 发表于 2016-1-14 08:16
老兄你好,我今天经过跟踪测试,发现你的MP3文件是好的啊。完全没有问题可以解压缩出来PCM。请参考下图 ...

嗯,真的非常非常感谢,我在找找问题,
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-24 12:13 , Processed in 0.046706 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表