8933|6

32

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

基于libmad的音频软解码 [复制链接]

解码后的数据如下:
大家还是尽量下载附件查看。帖子里面好多格式都乱了……我再慢慢改吧。
一、前期准备
移植libmad之前必须先调通SD卡硬件驱动,学会使用znFAT的基本读数据功能(参考znFAT实例之“08文件定位读取数据”)。
Libmad原来是在Linux下面使用的,我们需要做一些修改:
1.      删除minimad.c/version.c/version.h等没有用到的文件
2.      由于znfat中有一个config文件,libmad也有一个config文件,我们将libmad的config改为libmad_config.h,避免冲突。然后将libmad中#include config.h 全部改为 #include libmad_config.h
由于我们没有abort这个函数,所以我们需要在global.h将do { if (!(x)) abort(); } while (0) 这一句注释掉(如上图)

1. 最后我们在config文件中添加一行#define FPM_DEFAULT,防止编译时出现“FPM未选择”的错误。
对于libmad文件的修改比较简单,也并非移植的重点,大家可以直接使用我们修改过的libmad文件。经过修改后的libmad文件如图:



一/MP3格式探索
         关于MP3格式的资料很多,但很少有拿具体文件来分析的。我们这里结合手上的资料,使用具体文件来分析分析。这里只进行简单介绍,MP3内容主要分为三个部分:

1)      ID3V2
为了方便研究MP3格式,我将一个SD卡格式化,并放入一个MP3文件,然后通过WinHex进行查看:

最开头十个字节为ID3标签头,其结构如下:(来自pdf文档《mp3文件格式》)

我们的Size[4]按上面规则转换后为 1111110110=1014(10) 。而后面的数据从0x00408400开始,中间经过0x400=1024(10),说明这个标签部分应该是有1024个字节。所以说:那个计数应该没有包含标签头这十个字节。为了验证我们的猜想,再拿一个文件来试试看。
计算得到246.但是数据一部分为0之后又从0x00408100开始的。距开头0x00408000256个字节。验证了我们的猜想。

关于ID3V2标签我们就介绍到这里。如需更深入了解,可自己看看《mp3文件格式》
1)      一系列的帧
中间的核心数据就是一个一个帧。每个MP3帧(frame)都有一个帧头(frameheader),长度为4Byte(后文用B代表字节Byte,b代表位bit),帧头后面可能有两个字节的CRC校验位(这两个字节是否存在决定于frameheader第16b。0-无CRC校验位,1-有crc校验位),接着就是frame实体数据了。帧的格式如下:
A-frame sync   B-MPEG Audio version    C-Layer description    D-Protection bit
E-Bitrateindex   F-Sampling rate frequency index(Hz)   G-padding bit
H-Private bit     I-ChannelMode  
1111 1111 111110111001 00000000 0000
我们读到的文件帧头为: F   F    F   B    9  0    0   0
Syncword            11111111111       全为1
ID                     11            MPEG1
Layer description        01             Layer III (这就是MP3中那个3)
Protection bit           1              没有CRC校验位
Bitrate                1001           128kpbs(这就是我们常说的比特率)
Sampling rate           00             44100 (采样频率)
Pading bit               0              frame没有padding
Channel Mode          00             立体声
解析这些数据我们可以看到一些最基本的信息。我们这个帧是没有CRC校验的,所以接着的数据就直接是所谓的MAIN_DATA。这个MAIN_DATA到底有多大?我们可以通过上面的参数计算得到。
1 无论帧的长度为多长,每帧的播放时约为26ms
2 每帧数据大小:
FrameSize = (((MPEGVersion==MPEG1?14472)*Bitrate)/SamplingRate)+PaddingBit
如果MPEGVersionMPEG1就用Bitrate乘以144,否则乘以72.
我们的版本是MPEG1所以我们计算如下:
((128000*144)/44100)+0=418 Byte
a)       main_data
这个部分的数据比较复杂,经过了一些压缩,我们已经不能看到具体的意义了。只能基本看到数据被“FF FB 92 00”分为一堆一堆的,每堆被“LAME3.90(alpha)”分为两块,LAME3.90后面的数据是一堆标记信息。具体内容已经被加密得面目全非,不必深究。下面来看看libmad部分。

