AVR32B0256软件解码MP3论证 helix方案
没做过,总觉得MP3解码应该是很简单的事情,还有过用AVR解MP3的想法,现在看来真正的觉得可笑。查了一些关于软件解MP3的资料,决定用helix 方案试一下,让我们算一下用helix 解MP3最少要多少的资源:
1.MP3是一帧为单位进行解码,也就是说,必须至少读入一帧的数据以准备解码,一帧有多少的数据呢?看看:
数据帧大小:
FrameSize = (((MpegVersion == MPEG1 ? 144 : 72) * Bitrate) / SamplingRate) + PaddingBit
例如: Bitrate = 128000, a SamplingRate =44100, and PaddingBit = 1
FrameSize = (144 * 128000) / 44100 + 1 = 417 bytes
也就是说,想解码一个比特率为128K,采样率为44.1K的MP3文件,最少一次读入内存417 bytes 以准备解码。
2.helix 在运行解码程序的时候要24K的RAM内存,这个是官方给的数据这个就是最大的门槛
3.解码输出,这个也是要内存的,别告诉我你一输出就直接给DAC不用缓冲区,这个是跑不掉的,要多少呢,
PCM音频信号进行MP3压缩时,以1152个PCM采样值为单位,封装成具有固定长度的MP3数据帧。
在解码时,利用数据帧里的信息可以恢复出1152个PCM采样值
也就是说,helix 在进入一帧解码完成后,会输出1152个PCM数据,这个是16位的用于直接输出到DAC的数据
算一下,现在要多少内存了,假设我们想解码320K码率的MP3文件,那么按上面的算,我们至少要:
1047 + 24k + 1152 bytes = 26.2K
等等,这里还没有算上文件系统FAT还有堆栈占用的内存呢,那它们到底还要多少呢?
什么都别说,单是堆栈,在进入如些复杂的DSP运算,为了保证程序的可靠运行,官方建议4K ,综合以上,已用30.2K
到这里,AVR32B0256还剩下多少内存呢,我们知道这个片子有片内RAM 32K那还有32-30.2=1.8K的内存
我的天呀,似乎刚刚好。。。
----------------------------------------------------------------------------------------------------- 上传一下用helix方案 做的MP3,已经做成了,使用:
AVR32B112832KRAM 用PWM做DAC输出,定时器产生时序,中断里修改PWM值以输出PCM数据。
国外牛人用B1128做的MP3电路图和程序包ourdev_588129R4IGPT.zip(文件大小:1.50M) (原文件名:UC3B-MP3.zip) avrfreaks上有人用UC3B1256做出来了,也是用HELIX解码的 嗯,是的,我贴的压缩包就是从avrfreaks上下载来的,里面有完整的电路和工程目录, 楼主 PWM DAC 效果怎么样?
是1K、255K电阻RC网络,分别两个8-bit PWM组合成16-bit的方案吗?
我去年测试了下这样的pwm dac,效果奇差,基本上只能听到而已。不晓得哪里误了。 LS,
是1K、255K电阻RC网络,分别两个8-bit PWM组合成16-bit的方案,这样的DAC有噪音是跑不掉的,只能用来验证软件解码是否成功
但是我没有用PWMDAC,硬件方面,我使用了:
WM8978 CODEC,这个芯片工作在主模式,自动产生MCLK时序,不需要AVR32用另外的时钟来产生时序。
使用TWI总线来设置 WM8978 的采样率和音量。
电路参考了,RT-Thread 网络收音机。 哦,原来这样,明白。
atmel的SSC还是很好用的,灵活配置成 I2S、AC97、PCM 等各种帧格式,接codec,绝对秒杀NXP、ST、LM3S。 回复【6楼】huatuizh
哦,原来这样,明白。
atmel的ssc还是很好用的,灵活配置成 i2s、ac97、pcm 等各种帧格式,接codec,绝对秒杀nxp、st、lm3s。
-----------------------------------------------------------------------
在玩AVR32的表示对其SSC外设很满意.搭配PDCA使用一个字爽 经过几天的努力,终于做好了。
http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_590618T4L1O9.jpg
B0256+CODEC+SD (原文件名:SAM_0387.jpg)
http://cache.amobbs.com/bbs_upload782111/files_34/ourdev_590619URCF2A.jpg
正在播放...320Kbps@44100 (原文件名:SAM_0391.jpg) 授之以鱼不如授之以渔。
下面简单讲一下使用helix进行软解MP3的大概流程。
1.首先找到MP3格式的文件,这个需要文件系统的协助,我的代码使用了SOFTWARE_FRAMEWORK里面的文件系统
直接通过
if(nav_file_checkext((FS_STRING)"MP3"));进行判断这个文件的后缀是否是MP3文件夹
2.读取文件,找到MP3的帧起始标志,这个helix已经帮我们写好了
/**************************************************************************************
* Function: MP3FindSyncWord
*
* Description: locate the next byte-alinged sync word in the raw mp3 stream
*
* Inputs: buffer to search for sync word
* max number of bytes to search in buffer
*
* Outputs: none
*
* Return: offset to first sync word (bytes from start of buf)
* -1 if sync not found after searching nBytes
**************************************************************************************/
int MP3FindSyncWord(unsigned char *buf, int nBytes)
这个子程序的输入unsigned char *buf 是指读入文件数据的起始指针,
int nBytes 这个是指输入缓冲区的大小。
3.找到帧同步后就可以调用MP3Decode 来进行解码了
4.解码完成后,得到的PCM数据会存放在outBuf[] 这个缓冲区里面 详见SUBBAND.c
5.把得到的PCM数据输出到DAC。 伸个爪子学习, 谢谢! 感兴趣的可以一起讨论,我现在正尝试修改源码,以播放U盘里的MP3文件。
SOFTWARE_FRAMEWORK 的FAT文件系统不能同时打开两个文件,所以不能打开字库文件以支持中文显示,郁闷~~
做好了,公布代码,同时详细说明一下整个MP3工作流程 算一下,现在要多少内存了,假设我们想解码320K码率的MP3文件,那么按上面的算,我们至少要:
1047 + 24k + 1152 bytes = 26.2K
~~~~~~~~~~1152是MP3一帧的采样数,常见的双声道、16bit采样MP3一帧解出来的PCM数据是4608Bytes,开两个buffer就是8216Bytes!
MP3解码速度不是问题,跑5xMHz的44B0就能搞定,关键在于RAM要够,类似问题对于FLAC和WMA都存在。 以前我也想移植MP3解码进CM3,就查了以下几种
mpg123(mpg321)公认声音是最好的(MP3解码器),但是我记得以前看的时候发现里面带了SRC......内存占用很大。
libmad,这个调试了下,不知道为何解不成功。
helix,这个是real公司的代码吧,我记得好象是。 回复【11楼】lisn3188 龙南
感兴趣的可以一起讨论,我现在正尝试修改源码,以播放u盘里的mp3文件。
software_framework 的fat文件系统不能同时打开两个文件,所以不能打开字库文件以支持中文显示,郁闷~~
做好了,公布代码,同时详细说明一下整个mp3工作流程
-----------------------------------------------------------------------
每个NAV只能打开一个文件,但是你可以同时有多个NAV,迂回实现打开多个文件 helix代码比libmad小很多,不过helix是16位的,libmad是24位的,估计helix对几个常量表做了简化。
STM32 Radio项目就是用helix的,72M CM3解320k MP3大概占60-70%。 回复【15楼】gzhuli咕唧霖
helix代码比libmad小很多,不过helix是16位的,libmad是24位的,估计helix对几个常量表做了简化。
stm32 radio项目就是用helix的,72m cm3解320k mp3大概占60-70%。
-----------------------------------------------------------------------
移植到汇编也许会快点。
做一台功能类似D50(仅放音)的机器出来也不是没可能的。
话说D50的LCD好象是STN的点阵? 回复【16楼】90999 张耀扬
-----------------------------------------------------------------------
helix的核心部分已经是汇编的了,目前这个效能已经比较合理。AVR32官方的UC3A0512 demo是用libmad的,精度也是裁剪为16位。
类似D50的机器,MP3貌似可有可无吧,集中火力处理APE和FLAC更好。 是么,我去看看。 回复【17楼】 gzhuli 咕唧霖
---------------------------------------
APE需要占用系统更高频率和更大数据处理量的浮点运算, AVR32浮点运算可行吗? libmad用过,蛮方便的。 回复【8楼】lisn3188龙南
-----------------------------------------------------------------------
这个显示屏的效果很不错,,字体也很好看,, 显示屏是OLED吧 回复【19楼】piccode
回复【17楼】 gzhuli 咕唧霖
---------------------------------------
ape需要占用系统更高频率和更大数据处理量的浮点运算, avr32浮点运算可行吗?
-----------------------------------------------------------------------
其实一直很奇怪,是谁说APE需要浮点运算的?连MP3都能用整形运算解码,APE会在哪里需要用浮点?而且理论上看,用浮点运算会有精度损失问题,难以保证无损吧。
我看官方的SDK,除了计算播放进度之类的无关紧要功能外,暂时没看到核心部分用浮点运算的,有知道的麻烦帮忙指出具体在哪个文件的哪一行,大家一起看看能不能改成整形的。 回复【22楼】piccode
显示屏是oled吧
-----------------------------------------------------------------------
蛮多坏的mp3上面都有这个oled的,单买oled也不贵,
老外很喜欢用oled。。
谁能做一个支持mp3,wma,aac/m4a的解码库,就牛叉大发了,,,比较非主流的ogg,和asf就算了吧。rm不开源也算了。高端的ape,flac,wav基本上也不太指望能解码了。
要是都能支持?估计有人说不如买现成的产品了,,少了很多乐趣啊。 回复【24楼】reloaded 电子浪人
回复【22楼】piccode
显示屏是oled吧
-----------------------------------------------------------------------
谁能做一个支持mp3,wma,aac/m4a的解码库,就牛叉大发了,,,比较非主流的ogg,和asf就算了吧。rm不开源也算了。高端的ape,flac,wav基本上也不太指望能解码了。
-----------------------------------------------------------------------
主要是内存问题,单片机内存太小,做起来很麻烦。如果上ARM9,那直接用Linux就啥都有了,也没必要自己折腾。
APE, FLAC, WAV很高端么?WAV完全不需要解码呀。 内存几个办法外挂SRAM
或者用B0512 96K SRAM..... 大师,不好意思,还真不知道wav不要解码,,业余玩家见谅见谅~~~
arm9核心板也得250吧~~还不算布线的人工费~~(鉴于自己不会画多层板和使用pads)
~~~还不算学习linux系统的时间
以前有用7s64做的wav解码器,好像是哪位大虾的作品来着,,
现在64kram的mcu也就40元左右,96kram没仔细找过,128kram貌似就要70元++了。。
算算貌似也快到200了一共(加制版费的话)
回复【25楼】gzhuli咕唧霖
回复【24楼】reloaded 电子浪人
回复【22楼】piccode
显示屏是oled吧
-----------------------------------------------------------------------
谁能做一个支持mp3,wma,aac/m4a的解码库,就牛叉大发了,,,比较非主流的ogg,和asf就算了吧。rm不开源也算了。高端的ape,flac,wav基本上也不太指望能解码了。
-----------------------------------------------------------------------
主要是内存问题,单片机内存太小,做起来很麻烦。如果上arm9,那直接用linux就啥都有了,也没必要自己折腾。
ape, flac, wav很高端么?wav完全不需要解码呀。
----------------------------------------------------------------------- 回复【23楼】 gzhuli 咕唧霖
---------------------------------------------
http://www.monkeysaudio.com/developers.html上面的好像是浮点运算进入处理,没有细看
有没有谁有移植好的APE Library? (不知有没有其它的source code)
回复【26楼】 kingofkings 技术火
------------------------
内存几个办法外挂SRAM
或者用B0512 96K SRAM.....
------------------------------------
也不是做市场卖方案,自已玩的话APE/FLAC 其中之一就行了,WAV的话功耗还能下来呢, PIC32自已就有128K RAM 楼住的屏在那买的,是少脚位的话给个连接好不? 哇,好多大牛都出来了。。。
【12楼】 ForNever
谢谢你的指正,MP3一帧的采样数确实是1152个,解码出来的缓冲区必须要1152*2 bytes
【14楼】 mowin 雾湾
谢谢你的指点,可是多个NAV 是如何创建呢,迂回打开文件后会不会是从文件的起始打开?
【29楼】 piccode
屏是TAOBAO上买的。30个脚,关键字:“0.96寸 OLED”自己搜一下就出来了 举例说明吧
enum {
NAV_ID_0 = 0,
NAV_ID_1
}
在NAV_ID_0打开file_name_0
nav_select(NAV_ID_0);
nav_drive_set(nav_drive_nb() -1);
nav_partition_mount();
nav_checkdisk_disable(); /* Skip fat_check_device() for every read */
nav_filelist_reset();
nav_filelist_findname("file_name_0", FALSE));
file_open(FOPEN_MODE_R);
在NAV_ID_1打开file_name_1
nav_select(NAV_ID_1);
nav_drive_set(nav_drive_nb() -1);
nav_partition_mount();
nav_checkdisk_disable(); /* Skip fat_check_device() for every read */
nav_filelist_reset();
nav_filelist_findname("file_name_1", FALSE));
file_open(FOPEN_MODE_R);
读file_name_0
nav_select(NAV_ID_0);
file_seek(offset, FS_SEEK_SET);
file_read_buf(buf, BYTE_CNT);
读file_name_1
nav_select(NAV_ID_1);
file_seek(offset, FS_SEEK_SET);
file_read_buf(buf, BYTE_CNT);
以上是菜鸟代码,望大牛斧正,谢谢 mark mark,好贴,学习了 MP3论证 helix方案 这个应该是不用DSP的吧,怎么样把内部DSP利用起来呢? 回复【35楼】xiaob135 快乐青春
这个应该是不用dsp的吧,怎么样把内部dsp利用起来呢?
-----------------------------------------------------------------------
同问, 怎么把内部的DSP用于MP3解码呢? AVR32没有“内部DSP”,只有DSP指令,编译器支持就可以了。 mark 楼主,我的MP3 mp3FrameInfo.version=1 无法播放??
如果删掉声音断断续续.........
// check if this is really a valid frame
// (the decoder does not seem to calculate CRC, so make some plausibility checks)
if (MP3GetNextFrameInfo(hMP3Decoder, &mp3FrameInfo, read_ptr) == 0 &&
mp3FrameInfo.nChans == 2 &&
mp3FrameInfo.version == 0) {
debug_printf("Found a frame at offset %x\n", offset + read_ptr - mp3buf + mp3file->fptr);
} else {
puts("this is no valid frame");
// advance data pointer
// TODO: handle bytes_left == 0
assert(bytes_left > 0);
bytes_left -= 1;
read_ptr += 1;
return 0;
} 好像很占内存呀,我编译后的结果如下,楼主编译结果怎样呀?
http://cache.amobbs.com/bbs_upload782111/files_42/ourdev_653008TF4Q2D.jpg
编译结果 (原文件名:未命名.jpg)
文件缓冲区我设置单位 char buffer; // file copy buffer 回复【楼主位】lisn3188龙南
-----------------------------------------------------------------------
我关心功耗咋样? 正在学习,工作中要移植MP3解码。 很好。很强大 。。 mark!正打算做个mp3玩玩!
页:
[1]