OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3632|回复: 3

音乐播放器 VS1053

[复制链接]

10

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2017-8-4
在线时间
45 小时
发表于 2017-9-2 16:43:03 | 显示全部楼层 |阅读模式
5金钱
我用的是原子哥战舰板的音乐播放器的源码,解码芯片是VS1053,现在问题是WAV码率和歌曲总时长不对,,该怎么解决?@正点原子

我看了码率是通过读取HEAD1和HEAD0寄存器计算出来的,寄存器只有16位,也就是最高显示65535*8=524Kbps.而WAV码率为1411Ksps。

难道VS1053就不能正确显示WAV格式的码率了吗? 应该怎么解决?
UC截图20170902163637.png

最佳答案

查看完整内容[请看2#楼]

这个没法了 ,受性能所限
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

109

主题

5564

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
10572
金钱
10572
注册时间
2017-2-18
在线时间
1914 小时
发表于 2017-9-2 16:43:04 | 显示全部楼层
这个没法了 ,受性能所限
回复

使用道具 举报

10

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
173
金钱
173
注册时间
2017-8-4
在线时间
45 小时
 楼主| 发表于 2017-9-4 08:48:17 | 显示全部楼层
peng1554 发表于 2017-9-2 16:43
这个没法了 ,受性能所限

还有其他实现的方式吗?
回复

使用道具 举报

3

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
147
金钱
147
注册时间
2018-11-19
在线时间
40 小时
发表于 2018-12-10 11:32:10 | 显示全部楼层
//下面的代码是从网上找的音频软解码的程序里扣出来的,分析了以下flac的数据格式,可以获取准确的音频时长等信息
///////////////////////////////////////////////
//以下代码放在mp3player.h里
//保存FLAC文件信息
typedef struct FLACContext
{
        u8 channels;            //声道数
        u8 bps;         //采样位数       
        u16 samplerate;                //采样率
        u32 totalsamples; //全部音频样本数
  u32 filesize;            //总文件大小
        u32 bitrate;      //比特率
        u32 metadatalength;//文件信息块总长度
}FLAC_Information;

//声明函数
u8 get_flac_information(FIL *file, FLAC_Information *fc);


////////////////////////////////////////////////////////////////////
//以下代码放在mp3player.c里
//获取flac文件信息
u8 get_flac_information(FIL *file, FLAC_Information *fc)
{
        u16 minutes, seconds;
        u8 found_streaminfo = 0;
  u8 endofmetadata = 0;
  u16 blocklength;
  unsigned int br;
  u8 *buf;
  u32 *p;
       
  buf = mymalloc(SRAMIN,256);//存储 文件信息描述块 的信息
  if(!buf)return 0;                        //内存申请失败
       
  //判断是否为flac文件
  f_read(file, buf, 4, &br); //首次读取打开的文件前4个字节的数据
  if(br < 4)//读取失败
  {
    myfree(SRAMIN,buf);
    return 0;
  }
  if (memcmp(buf, "fLaC", 4) != 0) //flac文件中前四个字节为"fLaC"注意区分大小写
  {
    myfree(SRAMIN,buf);
    return 0;//文件出错
  }
       
  fc->metadatalength = 4; //记录 文件信息描述块 总长度  当前值4
       
        //循环读取 文件信息描述块 的信息
  while (!endofmetadata)
  {
                        f_read(file, buf, 4, &br);//继续读取四个4字节的数据
                        if (br < 4) //文件读完了,但是没有找到 文件信息描述块 结束标志,返回0(出错)
                        {
                                        myfree(SRAMIN,buf);
                                        return 0;
                        }
                       
                        endofmetadata = (buf[0] & 0x80);//判断 文件信息描述块 结束标志(1xxx xxxx)
                       
                        blocklength = (buf[1] << 16) | (buf[2] << 8) | buf[3];//得到这个文件信息块的长度       
                       
                        //记录 文件信息描述块 总长度
                        fc->metadatalength += blocklength + 4;

                        //分析文件信息块
                        if ((buf[0] & 0x7f) == 0)// 0 is the STREAMINFO block //低7位为0,则表示是STREAMINFO块 x000 0000
                        {
                                        f_read(file, buf, blocklength, &br); //读取这个blocklength长度数据
                                        if(br == 0) //读取失败
                                        {
                                                myfree(SRAMIN,buf);
                                                return 0;
                                        }       
                                       
                                        //提取flac文件参数
                                        //文件总长度
                                        fc->filesize = file->fsize;
                                        //采样率
                                        fc->samplerate = (buf[10] << 12) | (buf[11] << 4)         |  ((buf[12] & 0xf0) >> 4);
                                        //声道数
                                        fc->channels = ((buf[12] & 0x0e) >> 1) + 1;
                                        //位率
                                        fc->bps = (((buf[12] & 0x01) << 4) | ((buf[13] & 0xf0) >> 4) ) + 1;
                                        //全部样本数
                                        fc->totalsamples = (buf[14] << 24) | (buf[15] << 16) |  (buf[16] << 8) | buf[17];
                                        //比特率       [(总文件大小-文件信息描述块总长度 = 有效的音频数据)*8 ] = 有效音频数据总bit数   
                                        fc->bitrate = ((fc->filesize - fc->metadatalength) * 8) / ((fc->totalsamples / fc->samplerate) * 1000);   //[(bit/音频时长=比特率)/1000 ]= Kbs

                                        //全部样本数/采样率=音频总时长 totalsamples/samplerate  
                                        seconds  = fc->totalsamples / fc->samplerate;
                                        minutes  = seconds / 60;
                                        seconds %= 60;
                                       
                                        found_streaminfo = 1;  //标记找到了 STREAMINFO block
                        }
                        else // Skip to next metadata block 剩下的都是无需分析的块,只记录长度就好
                        {                               
                                        f_lseek(file, file->fptr + blocklength); //移动读写指针到fptr + blocklength
                                        if(file->fptr >= file->fsize)  //指针长度超过文件大小,文件错误
                                        {
                                                myfree(SRAMIN,buf);
                                                return 0;
                                        }
                        }
        }
       
        if (found_streaminfo) //找到了 STREAMINFO block
        {
                                               
                        printf("------------------------------\r\n");
                        printf("文件信息描述块长度: %d \r\n", fc->metadatalength);
                        printf("样本数           : %d\r\n", fc->totalsamples);
                        printf("采样率           : %d\r\n", fc->samplerate);
                        printf("位数             : %d\r\n", fc->bps);                       
                        printf("比特率           : %d Kbps \r\n", fc->bitrate);//比特率/码率
                        printf("时长             : %d%d:%d%d\r\n\n",minutes/10,minutes%10,seconds/10,seconds%10);
                        printf("声道             : ");
                        switch(fc->channels)
                        {
                                case 1:
                                        printf("单声道");//printf("Mono");
                                break;
                               
                                case 2:
                                        printf("立体声");//printf("Stereo");
                                break;                       
                               
                                default:
                                        printf("%d Channels\r\n", fc->channels);
                                break;
                        }
                        myfree(SRAMIN,buf);
                        return 1;//成功
  }
        myfree(SRAMIN,buf);//失败
        return 0;  
}



///////////////////////////////////////////////////
对原子哥的mp3_play_song的程序有一点修改
//播放一曲指定的歌曲                                                                                                                                     
//返回值:0,正常播放完成
//                 1,下一曲
//       2,上一曲
//       0XFF,出现错误了
u8 mp3_play_song(u8 *pname)
{         
                FLAC_Information* fc;       
                FIL* fmp3;
                u16 br;
                u8 res,rval=0;          
                u8 *databuf;                             
                u16 i=0;
                u8 key;              
         
                fmp3=(FIL*)mymalloc(SRAMIN,sizeof(FIL));//申请内存
                databuf=(u8*)mymalloc(SRAMIN,4096);                //开辟4096字节的内存区域
                if(databuf==NULL||fmp3==NULL)rval=0XFF ;//内存申请失败.
               
                if(rval==0)
                {          
                                VS_Restart_Play();                                          //重启播放 (切歌)
                                VS_Set_All();                                                //设置音量、音效等信息                          
                                VS_Reset_DecodeTime();                                //复位解码时间           
                                res=f_typetell(pname);                                  //得到文件类型(大类 小类 XXXX xxxx)                                                                                     
                               
                                if(res==0x4c)//如果是flac,获取歌曲信息,之后加载patch
                                {                                                       
                                                res=f_open(fmp3,(const TCHAR*)pname,FA_READ);//打开pname路径指向的文件 FA_READ-打开方式只读       
                                                if(res==0)//打开成功.
                                                {
                                                                fc=(FLAC_Information*)mymalloc(SRAMIN,sizeof(FLAC_Information));//申请内存
                                                                get_flac_information(fmp3, fc);        //获取flac文件重要数据                                                                               
                                                                myfree(SRAMIN,fc);       
                                                                f_close(fmp3);//关闭当前文件
                                                }
                                                //加载patch
                                                VS_Load_Patch((u16*)vs1053b_patch,VS1053B_PATCHLEN);               
                                }
                               
                                res=f_open(fmp3,(const TCHAR*)pname,FA_READ);//打开pname路径指向的文件 FA_READ-打开方式只读       
                                if(res==0)//打开成功.
                                {
                                                VS_SPI_SpeedHigh();        //设置SPI高速                                                  
                                                while(rval==0)
                                                {  
                                                                //如果要读的数据大于剩余大小,要读的出数据br就等于剩余数据大小         
                                                                res=f_read(fmp3,databuf,4096,(UINT*)&br);//每次读出4096个字节
                                                                i=0;
                                                                do//主播放循环
                                                                {         
                                                                                if(VS_Send_MusicData(databuf+i)==0)//判断VS10XX是否需要数据,如果是,发送32字节的音频数据
                                                                                {
                                                                                                i+=32;
                                                                                }
                                                                                else //发送完数据需要等VS10XX处理,VS10XX不需要接受数据了,这时可以检测按键  
                                                                                {
                                                                                                key=KEY_Scan(0);
                                                                                                switch(key)
                                                                                                {
                                                                                                                case KEY0_PRES:
                                                                                                                                rval=1;                //下一曲
                                                                                                                break;
                                                                                                                case KEY2_PRES:
                                                                                                                                rval=2;                //上一曲
                                                                                                                break;
                                                                                                                case WKUP_PRES:        //音量增加
                                                                                                                                if(vsset.mvol<250)
                                                                                                                                {
                                                                                                                                                vsset.mvol+=5;
                                                                                                                                                VS_Set_Vol(vsset.mvol);        //设置音量(函数里循环等待数据请求引脚有效)
                                                                                                                                }
                                                                                                                                else
                                                                                                                                                vsset.mvol=250;
                                                                                                                                mp3_vol_show((vsset.mvol-100)/5);        //音量限制在:100~250,显示的时候,按照公式(vol-100)/5,显示,也就是0~30   
                                                                                                                break;
                                                                                                                case KEY1_PRES:        //音量减
                                                                                                                                if(vsset.mvol>100)
                                                                                                                                {
                                                                                                                                        vsset.mvol-=5;
                                                                                                                                        VS_Set_Vol(vsset.mvol);                //设置音量(函数里循环等待数据请求引脚有效)
                                                                                                                                }
                                                                                                                                else
                                                                                                                                                vsset.mvol=100;
                                                                                                                                mp3_vol_show((vsset.mvol-100)/5);        //音量限制在:100~250,显示的时候,按照公式(vol-100)/5,显示,也就是0~30   
                                                                                                                break;
                                                                                                }
                                                                                                mp3_msg_show(fmp3->fsize);//显示播放时间,比特率 信息          fmp3->fsize-文件总大小   
                                                                                }                        
                                                                }while(i<4096);//循环发送4096个字节
                                                               
                                                                if(br!=4096||res!=0)//读完了(已经发送完了数据) 或者操作按键了
                                                                {
                                                                        rval=0;
                                                                        break;
                                                                }                                                          
                                                }
                                                f_close(fmp3);//关闭当前文件
                                }
                                else
                                                rval=0XFF;//出现错误                     
                }                                                              
                myfree(SRAMIN,databuf);                                                 
                myfree(SRAMIN,fmp3);
                return rval;                                                 
}
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-22 13:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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