DSP课程设计 MP3语音压缩
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
DSP系统课程设计
利用DSP实现语音mp3压缩课程设计报告
学院电子信息工程学院
小组成员
指导教师高海林
时间2016年7月14日
目录
一、实验目的 (3)
二、技术指标及设计要求 (3)
三、实验原理 (4)
3.1MP3 编码原理 (4)
3.1.1 概述 (4)
3.1.2 人耳听觉心理学模型(The Psychoacoustic Model) (4)
3.1.3 滤波器排(The filter bank) (5)
3.1.4 位元分配及量化(Bit Allocation and Quantization) (6)
3.1.5 霍夫曼编码(Huffman Encoding) (8)
3.1.6 位元串格式 (8)
3.2 MP3 解码原理 (9)
3.2.1 MP3 解码流程图 (9)
3.2.2 解码步骤分析 (9)
3.3硬件结构 (19)
3.2.1BJTU-DSP5502 实验系统板 (19)
3.2.2TLC320AIC23 的内部结构及工作原理 (20)
四、程序设计 (20)
4.1 MP3 编码 (20)
4.2 MP3 解码 (22)
五、方案优化 (26)
六、总结与体会 (26)
七、参考文献 (26)
一、实验目的
掌握利用DSP进行信号采集的方法,掌握利用DSP进行语音信号的压缩和解
压方法,以及语音信号的回放方法。
学会A/D、D/A的工作原理和使用,学会A/D、D/A转换器的编程方法。
以语音信号处理为依托,深入理解信号的抽样和重建的
基本方法,提高学生系统地思考问题和解决实际问题的能力。
通过调用DSP CSL
库对McBSP接口的编程,学会DSP片上外设的使用方法。
二、技术指标及设计要求
2.1基本部分:
(1)使用DSP实现语音压缩和解压缩的基本算法,算法类型采用mp3压缩算法。
(2)设置A/D的采样率为32KHz,从Line-in或MIC输入口实时采集语音信号,利用McBSP1接收寄存器将外部语音数据接收到DSP中,接收1s数据。
(3)采用适当的语音压缩算法,将接收到的数据进行压缩。
也可以将接收到的
数据直接压缩后存储。
(4)对上述已压缩数据进行解压。
(5)将解压后的数据经Headphone端口输出,利用耳机试听。
(6)使用指示灯对语音存储和回放过程进行指示。
2.2发挥部分:
(1)将A/D采样率和D/A的转换率设置为不同频率,对比输出的语音信号,发
现不同并解释。
(2)实现mp3语音压缩。
三、实验原理
3.1MP3编码原理
3.1.1概述
图3-1MP3编码器方框图
如图3-1所示,就单声道而言,MP3的一个编码框包含1152个声音取样,每个取样为16位元。
MP3编码时,首先将原始输入的16-bit PCM音讯经过滤波器排分析(Filter Bank Analysis),转换成32个等频宽的子频带讯号(Subband Signals),然后通过改良式离散余弦转换(MDCT,Modified Discrete Cosine Transform),将每个子频带信号,再细分为18个次频带。
然后根据第二声响心理模型(Psychoacoustic Model ll)所提供的讯号遮噪比(SMR,Signal-to-Mask Ratio),对每一子频带讯号,做位元分配及量化编码。
最后只要将编码后的资料依照MPEG-1定义的位元串的型式输出即可。
3.1.2人耳听觉心理学模型(The Psychoacoustic Model)
1.最小听觉门槛判定(The minimal audition threshold)
人耳的听力范围是20Hz-20k Hz的频率范围,但是人耳对不同的频率声音的灵敏度是不同的,不同频率的声音要达到能被人耳听到的水平所需要的强度是不一样。
那么通过计算,可以把音乐文件中存在但不能被人耳听到的声音去掉。
通过这原理,我们还可以建立模型,把大部分数据空间分配到人耳最灵敏的2kHz 到5kHz范围,其余频率分配比较少的空间。
2.人耳的遮蔽效应(The Masking effect)
遮蔽效应表现在强信号会遮蔽邻近频率的弱信号。
用生活经验来说,在安静的房间中,一根针掉到地上都能听见,可到了大街上,就算手机音量调到最大,来电时也未必能听见,而手机的声音确确实实是存在的,原因就是被周围更大的声音遮蔽了。
有了对遮蔽效应的研究成果,编码器就能根据已建立的数学模型,计算强信号对附近弱信号的遮蔽,把能引起人们注意的声音才保留。
3.1.3滤波器排(The filter bank)
滤波器排包含分析子频带滤波器和改良式离散余弦转换两部分。
如图3-2所示。
图3-2分析子频带滤波器和MDCT
1.分析子频带滤波器
MP3是一种子带编码,使用的是一个32通道的伪标准正交镜像滤波器组来完成这一功能,该滤波器组实际上是32个512阶的FIR带通滤波器,通带频率由低到高。
当PCM信号输入滤波器组后,就会被分解成32路等频宽的子带信号,如图3-3所示。
每输入32个PCM讯号做一次滤波器排分析,然后可以得到32个输出(每个子频带有一个结果),由于一个编码框有1152个PCM信号,所以共需要36次的子频带分析。
图3-3分析子频带滤波器组示意图
2.改良式离散余弦变换(MDCT)
将原始的音讯经过滤波器排分析,分成32个等宽的子频带讯号后,为了提
高频谱的分辨率,将每个子频带信号再经MDCT细分成数个频线信号。
MDCT的运算共包含了MDCT窗框、MDCT与长窗框假象处理三个部分。
如图3-2所示。
首先介绍MDCT的四种窗框:长窗框(Normal Window)、长短窗框(Start Window)、短窗框(Short Window)与短长窗框(Stop Window)。
使用长窗框做转换,可得较好的频谱分辨率,而使用短窗框做转换,则可得较佳的时间轴分辨率。
至于长短窗框是用于长窗框要转换到短窗框时的过渡窗框,短长窗框则相反。
决定好窗框后就可以做MDCT的运算,表达式如下:
其中Zk是子频带讯号与MDCT窗框相乘后的结果,若此处选择短窗框则做短区块的DCT运算(n=12),否则就做长区块的DCT运算(n=36)。
由于滤波器排的特性,当原始音频被分成32个子频带时,在频谱上可见邻
近的子频带间有明显的重叠现象,而处于重叠区间的讯号将会同时影响两个子频带。
所以在经过MDCT转成频线信号时,需对邻近相对应的频线信号做特别处理,以减少因混叠所造成的噪声,影响音讯质量。
处理的方式是将处在相对应位置的频线之能量做一定比例的增减。
3.1.4位元分配及量化(Bit Allocation and Quantization)
1.位元分配(Bit allocation)
位元分配的目的,在于使得每个比例因子频带之遮噪比
(MNR,Mask-to-Noise
Ratio)达到最大,以得到最佳的音讯质量。
这是一个反复的过程,每次找出最
小MNR的频带,分配位元给此频带以提高MNR,接着重新计算各频带的MNR,然后再不断重覆此调整过程,直到没有足够的位元可供调整为止。
因此在进行位元分配之前,需要知道可以用来编码之位元数,以及各子频带的MNR。
假设用SNR(m)来表示讯号经过m个位元量化之后的signal-to-noise ratio(SNR),那么在这个临界频带中,用来量测人耳可感知
的失真之参数mask-to-noise ratio(MNR)可以计算如下:
SMR是由声响心理模型提供。
有了MNR之后,就可以开始位元分配与量化。
MP3编码在量化时,将频域划分成21个比例因子频带(scalefactor band)为单位来处理。
量化器对频谱量化后,计算需要多少位元来对做霍夫曼编码,若超过可用之位元数,就要调整stepsize的大小,如此可以降低所需的位元数。
决定好量化后的频线后,再和未量化前的频线做噪声估计。
如果求出的比例因子频带的失真超过可容忍的大小(由人耳听觉心理模型提供),编码器就会放大该频带内的值,这样就可以使得该频带分到更多的位元,也就和前面所提到有关利用MNR来做位元分配的观念呼应。
如此一来,再对做量化的操作,重复上述操作一直到没有任何比例因子频带的误差超过可容忍的失真大小即可。
2.非均匀量化
上式是MP3编码的量化公式,其中xr(i)是从MDCT输出并调整过的频线,ix(i)为量化过后的频线(整数值),0.75次方是用来使得量化器能提供一致
的SNR值,而nint()代表四舍五入的函数。
图3-4量化器的输入输出关系曲线图
图3-4是MP3量化器的输入输出关系图,可以看出这是一个非均匀量化的量化器。
0.75次方是造成非均匀量化的原因,如果把0.75次方改成1次方,就会变为均匀量化。
编码器一方面要削减量化噪音,让它在人耳遮蔽曲线以下;另一方面要保证bitrate满足要求。
实际上这里就是要确定两个数值:一个是确定bitrate的步
进值(gain value),另一个是削减量化噪音的增益因子(ScaleFactor),这两个
系数会在正式编码之前确定下来,确定过程由两个嵌套的迭代回路完成:失真控
制回路(Distortion Control Loop)和量化速率控制回路(Nonuniform Quantization Rate Control Loop)。
◆内部迭代回路(Rate Loop)
量化以后的数据送进Huffman编码器,当发现比特数大于可用流量时,编码器会返回信息,让Rate Loop调整步进值以增大量化步长,从而让数据流量减小。
循环会一直进行,尝试不同的量化步长,直到Huffman编码以后的数据流量足够小。
因为这个回路是用来控制码率的,所以叫做Rate Loop。
◆外部迭代回路(noise control loop)
显然,这个回路的作用就是控制量化噪音(quantization noise),让其保持
在听觉心理学提供的屏蔽临界线(masking threshold)以下。
每一个频段都会有
一个增益因子,一开始编码器以1.0作为默认因子,如果量化噪音量超过允许的值,那么回路就会调整增益因子,来把量化噪音降下来。
更少的量化噪音意味着流量增大,码率需要提高,所以增益因子每次改变以后,Rate Loop都要进行调整,让码率符合要求。
频线经量化之后再做霍夫曼编码。
3.1.5霍夫曼编码(Huffman Encoding)
为了提高压缩率,在量化之后又使用了无失真且非固定长度的霍夫曼编码,
将量化后的频线ix(i)编码。
在量化后除了在MDCT使用短区块的情况之外,量
化器将输出的频线依频率来排序。
对于使用短区块的情况而言,在相同的频率下,又有三个窗框值,所以在每个比例因子频带里其顺序为频率再来才是窗框。
排序的优点在于可使得最大的值分布在低频,而在高频时有一连频的零
(zero values),能够提高压缩比。
量化器将频线ix(i)分成三个区间,分别为零区间(zero region)、count1区间和big_value区间,这样就可以让编码器依照不同的区间使用不同的霍夫曼表(Huffman table),而此霍夫曼表是利用各个区间里的统计特性而建立的。
在高
频区间,编码器将连续的一串零视为一个区间,称为零区间(zero region),在
此区间是不用编码的,因为这个区间的长度的信息可由另两个区间的长度求之。
而第二个区间称为count1区间,是由一连串的0和1组成,此区间的霍夫曼编
码方式是以四个取样为一组来查表,所以此区间的长度为4的倍数。
第三个区间
为big_value区间,此区间会出现较大的数值,这里所用的霍夫曼表是以两个量
化后的频线为一组来编码,而此区间可再细分成三个区间,每个区间的霍夫曼表不一定相同,根据各区间的最大数值来决定合适的霍夫曼表。
3.1.6位元串格式
MP3的位元串格式共分为四个部分,分别是档头(header)、错误侦测码(CRC)、附属资料(side information)和主要信息(main data)。
档头和附属资料记载
译码时所需的信息,其中单声道的音讯必须包含136位元的附属资料,双声道的音讯则需要256位元。
在档头区的第16个位元会记录是否使用错误侦测码,若有,则在档头区之后会接着16位元的侦测码。
错误侦测码是用来对档头在译码时做侦错的动作,避免因为档头出现错误而无法正确的译码资料;主要资料区是存放着比例因子(scalefactor)和经过量化、位元分配与无失真的霍夫曼编码之后的音乐讯号。
3.2MP3解码原理
3.2.1MP3解码流程图
图3-5MP3解码流程图
说明:其中同步及差错检查包括了头解码模块在主控模块开始运行后,主控模块将比特流的数据缓冲区交给同步及差错检查模块,此模块包含两个功能,即头信息解码及帧边信息解码,根据它们的信息进行尺度因子解码及哈夫曼解码,得出的结果经过逆量化,立体声解码,混淆缩减,IMDCT,频率反转,合成多相滤波这几个模块之后,得出左右声道的PCM码流,再由主控模块将其放入输出缓冲区输出到声音播放设备。
3.2.2解码步骤分析
1.主控模块
主控模块的主要任务是操作输入输出缓冲区,调用其它各模块协同工作。
其中,输入输出缓冲区均由DSP控制模块提供接口。
输入缓冲区中放的数据为原始mp3压缩数据流,DSP控制模块每次给出大于最大可能帧长度的一块缓冲区,这块缓冲区与上次解帧完后的数据(必然小于一
帧)连接在一起,构成新的缓冲区。
输出缓冲区中将存放的数据为解码出来的PCM数据,代表了声音的振幅。
它由一块固定长度的缓冲区构成,通过调用DSP控制模块的接口函数,得到头指针,在完成输出缓冲区的填充后,调用中断处理输出至I2S接口所连接的音
频ADC芯片(立体声音频DAC和DirectDrive耳机放大器)输出模拟声音。
2.同步及差错检测
同步及差错检测模块主要用于找出数据帧在比特流中的位置,并对以此位置开始的帧头、CRC校验码及帧边信息进行解码,这些解码的结果用于后继的尺度因子解码模块和哈夫曼解码模块。
Mpeg1layer3的流的主数据格式见下图:
图3-6主数据的组织结构图
其中granule0和granule1表示在一帧里面的粒度组1和粒度组2,channel0
和channel1表示在一个粒度组里面的两个通道,s calefactor为尺度因子quantized value为量化后的哈夫曼编码值,它分为big values大值区
和count11值区
CRC校验:表达式为X16+X15+X2+1
2.1帧同步
帧同步目的在于找出帧头在比特流中的位置,ISO1172-3规定,MPEG1的帧头
为12比特的“111111111111”,且相邻的两个帧头隔有等间距的字节数,这个字节数可由下式算出:
N=144*比特率/采样率
如果这个式子的结果不是整数,那么就需要用到一个叫填充位的参数,表示间距为N+1。
2.2头信息解码
头信息解码目的是找出这一帧的特征信息,如采样率,是否受保护,是否有填充位等。
头信息见下图:
图3-7帧头信息结构图
2.3帧边信息解码
帧边信息解码的主要目的在于找出解这帧的各个参数,包括主数据开始位置,尺度因子长度等等,帧边信息如下表所示:
表3-1帧边信息(side_infomation)表
2.4main_data_begin
main_data_begin(主数据开始)是一个偏移值,指出主数据是在同步字之前多
少个字节开始。
需要注意的是:
1.帧头不一定是一帧的开始,帧头 CRC 校验字和帧边信息在帧数据中是滑动的。
2.这个数值忽略帧头和帧边信息的存在,如果 main_data_begin = 0, 则主数
据从帧边信息的下一个字节开始。
2.5block_type
block_type 指出如下三种块类型:
block_type = 0 长块
block_type = 1 开始块
block_type = 3 结束块
block_type = 2 短块
在编码过程中进行 IMDCT 变换时,针对不同信号为同时得到较好的时域和
频域分辨率定义了两种不同的块长:长块的块长为 18 个样本,短块的块长
为 6 个样本。
这使得长块对于平稳的声音信号可以得到更高的频率分辨率,而短
块对跳变信号可以得到更高的时域分辨率。
由于在短块模式下,3 个短块代替 1
个长块,而短块的大小恰好是一个长块的 1/3,所以 IMDCT 的样本数不受块长的
影响。
对于给定的一帧声音信号,IMDCT 可以全部使用长块或全部使用短块,
也可以长短块混合使用。
因为低频区的频域分辨率对音质有重大影响,所以在混合块模式下,IMDCT 对最低频的 2 个子带使用长块,而对其余的 30 个子带使用
短块。
这样,既能保证低频区的频域分辨率,又不会牺牲高频区的时域分辨率。
长块和短块之间的切换有一个过程,一般用一个带特殊长转短(即起始
块 block_type = 1)或短转长(即终止块,block_type = 3)数据窗口的长块来
完成这个长短块之间的切换。
因此长块也就是包括正常窗,起始块和终止块数据窗口的数据块;短块也包含 18 个数据,但是是由 6 个数据独立加窗后在经过连
接计算得到的。
2.6big_values,count1
每一个粒度组的频谱都是用不同的哈夫曼表来进行编码的。
编码时,把整个
从 0 到奈奎斯特频率的频率范围(共 576 个频率线)分成几个区域,然后再用
不同的表编码。
划分过程是根据最大的量化值来完成的,它假设较高频率的值有较低的幅度或者根本不需要编码。
从高频开始,一对一对的计算量化值等于“0”的数目,此数目记为“rzero”。
然后 4 个一组地计算绝对值不超过“1”的量化值(也就是说,其中只可能有-1,0 和+1 共 3 个可能的量化级别)的数目,记为“count1”,在此区域只应用了 4 个哈夫曼编码表。
最后,剩下的偶数个值的对数记为“big values”,在此区域只应用了 32 个哈夫曼编码表。
在此范围里的
最大绝对值限制为 8191。
此后,为增强哈夫曼编码性能,进一步划分了频谱。
也就是说,对 big values 的区域(姑且称为大值区)再细化,目的是为了得到更
好的错误顽健性和更好的编码效率。
在不同的区域内应用了不同的哈夫曼编码表。
具体使用哪一个表由 table_select 给出。
从帧边信息表中可以看到:
当 window_switch_flag == 0 时,只将大值区在细分为 2 个区,此时 region1_count
无意义,此时的region0_count 的值是标准默认的;但当window_switch_flag == 1 时再将大值区细分为 3 个区。
但是由于
region0_count 和 region1_count 是根据从 576 个频率线划分的,因此有可能超出
了 big_values *2 的范围,此时以 big_values *2 为准 . region0_count 和
region1_count 表示的只是一个索引值,具体频带要根据标准中的缩放因子频带
表来查得。
图3-8缩放因子、大值区、1值区和零值区分布图
3、缩放因子(scale factor)解码
缩放因子用于对哈夫曼解码数据进行逆量化的样点重构。
根据帧边信息中的scalefactor_compress和标准中的对应表格来确定的slen1和slen2对缩放
因子进行解码,即直接从主数据块中读取缩放因子信息并存入表
scalefac_l[gr][ch][sfb]和scalefac_s[gr][ch][sfb]中。
对第2粒度组解码
时,若为长块,则必须考虑尺度因子选择信息。
3.1尺度因子带(scalefactor-band)
在mpeg layer3中576条频率线根据人耳的听觉特性被分成多个组,每个组对应若干个尺度因子,这些组就叫做尺度因子带,每个长窗有21个尺度因子
带而每个短窗有12个尺度因子带。
3.2scfsi
scfsi(尺度因子选择信息)用于指出是否将粒度组1的尺度因子用于粒度
组2。
如果为0表示不用,则在比特流中需读取粒度组2的尺度因子。
4、哈夫曼解码
哈夫曼编码是一种变长编码,在mp3哈夫曼编码中,高频的一串零值不编码,不超过1的下一个区域使用四维哈夫曼编码,其余的大值区域采用二维哈夫曼编码,而且可选择地分为三个亚区,每个有独立选择的哈夫曼码表。
通过每个亚区单独的自适应码表,增强编码效率,而且同时降低了对传输误码的敏感度。
在程序实现上,哈夫曼表逻辑存储采用了广义表结构,物理存储上使用数组结构。
查表时,先读入4bit数据,以这4bit数据作为索引,其指向的元素有两种类
型,一种是值结构,另一种是链表指针式结构,在链表指针式结构中给出了还需要读取的bit数,及一个偏移值。
如果索引指向的是一个值结构,则这个值结构
就包含了要查找的数据。
如果索引指向的是一个链表指针式结构,则还需再读取其中指定的比特数,再把读取出的比特数同偏移值相加,递归的找下去,直到找到值结构为止。
5、逆量化
5.1逆量化公式
逆量化由下面公式算出:
短窗模式:
长窗模式:
其中:
is[i]:由huffman编码构造的频率线
sbg:subblock_gain
scalefac_multiplier:=(scalefac_scale+1)/2
其它值均可在帧边信息中找到。
6.联合立体声转换
6.1强度立体声转换
在强度立体声模式中,左声道传的是幅值,右声道的scalefactor传的是立体声的位置is_pos。
需要转换的频率线有一个低边界,这个低边界是由右声道的
zero_part决定的,并且使用右声道的尺度因子来作为is_pos。
强度立体声比
左声道:右声道:
6.2M_S立体声转换
在M_S立体声模式中,传送的是规格化的中间/旁边声道的信息。
左声道右声道
其中Mi是channel[0]的值,Si是channel[1]的值
6.3处理流程
强度立体声模式:
图3-9处理流程图
7、重排序
重排序的目的在于把哈夫曼解码之后的短块的每个尺度因子带3个窗,每个窗sfbwidth(尺度因子带宽度)个采样的顺序整理成为每个子带三个窗,每个窗六个采样xr[sb][window][freq_line]的顺序。
图3-10重排序处理流程图
8.混淆缩减
对于长块,在进入IMDCT之前应当先进行混淆缩减。
其算法思想是用蝶形算法进行相邻块相邻频率线的调整。
如图:
图3-11混淆缩减算法图
9.IMDCT覆盖叠加
MDCT的目的在于进行时域到频域的转换,减少信号的相关性,使得信号的压缩可以更加高效地完成,而它的反变换IMDCT的目的在于将信号还原为没有变换之前的数值,使频域值向时域值过渡。
其公式如下:
在进行了IMDCT变换之后,需对频率信号进行加窗、覆盖、叠加。
10、频率反转
在IMDCT之后,进入合成多相滤波之前必须进行频率反转补偿以校正多相滤波器组的
频率反转。
方法是将奇数号子带的奇数个采样值乘以-1。
11、合成多相滤波
合成多相滤波的目的是将频域信号转化为时域信号。
其原理流程如下:
图3-12合成多相滤波原理图
上图流程可简述如下:
1.将从32个子带抽来的32个sample值通过一个矩阵运算算出64个中间值。
2.将这64个中间值放入一个长度为1024的FIFO缓冲区(这个缓冲区初始化为0)。
3.从这个缓冲区中每连续的128个值中取头尾各32个值,合为64个值。
完成后组成512值的向量U。
4.加窗,即将Ui与窗口系数Di相乘,得到另一512值向量W。
5.最后将这512值向量W每连续的32个值中顺次取一个值,一次共取
得512/32=16个值相加。
完成后一共取得32个最终的时域信号值。
3.3硬件结构
3.2.1BJTU-DSP5502实验系统板
本次实验采用的BJTU-DSP5502实验系统,是一套DSP信号处理硬件实验系统,包括BJTU-DSP5502实验板和SEED-XDS510PLUS仿真器以及相关配件。
图3-13BJTU-DSP5502实验系统
图3-14BJTU-DSP5502板结构组成框图
BJTU-DSP5502实验系统板主要包括:
(1)DSP芯片1枚(U1):TMS320VC5502@300MHz
(2)SDRAM1枚(U5):2M×32bit(8Mbytes)HY57V643220CT
(3)FLASH1枚(U4):256K×16bit(512Kbytes)SST39VF400A-70
(4)CPLD1枚(U2):CY37064VP100
(5)通信接口3个:仿真器JTAG接口(J1)、连接到PC机USB接口(J4)和UART接口(J2)
(6)信号采集和输出端口:立体音输入接口line-in(J5,直接接电脑的语音输出端口)/麦克风输入接口(J7)/耳机音频输出接口(J6)
(7)扩展板接口(J9,J10)
3.2.2TLC320AIC23的内部结构及工作原理
TLV320AIC23B是TI公司生产的高性能语音芯片,16、20、24、32位串行A/D、D/A转换电路。
采样速率:可通过DSP对其寄存器编程来设置,范围8KHz~96KHz。
内含抗混叠滤波器和重构滤波器。
在ADC之后有一个抽取滤波器:提高输入信号的信噪比(通带截频0.416fs 或0.4535fs)。
在DAC之前有一个插值滤波器:保证输出信号平滑(通带截频0.416fs或0.4535fs)。
内含11个寄存器,名称和功能如下(省略9、10、11):
①左侧line输入通道音量控制(地址:0000000)
②右侧line输入通道音量控制(地址:0000001)
③耳机左声道音量控制(地址:0000010)
④耳机右声道音量控制(地址:0000011)
⑤模拟音频通道控制(地址:0000100)
⑥数字音频通道控制(地址:0000101)
⑦采样率控制(地址:0001000)
⑧数字音频接口格式设置(地址:0000111)
四、程序设计
4.1MP3编码
#include "g_includes.h"
#include "wave.h"
#include "Layer3.h"
#define WAVE 0xfb1
extern int wave_get(short buffer[2][samp_per_frame], void *config_in);
int write_mp3(long bytes, void *buffer, void *config_in) {
config_t *config=(config_t *)config_in;
config->mpeg.outbuffer[config->mpeg.outprocessed] = *((char*)buffer);
config->mpeg.outprocessed++;
return 1;
}
void error(char *s)
{
printf("[ERROR] %s\n",s);
exit(1);
}
static void set_defaults(config_t *config)
{
L3_set_config_mpeg_defaults(&config->mpeg);
}
static bool parse_command(config_t *config)
{
config->infile = "C:\\test.pcm";
config->outfile = "C:\\test.mp3";
}
void outmp3(config_t *config)
{
FILE *fp = fopen(config->outfile,"wb");
fwrite(config->mpeg.outbuffer,sizeof(char),config->mpeg.outprocessed,fp);
fclose(fp);
}
int main()
{
config_t config;
set_defaults(&config);//设定默认参数
parse_command(&config);
wave_open(&config);//打开 pcm 文件
config.mpeg.samplerate_index = L3_find_samplerate_index(config.wave.samplerate); if(config.mpeg.samplerate_index < 0) error("invalid samplerate");
config.mpeg.bitrate_index = L3_find_bitrate_index(config.mpeg.bitr); if(config.mpeg.bitrate_index < 0) error("invalid bitrate");
if ((config.mpeg.file = fopen(config.outfile, "wb")) == NULL) {
printf("Could not create \"%s\".\n", config.outfile);
exit(1);
}
config.get_pcm=&wave_get;
config.write_mp3=&write_mp3;
L3_compress(&config);
wave_close(&config);
outmp3(&config);
fclose(config.mpeg.file);
exit(0);
}
4.2MP3解码
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "decode.h"
void main(int argc, char**argv)
{
//定义变量
FILE *musicout;
Bit_stream_struc bs;
frame_params fr_ps;
III_side_info_t III_side_info;
III_scalefac_t III_scalefac;
unsigned int old_crc;
layer info;
int sync, clip;
int done = FALSE;
unsigned long frameNum=0;
unsigned long bitsPerSlot;
unsigned long sample_frames;
//二进制方式打开文件
typedef short PCM[2][SSLIMIT][SBLIMIT];
PCM *pcm_sample;
char *file_in = "D:\\test.mp3";
char *file_out = "D:\\test.pcm";
pcm_sample = (PCM *) mem_alloc((long) sizeof(PCM), "PCM Samp");
fr_ps.header = &info;
if ((musicout = fopen(file_out, "w+b")) == NULL) {
printf ("Could not create \"%s\".\n", file_out);
exit(1);
}
//以比特为单位取出文件包含的信息并存入相应内存
open_bit_stream_r(&bs, file_in, BUFFER_SIZE);
sample_frames = 0;
while(!end_bs(&bs)) {
//尝试帧同步
sync = seek_sync(&bs, SYNC_WORD, SYNC_WORD_LENGTH);
if (!sync) {
done = TRUE;
printf("\nFrame cannot be located\n");
out_fifo(*pcm_sample, 3, &fr_ps, done, musicout, &sample_frames);
break;
}
//解码帧头
decode_info(&bs, &fr_ps);
//将 fr_ps.header 中的信息解读到 fr_ps 的相关域中
hdr_to_frps(&fr_ps);
//输出相关信息
if(frameNum == 0)
WriteHdr(&fr_ps);
printf("\r%05lu", frameNum++);
if (info.error_protection)
buffer_CRC(&bs, &old_crc);
switch (y) {
case 3:
{
int nSlots, main_data_end, flush_main;
int bytes_to_discard, gr, ch, ss, sb;
static int frame_start = 0;。