一、初探libmad
Libmad解码mp3的具体过程中有些地方涉及到的知识还是比较深涩的。有兴趣的可以自己研究研究,我们来介绍一些简单的概念。
Libmad主要结构体:
mad_stream  存放解码前的Bitstream数据
mad_synth   存放解码合成滤波后的PCM数据
mad_pcm    定义了音频的采样率,声道个数和PCM采样数据,用来初始化音频MPEG
mad_frame  记录MPEG帧解码后PCM数据的数据结构,其中的mad_header用来记录帧的基本信息,比如MPEG层数、声道模式、流比特率、采样比特率。声道模式包括单声道、双声道、联合立体混音道以及一般立体声。

我们可以再stream.h中找到mad_stream的定义:(在基于zn-X开发板的例子中,已经加上比较详细的注释)
这里就不详细列出,大家可以到工程中查看。libmad解码的流程是:
1.      我们从SD卡中读出文件存入InputBuffer中,
2.      从InputBuffer相关信息送给stream。
3.      经过解码,得到PCM数据放入mad_frame的相应位置。
4.      经过子带合成滤波处理,放入mad_synth相应位置。
5.      从Synth.pcm.samples[0]中读出数据,进行处理。
一、利用LIBMAD实现功能
为了方便验证解码是否正确,我们决定将解码得到的信息存入一个文件中,然后利用cooledit进行查看。
1.      读入数据
要实现这个功能我们必须要从SD卡中读取出相应的数据。这里我们采用南哥的znFAT
在madlld.c这个文件中有这样一个标志                              
这就是解码的第一步,读入数据:

起始,read_num和ReadStart都为0。至于remaining的值,就是解码之后剩下不足一帧的数据的长度。我们将其放入InputBuffer(输入缓冲区)头,然后再从SD卡中读取数据填满InputBuffer进行解码。


这之后,我们将InputBuffer移交给Stream结构体。读入数据的第一步就完成啦!

2.      帧解码

实现解码的是mad_frame_decode这一句,如果返回值非零,表示出现错误,对错误进行一些处理。
3.      合成滤波

这个部分的代码就这么一句。
4.      数据存储

每一帧解码出来的PCM数据有左右声道各1152个。





二、数据查看
程序运行完成后,SD卡中会多出一个pcm.txt文档。我们打开CoolEdit
找到文件打开

设置格式


中间显示波形。

播放



就可以听到解码出来的歌曲啦!







基于libmad的MP3软件解码.pdf

872.68 KB, 下载次数: 238

此帖出自stm32/stm8论坛

最新回复

感谢分享,支持一下  详情 回复 发表于 2022-12-29 16:02
点赞 关注(1)
 

回复
举报

2886

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 
感谢分享
此帖出自stm32/stm8论坛
 
个人签名昵称:灰小子
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
很好啊,我正在用阿
此帖出自stm32/stm8论坛
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

4
 
这个madlld-1.1p1.tar文件下载不到,可不可以发一份工程代码,我的邮箱:yx58yx58@eyou.com
万分感谢!!!
此帖出自stm32/stm8论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

5
 

感谢分享
此帖出自stm32/stm8论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 
明月明 发表于 2018-7-1 13:07 这个madlld-1.1p1.tar文件下载不到,可不可以发一份工程代码,我的邮箱:, 万分感谢!!!

请问有可以用的吗?我也正在学习相关东西

此帖出自stm32/stm8论坛
 
 
 

回复

81

帖子

3

TA的资源

一粒金砂(中级)

7
 
感谢分享,支持一下
此帖出自stm32/stm8论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表