球球大作战彩字代码:凌阳音频压缩算法-

来源:百度文库 编辑:偶看新闻 时间:2024/04/27 21:44:38

 

第7章凌阳音频压缩算法261
第7章凌阳音频压缩算法
7.1背景介绍
7.1.1音频的概述(特点,分类)
我们所说的音频是指频率在20Hz~20kHz的声音信号,分为:波形声音,语音
和音乐三种,其中波形声音就是自然界中所有的声音,是声音数字化的基础.语音也
可以表示为波形声音,但波形声音表示不出语言,语音学的内涵.语音是对讲话声音
的一次抽象.是语言的载体,是人类社会特有的一种信息系统,是社会交际工具的符
号.音乐与语音相比更规范一些,是符号化了的声音.但音乐不能对所有的声音进行
符号化.乐谱是符号化声音的符号组,表示比单个符号更复杂的声音信息内容.
7.1.2数字音频的采样和量化
将模拟的(连续的)声音波形数字元化(离散化),以便利数字计算机进行处理
的过程,主要包括采样和量化两个方面.
数字音频的质量取决于:采样频率和量化位数这两个重要参数.此外,声道的数
目,相应的音频设备也是影响音频质量的原因.
7.1.3音频格式的介绍
音频文件通常分为两类:声音文件和MIDI文件
(1)声音文件:指的是通过声音录入设备录制的原始声音,直接记录了真实声音
的二进制采样数据,通常文件较大;
(2)MIDI文件:它是一种音乐演奏指令序列,相当于乐谱,可以利用声音输出设
备或与计算机相连的电子乐器进行演奏,由于不包含声音数据,其文件尺寸较小.
1)声音文件的格式
WAVE文件——*.WAV
WAVE文件使用三个参数来表示声音,它们是:采样位数,采样频率和声道数.
在计算机中采样位数一般有8位和16位两种,而采样频率一般有11025Hz(11KHz),
22050Hz(22KHz),44100Hz(44KHz)三种.我们以单声道为例,则一般WAVE文
件的比特率可达到88K~704Kbps.具体介绍如下:
(1)WAVE格式是Microsoft公司开发的一种声音文件格式,它符合RIFF(Resource
InterchangeFileFormat)文件规范;
第7章凌阳音频压缩算法262
(2)用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广
泛支持.
(3)WAVE格式支持MSADPCM,CCITTALaw,CCITTLaw和其它压缩算法,
支持多种音频位数,采样频率和声道,是PC机上最为流行的声音文件格式.
(4)但其文件尺寸较大,多用于存储简短的声音片段.
AIFF文件——AIF/AIFF
(1)AIFF是音频交换文件格式(AudioInterchangeFileFormat)的英文缩写,是苹
果计算机公司开发的一种声音文件格式;
(2)被Macintosh平台及其应用程序所支持,NetscapeNavigator浏览器中的
LiveAudio也支持AIFF格式,SGI及其它专业音频软件包同样支持这种格式.
(3)AIFF支持ACE2,ACE8,MAC3和MAC6压缩,支持16位44.1Kz立体声.
Audio文件——*.Audio
(1)Audio文件是SunMicrosystems公司推出的一种经过压缩的数字声音格式,是
Internet中常用的声音文件格式;
(2)NetscapeNavigator浏览器中的LiveAudio也支持Audio格式的声音文件.
MPEG文件——*.MP1/*.MP2/*.MP3
(1)MPEG是运动图像专家组(MovingPictureExpertsGroup)的英文缩写,代表
MPEG标准中的音频部分,即MPEG音频层(MPEGAudioLayer);
(2)MPEG音频文件的压缩是一种有损压缩,根据压缩质量和编码复杂程度的不同
可分为三层(MPEGAudioLayer1/2/3),分别对应MP1,MP2和MP3这三种声
音文件;
(3)MPEG音频编码具有很高的压缩率,MP1和MP2的压缩率分别为4:1和6:
1~8:1,而MP3的压缩率则高达10:1~12:1,也就是说一分钟CD音质的音
乐,未经压缩需要10MB存储空间,而经过MP3压缩编码后只有1MB左右,
同时其音质基本保持不失真,因此,目前使用最多的是MP3文件格式.
RealAudio文件——*.RA/*.RM/*.RAM
(1)RealAudio文件是RealNerworks公司开发的一种新型流式音频(Streaming
Audio)文件格式;
(2)它包含在RealMedia中,主要用于在低速的广域网上实时传输音频信息;
(3)网络连接速率不同,客户端所获得的声音质量也不尽相同:对于28.8Kbps的连
接,可以达到广播级的声音质量;如果拥有ISDN或更快的线路连接,则可获
得CD音质的声音.
2)MIDI文件——*.MID/*.RMI
(1)MIDI是乐器数字接口(MusicalInstrumentDigitalInterface)的英文缩写,是数
字音乐/电子合成乐器的统一国际标准;
(2)它定义了计算机音乐程序,合成器及其它电子设备交换音乐信号的方式,还规
第7章凌阳音频压缩算法263
定了不同厂家的电子乐器与计算机连接的电缆和硬件及设备间数据传输的协
议,可用于为不同乐器创建数字声音,可以模拟大提琴,小提琴,钢琴等常见
乐器;
(3)在MIDI文件中,只包含产生某种声音的指令,这些指令包括使用什么MIDI
设备的音色,声音的强弱,声音持续多长时间等,计算机将这些指令发送给声
卡,声卡按照指令将声音合成出来,MIDI在重放时可以有不同的效果,这取
决于音乐合成器的质量;
(4)相对于保存真实采样资料的声音文件,MIDI文件显得更加紧凑,其文件尺寸
通常比声音文件小得多.
7.1.4语音压缩编码基础
语音压缩编码中的数据量是指:数据量=(采样频率×量化位数)/8(字节数)×声道
数目.
压缩编码的目的:通过对资料的压缩,达到高效率存储和转换资料的结果,即在
保证一定声音质量的条件下,以最小的资料率来表达和传送声音信息.
压缩编码的必要性:实际应用中,未经压缩编码的音频资料量很大,进行传输或
存储是不现实的.所以要通过对信号趋势的预测和冗余信息处理,进行资料的压缩,
这样就可以使我们用较少的资源建立更多的信息.
举个例子,没有压缩过的CD品质的资料,一分钟的内容需要11MB的内存容量
来存储.如果将原始资料进行压缩处理,在确保声音品质不失真的前提下,将数据压
缩一半,5.5MB就可以完全还原效果.而在实际操作中,可以依需要来选择合适的算
法.
常见的几种音频压缩编码:
1)波形编码:将时间域信号直接变换为数字代码,力图使重建语音波形保持原语
音信号的波形形状.波形编码的基本原理是在时间轴上对模拟语音按一定的速
率抽样,然后将幅度样本分层量化,并用代码表示.译码是其反过程,将收到
的数字序列经过译码和滤波恢复成模拟信号.
如:脉冲编码调制(PulseCodeModulation,PCM),差分脉冲编码调制(DPCM),
增量调制(DM)以及它们的各种改进型,如自适应差分脉冲编码调制(ADPCM),自
适应增量调制(ADM),自适应传输编码(AdaptiveTransferCoding,ATC)和子带
编码(SBC)等都属于波形编码技术.
波形编码特点:高话音质量,高码率,适于高保真音乐及语音.
2)参数编码:参数编码又称为声源编码,是将信源信号在频率域或其它正交变换
域提取特征参数,并将其变换成数字代码进行传输.译码为其反过程,将收到
的数字序列经变换恢复特征参量,再根据特征参量重建语音信号.具体说,参
数编码是通过对语音信号特征参数的提取和编码,力图使重建语音信号具有尽
可能高的准确性,但重建信号的波形同原语音信号的波形可能会有相当大的差
别.
第7章凌阳音频压缩算法264
如:线性预测编码(LPC)及其它各种改进型都属于参数编码.该编码比特率可
压缩到2Kbit/s-4.8Kbit/s,甚至更低,但语音质量只能达到中等,特别是自然度较低.
参数编码特点:压缩比大,计算量大,音质不高,廉价!
3)混合编码:混合编码使用参数编码技术和波形编码技术,计算机的发展为语音
编码技术的研究提供了强有力的工具,大规模,超大规模集成电路的出现,则
为语音编码的实现提供了基础.80年代以来,语音编码技术有了实质性的进
展,产生了新一代的编码算法,这就是混合编码.它将波形编码和参数编码组
合起来,克服了原有波形编码和参数编码的弱点,结合各自的长处,力图保持
波形编码的高质量和参数编码的低速率.
如:多脉冲激励线性预测编码(MPLPC),规划脉冲激励线性预测编码(KPELPC),
码本激励线性预测编码(CELP)等都是属于混合编码技术.其数据率和音质介于参数
和波形编码之间.
总之,音频压缩技术之趋势有两个:
1)降低资料率,提高压缩比,用于廉价,低保真场合(如:电话).
2)追求高保真度,复杂的压缩技术(如:CD).语音合成,辨识技术的介绍:
按照实现的功能来分,语音合成可分两个档次:
(1)有限词汇的计算机语音输出
(2)基于语音合成技术的文字语音转换(TTS:Text-to-Speech)
按照人类语言功能的不同层次,语音合成可分为三个层次:
(1)从文字到语音的合成(Text-to-Speech)
(2)从概念到语音的合成(Concept-to-Speech)
(3)从意向到语音的合成(Intention-to-Speech)
图7.1是文本到语音的转换过程:
文本处理语音合成韵律处理
语音数据库词典及语言规范
合成语音输出文本输入
图7.1从文本到语音转换过程示意
语音辨识:
语音辨识技术有三大研究范围:口音独立,连续语音及可辨认字词数量.
口音独立:
1)早期只能辨认特定的使用者即特定语者(SpeakerDependent,SD)模式,使用者
可针对特定语者辨认词汇(可由使用者自行定义,如人名声控拨号),作简单快速的训
第7章凌阳音频压缩算法265
练纪录使用者的声音特性来加以辨认.随着技术的成熟,进入语音适应阶段SA(speaker
adaptation),使用者只要对于语音辨识核心,经过一段时间的口音训练后,即可拥有
不错的辨识率.
2)非特定语者模式(SpeakerIndependent,SI),使用者无需训练即可使用,并进行
辨认.任何人皆可随时使用此技术,不限定语者即男性,女性,小孩,老人皆可.
连续语音:
1)单字音辨认:为了确保每个字音可以正确地切割出来,必须一个字一个字分开
来念,非常不自然,与我们平常说话的连续方式,还是有点不同.
2)整个句子辨识:只要按照你正常说话的速度,直接将要表达的说出来,中间并
不需要停顿,这种方式是最直接最自然的,难度也最高,现阶段连续语音的辨识率及
正确率,虽然效果还不错但仍需再提高.然而,中文字有太多的同音字,因此目前所
有的中文语音辨识系统,几乎都是以词为依据,来判断正确的同音字.
可辨认词汇数量:
内建的词汇数据库的多寡,也直接影响其辨识能力.因此就语音辨识的词汇数量
来说亦可分为三种:
1)小词汇量(10-100)
2)中词汇量(100-1000)
3)无限词汇量(即听写机)
图7.2是简化的语音识别原理图,其中实线部分成为训练模块,虚线部分为识别
模块.
复杂声
学,言
语条件
下的语
音输入
语音模型声学模式训练
语音匹配
语音模式训练
语音处理
识别结果,理
解结果
语言模型
图7.2语音识别原理简图
第7章凌阳音频压缩算法266
7.2凌阳音频简介
7.2.1凌阳音频压缩算法的编码标准
表7.1是不同音频质量等级的编码技术标准(频响):
表7.1
信号类型频率范围(Hz)采样率(kHz)量化精度(位)
电话话音200~340088
宽带音频
(AM质量)
50~70001616
调频广播
(FM质量)
20~15k37.816
高质量音频
(CD质量)
20~20k44.116
凌阳音频压缩算法处理的语音信号的范围是200Hz-3.4KHz的电话话音.
7.2.2压缩分类
压缩分无损压缩和有损压缩.
无损压缩一般指:磁盘文件,压缩比低:2:1~4:1.
而有损压缩则是指:音/视频文件,压缩比可高达100:1.
凌阳音频压缩算法根据不同的压缩比分为以下几种(具体可参见语音压缩工具一
节内容):
SACM-A2000:压缩比为8:1,8:1.25,8:1.5
SACM-S480:压缩比为80:3,80:4.5
SACM-S240:压缩比为80:1.5
按音质排序:A2000>S480>S240
7.2.3凌阳常用的音频形式和压缩算法
1)波形编码:sub-band即SACM-A2000
特点:高质量,高码率,适于高保真语音/音乐.
2)参数编码:声码器(vocoder)模型表达,抽取参数与激励信号进行编码.如:
SACM-S240.
特点:压缩比大,计算量大,音质不高,廉价!
3)混合编码:CELP即SACM-S480
特点:综合参数和波形编码之优点.
除此之外,还具有FM音乐合成方式即SACM-MS01.
第7章凌阳音频压缩算法267
7.2.4分别介绍凌阳语音的播放,录制,合成和辨识
凌阳的SPCE061A是16位单片机,具有DSP功能,有很强的信息处理能力,最
高时钟频率可达到49MHz,具备运算速度高的优势等等,这些都无疑为语音的播放,
录放,合成及辨识提供了条件.
凌阳压缩算法中SACM_A2000,SACM_S480,SACM_S240主要是用来放音,可
用于语音提示,而DVR则用来录放音.对于音乐合成MS01,该算法较繁琐,而且需
要具备音乐理论,配器法及和声学知识,所以对于特别爱好者可以到我们的网站去了
解相关内容,这里只给出它的API函数介绍及程序代码的范例,仅供参考.
对于语音辨识主要有以下两种:
1)特定发音人识别SD(SpeakerDependent):是指语音样板由单个人训练,
也只能识别训练人的语音命令,而他人的命令识别率较低或几乎不能识别.
2)非特定发音人识别SI(SpeakerIndependent):是指语音样板由不同年龄,
不同性别,不同口音的人进行训练,可以识别一群人的命令.
语音识别电路基本结构如图7.3所示:

滤除噪音
预加重
滤波器组
PARCOR系数
线性预测系数
过零次数
能量
相关函数等
模式匹配
词典
语音分析
语音
识别
结果
输出
图7.3语音识别电路结构
具体应用及程序代码可参考7.3.4
7.3常用的应用程序接口API的功能介绍及应用
7.3.1概述
表7.2所列出的是凌阳音频的几种算法:
表7.2SACM-lib库中模块及其算法类型
模块名称(Model-Index)语音压缩编码率类型资料采样率
SACM_A200016Kbit/s,20Kbit/s,24Kbit/s16KHz
SACM_S480/S7204.8Kbit/s,7.2Kbit/s16KHz
第7章凌阳音频压缩算法268
SACM_S2402.4Kbit/s24KHz
SACM_MS01音乐合成(16Kbits/s,20Kbits/s,24Kbits/s)16KHz
SACM_DVR(A2000)16Kbit/s的资料率,8K的采样率,用于ADC通道录音功能16KHz
语音和音乐与我们的生活有着非常密切的关系,而单片机对语音的控制如录放音,
合成及辨识也广泛应用在现实生活中.我们知道对于语音处理大致可以分为A/D,编
码处理,存储,解码处理以及D/A等见图7.4所示.然而,通过前面介绍我们知道麦
克风输入所生成的WAVE文件,其占用的存储空间很大,对于单片机来说想要存储大
量的信息显然是不可能的,而凌阳的SPCE061A提出了解决的方法,即SACM-LIB,
该库将A/D,编码,解码,存储及D/A作成相应的模块,对于每个模块都有其应用程
序接口API,所以您只需了解每个模块所要实现的功能及其参数的内容,然后调用该
API函数即可实现该功能,例如在程序中插入语音提示,或连续播放一段语音或音乐,
也可以根据自己需要的空间或使用范围选择适合自己的算法如表7.2所示.
麦克风A/D转换
存储
喇叭编解码处理D/A转换
图7.4单片机对语音处理过程
以下就不同的算法具体介绍各自的API函数的格式,功能,参数,返回值,备注
及应用范例.
7.3.2SACM_A2000
该压缩算法压缩比较小(8:1)所以具有高质量,高码率的特点适用于高保真音乐和
语音.
其相关API函数如下所示:
voidSACM_A2000_Initial(intInit_Index)//初始化
voidSACM_A2000_ServiceLoop(void)//获取语音资料,填入译码队列
voidSACM_A2000_Play(intSpeech_Index,intChannel,intRamp_Set)//播放
voidSACM_A2000_Stop(void)//停止播放
voidSACM_A2000_Pause(void)//暂停播放
voidSACM_A2000_Resume(void)//暂停后恢复
voidSACM_A2000_Volume(Volume_Index)//音量控制
unsignedintSACM_A2000_Status(void)//获取模块状态
第7章凌阳音频压缩算法269
voidSACM_A2000_InitDecode(intChannel)//译码初始化
voidSACM_A2000_Decode(void)//译码
voidSACM_A2000_FillQueue(unsignedintencoded-data)//填充队列
unsignedintSACM_A2000_TestQueue(void)//测试队列
CallF_FIQ_Service_SACM_A2000//中断服务函数
下面对各个函数进行具体介绍:
1)【API格式】C:voidSACM_A2000_Initial(intInit_Index)
ASM:R1=[Init_Index]
CallF_SACM_A2000_Initial
【功能说明】SACM_A2000语音播放之前的初始化.
【参数】Init_Index=0表示手动方式;Init_Index=1则表示自动方式.
【返回值】无
【备注】该函数用于对定时器,中断和DAC等的初始化.
2)【API格式】C:voidSACM_A2000_ServiceLoop(void)
ASM:CallF_SACM_A2000_ServiceLoop
【功能说明】从资源中获取SACM_A2000语音资料,并将其填入译码队列中.
【参数】无.
【返回值】无.
3)【API格式】
C:voidSACM_A2000_Play(intSpeech_Index,intChannel,int
Ramp_Set);
ASM:R1=[Speech_Index]
R2=[Channel]
R3=[Ramp_Set]
CallSACM_A2000_Play
【功能说明】播放资源中SACM_A2000语音或乐曲.
【参数】Speech_Index:表示语音索引号.
Channel:1.通过DAC1通道播放;
2.通过DAC2通道播放;
3.通过DAC1和DAC2双通道播放.
Ramp_Set:0.禁止音量增/减调节;
1.仅允许音量增调节;
2.仅允许音量减调节;
3.允许音量增/减调节.
【返回值】无.
【备注】
①SACM_A2000的数据率有16Kbps\20Kbps\24Kbps三种,可在同一模块的几种算
法中自动选择一种.
第7章凌阳音频压缩算法270
②Speech_Index是定义在resource.inc文件中资源表(T_
SACM_A2000_SpeechTable)的偏移地址.
③中断服务子程序F_FIQ_Service_SACM_A2000必须安置在TMA_FIQ中断向量
上(参见第五章中断系统内容).
函数允许TimerA以所选的的数据采样率(计数溢出)中断.
程序7-1以自动方式播放一段SACM_A2000语音,并自动结束.(见光盘)
SACM_A2000自动方式主程序流程图:
SACM_A2000放音
的初始化
SACM_A2000压缩播放
获取语音数据并解
码等待中断播放
图7.5A2000自动方式主程序流程
前台程序:
#defineSpeech_10
#defineDAC11
#defineDAC22
#defineRamp_UpDn_Off0
#defineRamp_Up_On1
#defineRamp_Dn_On2
#defineRamp_UpDn_On3
Main()
{
SACM_A2000_Initial(1);
SACM_A2000_Play(Speech_1,DAC1+DAC2,Ramp_UpDn_On);//放音
while(SACM_A2000_Status()&0x01)
{
SACM_A2000_ServiceLoop();
}
}
背景程序:
.TEXT
第7章凌阳音频压缩算法271
.INCLUDEhardware.inc
.INCLUDEA2000.inc
.INCLUDEResource.inc
//========================================================
//函数:FIQ()
//语法:voidFIQ(void)
//描述:FIQ中服务断函数
//参数:无
//返回:无
//========================================================
.PUBLIC_FIQ;
_FIQ:
PUSHR1,R4TO[sp];//入栈保护
R1=0x2000;
TESTR1,[P_INT_Ctrl];//是否为定时器A中断
JNZL_FIQ_TimerA;
R1=0x0800;
TESTR1,[P_INT_Ctrl];//是否为定时器B中断
JNZL_FIQ_TimerB;
L_FIQ_PWM:
R1=C_FIQ_PWM;
[P_INT_Clear]=R1;//清中断
POPR1,R4from[sp];//恢复现场
RETI;
L_FIQ_TimerA://定时器A中断处理
[P_INT_Clear]=R1;//清中断
CALLF_FIQ_Service_SACM_A2000;//调用A2000中断服务函数
POPR1,R4FROM[sp];//恢复现场
RETI;
L_FIQ_TimerB://定时器B中断处理
[P_INT_Clear]=R1;//清中断
POPR1,R4FROM[sp];//恢复现场
RETI;//中断返回
/****************************************************************************/
注:播放语音文件中数据,当出现FFFFFFH数据时便停止播放.
4)【API格式】C:voidSACM_A2000_Stop(void);
ASM:CallF_SACM_A2000_Stop
【功能说明】停止播放SACM_A2000语音或乐曲.
【参数】无.
【返回值】无.
5)【API格式】C:voidSACM_A2000_Pause(void);
ASM:CallF_SACM_A2000_Pause
【功能说明】暂停播放SACM_A2000语音或乐曲.
第7章凌阳音频压缩算法272
【参数】无.
【返回值】无.
6)【API格式】C:voidSACM_A2000_Resume(void);
ASM:CallF_SACM_A2000_Resume
【功能说明】恢复暂停播放的SACM_A2000语音或乐曲.
【参数】无.
【返回值】无.
7)【API格式】C:voidSACM_A2000_Volume(Volume_Index);
ASM:R1=[Volume_Index]
CallF_SACM_A2000_Volume
【功能说明】在播放SACM_A2000语音或乐曲时改变主音量.
【参数】Volume_Index为音量数,音量从最小到最大可在0~15之间选择.
【返回值】无.
8)【API格式】C:unsignedintSACM_A2000_Status(void);
ASM:CallF_SACM_A2000_Status
[返回值]=R1
【功能说明】获取SACM_A2000语音播放的状态.
【参数】无.
【返回值】当R1的bit0=0,表示语音播放结束;bit0=1,表示语音在播放中.
9)【API格式】ASM:CallF_FIQ_Service_SACM_A2000
【功能说明】用作SACM_A2000语音背景程序的中断服务子程序.通过前台子程
序(自动方式的SACM_A2000_ServiceLoop及手动方式的SACM_A2000_Decode)
对语音资料进行解码,然后将其送入DAC通道播放.
【参数】无.
【返回值】无.
【备注】SACM_A2000语音背景子程序只有汇编指令形式,且应将此子程序
安置在TMA_FIQ中断源上.
10)【API格式】C:voidSACM_A2000_InitDecode(intChannel);
ASM:CallF_SACM_A2000_Decode
【功能说明】开始对SACM_A2000语音资料以非自动方式(编程控制)进行译码.
【参数】Channel=1,2,3;分别表示使用DAC1,DAC2通道以及DAC1和
DAC2双通道.
【返回值】无.
【备注】用户只能通过非自动方式对语音资料解压缩.
11)【API格式】C:voidSACM_A2000_Decode(void);
ASM:CallF_SACM_A2000_Decode
第7章凌阳音频压缩算法273
【功能说明】从语音队列里获取的SACM_A2000语音资料,并进行译码,然后通
过中断服务子程序将其送入DAC通道播放.
【参数】无.
【返回值】无.
【备注】用户仅能通过非自动方式对语音资料进行译码.
12)【API格式】C:voidSACM_A2000_FillQueue(unsignedintencoded-data);
ASM:R1=[语音编码资料]
CallF_SACM_A2000_FillQueue
【功能说明】将从用户存储区里获取SACM_A2000语音编码资料,然后将其填
入语音队列中等候译码处理.
【参数】encoded-data为语音编码资料.
【返回值】无.
【备注】用户仅能通过非自动方式对语音资料进行译码.
13)【API格式】C:unsignedintSACM_A2000_TestQueue(void);
ASM:CallF_SACM_A2000_TestQueue
[返回值]=R1
【功能说明】获取语音队列的状态.
【参数】无.
【返回值】R1=0,1,2;分别表示语音队列不空不满,语音队列满及语音队列
空.
【备注】用户仅能通过非自动方式测试语音队列状态.
程序7-2SACM_A2000非自动方式(编程控制)播放语音.(见光盘)
SACM_A2000非自动方式主程序流程见图7.6:
第7章凌阳音频压缩算法274
A2000播放初始化
获取语音资源
并填充语音队列
解码获取数据并播放
判断语音队列
是否满
判断是否到
语音的结束地址放音结束
结束
开始




图7.6SACM_A2000非自动方式主程序流程
中断服务子程序流程见图7.7:
FIQ是TimerA中断吗
填充语音队列
清中断状态


中断返回
寄存器组出

开始
图7.7SACM_A2000中断服务子程序流程
前台程序:
第7章凌阳音频压缩算法275
#defineManual0
#defineAuto1
#defineFull1
#defineEmpty2
#defineDAC11
#defineDAC22
Main()
{
Addr=RES_A32_SA;//长整型资源地址
SACM_A2000_Initial(Manual);//选择非自动方式
SACM_A2000_InitDecode(DAC1+DAC2);//使用双通道
While(SACM_A2000_TestQueue()!=Full)//若队列不满,填入资料
{
Ret=GetResource(Addr);//从ROM中取语音资料
SACM_A2000_FillQueue(Ret);//将语音资料填入队列
Addr++;//指向下一个资料地址
}
While(1)
{
If(SACM_A2000_TestQueue()!=Full)//继续填资料到队列中
{
Ret=GetResource(Addr);
SACM_A2000_FillQueue(Ret);
Addr++;
}
if(AddrSACM_A2000_Decode();//对语音资料进行译码
elseSACM_A2000_Stop();//地址结束,停止播放
}
}
注:
1)文件的结束是由用户位址变量控制的.
2)在非自动方式播放语音,其音量的增/减是通过外部子程序
(SP_Ramp_Up,SP_Ramp_Dn)控制的.
7.3.3SACM_S480
该压缩算法压缩比较大80:3,存储容量大,音质介于A2000和S240之间,适用于语
音播放,如"文曲星"词库.
其相关API函数如下所示:
intSACM_S480_Initial(intInit_Index)//初始化
voidSACM_S480_ServiceLoop(void)//获取语音资料,填入译码队列
voidSACM_S480_Play(intSpeech_Index,intChannel,intRamp_Set)
第7章凌阳音频压缩算法276
//播放
voidSACM_S480_Stop(void)//停止播放
voidSACM_S480_Pause(void)//暂停播放
voidSACM_S480_Resume(void)//暂停后恢复
voidSACM_S480_Volume(Volume_Index)//音量的控制
unsignedintSACM_S480_Status(void)//获取模块的状态
CallF_FIQ_Service_SACM_S480//中断服务函数
各函数具体内容如下:
1)【API格式】C:intSACM_S480_Initial(intInit_Index)
ASM:R1=[Init_Index]
CallF_SACM_S480_Initial
【功能说明】SACM_S480语音播放之前的初始化.
【参数】Init_Index=0表示手动方式;Init_Index=1则表示自动方式.
【返回值】0:代表语音模块初始化失败
1:代表初始化成功.
【备注】该函数用于对定时器,中断和DAC等的初始化.
2)【API格式】C:voidSACM_S480_ServiceLoop(void)
ASM:CallF_SACM_S480_ServiceLoop
【功能说明】从资源中获取SACM_S480语音资料,并将其填入解码队列中.
【参数】无.
【返回值】无.
【备注】播放语音文件中数据,当出现FFFFFFH数据时便停止播放.
3)【API格式】
C:intSACM_S480_Play(intSpeech_Index,intChannel,intRamp_Set);
ASM:R1=[Speech_Index]
R2=[Channel]
R3=[Ramp_Set]
CallSACM_S480_Play
【功能说明】播放资源中SACM_S480语音.
【参数】Speech_Index表示语音索引号.
Channel:1.通过DAC1通道播放;
2.通过DAC2通道播放;
3.通过DAC1和DAC2双通道播放.
Ramp_Set:0.禁止音量增/减调节;
1.仅允许音量增调节;
2.仅允许音量减调节;
3.允许音量增/减调节.
【返回值】无.
第7章凌阳音频压缩算法277
【备注】
①SACM_S480的数据率有4.8Kbps\7.2Kbps三种,可在同一模块的几种算法中自
动选择一种.
②Speech_Index是定义在resource.inc文件中资源表(T_SACM_S480_SpeechTable)
的偏移地址.
③中断服务子程序中F_FIQ_Service_SACM_S480必须放在TMA_FIQ中断向量
上(参见SPCE的中断系统).
④函数允许TimerA以所选的的数据采样率(计数溢出)中断.
程序7-3以自动方式播放一段SACM_S480语音,并自动结束.(见光盘)
SACM_S480自动方式主程序流程见图7.8:
SACM_S480放音的初
始化
SACM_S480压缩播放
获取语音数据并解码
等待中断播放
图7.8SACM_S480自动方式主程序流程
中断流程同上.
前台程序:
//*******************************************************************************************/
//描述:s480只有自动播放方式,在中断FIQ的FIQ_TMA中断源中通过
//主程序的SACM_S480_ServiceLoop()对语音数据进行解码,然后将其
//送入DAC通道播放
//*******************************************************************************************/
#include"s480.h"
#defineSpeech_10
#defineDAC11
#defineDAC22
#defineRamp_UpDn_Off0
#defineRamp_UpDn_On3
#defineAuto1
//=====================================================================
//函数:main()
第7章凌阳音频压缩算法278
//=====================================================================
main()
{
SACM_S480_Initial(1);//自动方式播放初始化
SACM_S480_Play(Speech_1,DAC1+DAC2,Ramp_UpDn_On);
//定义语音索引号,播放通道,允许音量增/减调节
while(SACM_S480_Status()&0x01)//是否播放结束
SACM_S480_ServiceLoop();//获取语音数据并将其填入解码队列
}
背景程序:
.TEXT
.INCLUDEhardware.inc
.INCLUDES480.inc
.PUBLIC_FIQ;
_FIQ:
PUSHR1,R4TO[sp];//入栈保护
R1=0x2000;
TESTR1,[P_INT_Ctrl];//是否为定时器A中断
JNZL_FIQ_TimerA;
R1=0x0800;
TESTR1,[P_INT_Ctrl];//是否为定时器B中断
JNZL_FIQ_TimerB;
L_FIQ_PWM:
R1=C_FIQ_PWM;
[P_INT_Clear]=R1;//清中断
POPR1,R4from[SP];//恢复现场
RETI;
L_FIQ_TimerA://定时器A中断处理
[P_INT_Clear]=R1;//清中断
CALLF_FIQ_Service_SACM_S480;//调用S480中断服务函数
POPR1,R4FROM[SP];//恢复现场
RETI;
L_FIQ_TimerB://定时器B中断处理
[P_INT_Clear]=R1;//清中断
POPR1,R4FROM[SP];//恢复现场
RETI;//中断返回
注:自动放音时,当语音资源文件中的资料为FFFFFFH时便停止播放.
4)【API格式】C:voidSACM_S480_Stop(void);
ASM:CallF_SACM_S480_Stop
【功能说明】停止播放SACM_S480语音.
【参数】无.
【返回值】无.
第7章凌阳音频压缩算法279
5)【API格式】C:voidSACM_S480_Pause(void);
ASM:CallF_SACM_S480_Pause
【功能说明】暂停播放SACM_S480语音.
【参数】无.
【返回值】无.
6)【API格式】C:voidSACM_S480_Resume(void);
ASM:CallF_SACM_S480_Resume
【功能说明】恢复暂停播放的SACM_S480语音.
【参数】无.
【返回值】无.
7)【API格式】C:voidSACM_S480_Volume(Volume_Index);
ASM:R1=[Volume_Index]
CallF_Model-Index_Volume
【功能说明】在播放SACM_S480语音时改变主音量.
【参数】Volume_Index为音量数,音量从最小到最大可在0~15之间选择.
【返回值】无.
8)【API格式】C:unsignedintSACM_S480_Status(void);
ASM:CallF_SACM_S480_Status
[返回值]=R1
【功能说明】获取SACM_S480语音播放的状态.
【参数】无.
【返回值】当R1的值bit0=0,表示语音播放结束;bit0=1,表示语音在播放中.
9)【API格式】ASM:CallF_FIQ_Service_SACM_S480
【功能说明】用作SACM_S480语音背景程序的中断服务子程序.通过前台子程
序(自动方式的SACM_S480_ServiceLoop及手动方式的
SACM_S480_Decode)对语音资料进行解码,然后将其送入DAC通道
播放.
【参数】无.
【返回值】无.
【备注】SACM_S480语音背景子程序只有汇编指令形式,且应将此子程序
安置在TMA_FIQ中断源上.
7.3.4SACM_S240
该压缩算法的压缩比较大80:1.5,价格低,适用于对保真度要求不高的场合,如玩具
类产品的批量生产,编码率仅为2.4Kbps.
其相关API函数如下所示:
intSACM_S240_Initial(intInit_Index)//初始化
voidSACM_S240_ServiceLoop(void)//获取语音资料,填入译码队列
voidSACM_S240_Play(intSpeech_Index,intChannel,intRamp_Set)
第7章凌阳音频压缩算法280
//播放
voidSACM_S240_Stop(void)//停止播放
voidSACM_S240_Pause(void)//暂停播放
voidSACM_S240_Resume(void)//暂停后恢复
voidSACM_S240_Volume(Volume_Index)//音量控制
unsignedintSACM_S240_Status(void)//获取模块状态
CallF_FIQ_Service_SACM_S240//中断服务函数
下面具体介绍一下各个函数:
1)【API格式】C:intSACM_S240_Initial(intInit_Index)
ASM:R1=[Init_Index]
CallF_SACM_S240_Initial
【功能说明】SACM_S240语音播放之前的初始化.
【参数】Init_Index=0表示手动方式;Init_Index=1则表示自动方式.
【返回值】0:代表语音模块初始化失败
1:代表初始化成功.
【备注】函数用于S240语音译码的初始化以及相关设备的初始化.
2)【API格式】C:voidSACM_S240_ServiceLoop(void)
ASM:CallF_SACM_S240_ServiceLoop
【功能说明】从资源中获取SACM_S240语音资料,并将其填入解码队列中.
【参数】无.
【返回值】无.
3)【API格式】
C:intSACM_S240_Play(intSpeech_Index,intChannel,intRamp_Set);
ASM:R1=[Speech_Index]
R2=[Channel]
R3=[Ramp_Set]
CallSACM_S240_Play
【功能说明】播放资源中SACM_S240语音.
【参数】Speech_Index表示语音索引号.
Channel:1.通过DAC1通道播放;
2.通过DAC2通道播放;
3.通过DAC1和DAC2双通道播放.
Ramp_Set:0.禁止音量增/减调节;
1.仅允许音量增调节;
2仅允许音量减调节;
3.允许音量增/减调节.
【返回值】无.
【备注】
①SACM_S240的数据率为2.4Kbps,
第7章凌阳音频压缩算法281
②Speech_Index是定义在resource.inc文件中资源表(T_SACM_S240_SpeechTable)
的偏移地址
③中断服务子程序F_FIQ_Service_SACM_S240必须安置在TMA_FIQ中断向量
上(参见第五章中断系统内容).
④函数允许TimerA以所选的的数据采样率(计数溢出)中断.
程序7-4以自动方式播放一段SACM_S240语音,并自动结束.(见光盘)
SACM_S240在自动方式下的主程序流程见图7.9:
S240放音的初始化
SACM_S240压缩播放
播放下一段语音
获取语音数据并解码
等待中断播放
判断语
音是否播放完毕是否为
"1"


图7.9SACM_S240在自动方式下的主程序流程
//*******************************************************************************************/
//名称:S240
//描述:s240只有自动播放方式,在中断FIQ的FIQ_TMA中断源中通过
//主程序的SACM_S240_ServiceLoop()对语音数据进行解码,然后将其
//送入DAC通道播放
//日期:2002/12/6
//*******************************************************************************************/
#include"hardware.h"
#include"s240.h"
#defineDAC11
#defineDAC22
#defineRamp_UpDn_Off0
#defineRamp_Up_On1
第7章凌阳音频压缩算法282
#defineRamp_Dn_On2
#defineRamp_UpDn_On3
#defineMaxSpeechNum3//播放语音的最大个数
#defineAuto1
//========================================================================
//函数:main()
//========================================================================
main()
{
intSpeechIndex=0;//选择第一首语音
while(1)
{
SACM_S240_Initial(Auto);//自动方式播放初始化
SACM_S240_Play(SpeechIndex,DAC1+DAC2,Ramp_UpDn_On);//播放第一首
while(SACM_S240_Status()&0x01)//判断第一首是否播完
SACM_S240_ServiceLoop();//获取语音数据并将其填入解码队列
SpeechIndex++;
if(SpeechIndex==3)//修改播放语音序号
SpeechIndex=0;
}
}
//========================================================================
//函数:FIQ()
//========================================================================
.TEXT
.INCLUDEhardware.inc
.INCLUDES240.inc
.INCLUDEResource.inc
.EXTERNALF_FIQ_Service_SACM_S240;
.PUBLIC_FIQ;
_FIQ:
PUSHR1,R4TO[SP];//入栈保护
R1=0x2000;
TESTR1,[P_INT_Ctrl];//是否为定时器A中断
JNZL_FIQ_TimerA;
R1=0x0800;
TESTR1,[P_INT_Ctrl];//是否为定时器B中断
JNZL_FIQ_TimerB;
L_FIQ_PWM:
R1=C_FIQ_PWM;
[P_INT_Clear]=R1;//清中断
POPR1,R4FROM[sp];//恢复现场
第7章凌阳音频压缩算法283
RETI;//中断返回
L_FIQ_TimerA://定时器A中断处理
[P_INT_Clear]=R1;//清中断
CALLF_FIQ_Service_SACM_S240;//调用S240中断服务函数
POPR1,R4FROM[sp];//恢复现场
RETI;//中断返回
L_FIQ_TimerB://定时器B中断处理
[P_INT_Clear]=R1;//清中断
POPR1,R4FROM[sp];//恢复现场
RETI;//中断返回
注:自动放音时,当语音资源文件中的资料为FFFFFFH时便停止播放.
4)【API格式】C:voidSACM_S240_Stop(void);
ASM:CallF_SACM_S240_Stop【功能说明】停止播放SACM_S240语音.
【参数】无.
【返回值】无.
5)【API格式】C:voidSACM_S240_Pause(void);
ASM:CallF_SACM_S240_Pause
【功能说明】暂停播放SACM_S240语音.
【参数】无.
【返回值】无.
6)【API格式】C:voidSACM_S240_Resume(void);
ASM:CallF_SACM_S240_Resume
【功能说明】恢复暂停播放的SACM_S240语音的播放.
【参数】无.
【返回值】无.
7)【API格式】C:voidSACM_S240_Volume(Volume_Index);
ASM:R1=[Volume_Index]
CallFSACM_S240_Volume
【功能说明】在播放SACM_S240语音时改变主音量.
【参数】Volume_Index为音量数,音量从最小到最大可在0~15之间选择.
【返回值】无.
8)【API格式】C:unsignedintSACM_S240_Status(void);
ASM:CallF_SACM_S240_Status
[返回值]=R1
【功能说明】获取SACM_S240语音播放的状态.
第7章凌阳音频压缩算法284
【参数】无.【返回值】当R1中bit0=0,表示语音播放结束;bit0=1,表
示语音在播放中.
9)【API格式】ASM:CallF_FIQ_Service_SACM_S240
【功能说明】用作SACM_S240语音背景程序的中断服务子程序.通过前台子程
序(自动方式的SACM_S240_ServiceLoop及手动方式的
Model-Index_Decode)对语音资料进行译码,然后将其送入DAC通道
播放.
【参数】无.
【返回值】无.
【备注】SACM_S240语音背景子程序只有汇编指令形式,且应将此子程序
安置在TMA_FIQ中断源上.
7.3.5SACM_MS01
该算法较繁琐,但只要具备音乐理论,配器法和声学知识了解SPCE编曲格式者
均可尝试.遵照SPCE编曲格式用DTM&MIDI(音源+MIDI键盘+作曲软件)的方
法演奏自动生成*.mid文件,再用凌阳MIDI2POP.EXE转成*.pop文件.但需要专业设
备与软件,具备键盘乐演艺技能,了解SPCE编曲格式.对于初学者或非专业用途一
般了解放音或录放音即可.
其相关API函数如下所示:
voidSACM_MS01_Initial(intInit_Index)//初始化
voidSACM_MS01_ServiceLoop(void)//获取语音资料,填入译码队列
voidSACM_MS01_Play(intSpeech_Index,intChannel,intRamp_Set)
//播放
voidSACM_MS01_Stop(void)//停止播放
voidSACM_MS01_Pause(void)//暂停播放
voidSACM_MS01_Resume(void)//暂停后恢复
voidSACM_MS01_Volume(Volume_Index)//音量控制
unsignedintSACM_MS01_Status(void)//获取模块状态
voidSACM_MS01_ChannelOn(intChannel)//接通通道
voidSACM_MS01_ChannelOff(intChannel)//关闭通道
voidSACM_MS01_Setlnstrument(Channel,Instrument,Mode)
//设置乐曲配器类型
中断服务函数:
ASM:F_FIQ_Service_SACM_MS01
ASM:F_IRQ2_Service_SACM_MS01
ASM:F_IRQ4_Service_SACM_MS01
下面具体的介绍一下各个函数:
1)【API格式】C:voidSACM_MS01_Initial(intInit_Index)
第7章凌阳音频压缩算法285
ASM:R1=[Init_Index]
CallF_SACM_MS01_Initial
【功能说明】SACM_MS01语音播放之前的初始化:设置中断源,定时器和播放
方式(手动,自动)
【参数】Init_Index=0表示手动方式;Init_Index=1则表示自动方式.
Init_Index:
0:代表PWM音频输出方式
1:DAC音频输出方式下24K的播放率.
2:DAC音频输出方式下20K的播放率.
3:DAC音频输出方式下16K的播放率.
【返回值】0:代表语音模块初始化失败
4:代表SACM_MS01初始化成功.
【备注】
①该函数初始化MS01的译码器,以及系统时钟(Systemclock)TimerA,TimerB,
DAC并且以16/20/24KHz采样率触发FIQ_TMA中断.
②初始化后会接通所有播放通道(0~5).
③对于SACM_MS01模块,FIQ中断服务子程序用于从前台程序(SACM_MS01_
ServiceLoop)的执行过程中获取乐曲译码资料;若未来事件不是音符而是由鼓点节奏
引起,则其自适应音频脉冲编码方式(ADPCM)资料将被传入IRQ2进行译码,然后
将二者混合在一起送出DAC通道播放.
2)【API格式】C:voidSACM_MS01_ServiceLoop(void)
ASM:CallF_SACM_MS01_ServiceLoop
【功能说明】从资源中获取SACM_MS01语音资料,并将其填入译码队列自动译
码.
【参数】无.
【返回值】无.
3)【API格式】
C:intSACM_MS01_Play(intSpeech_Index,intChannel,intRamp_Set);
ASM:R1=[Speech_Index]
R2=[Channel]
R3=[Ramp_Set]
CallSACM_MS01_Play
【功能说明】开始播放一种SACM_MS01音调.
【参数】Speech_Index表示语音索引号.
Channel:1:通过DAC1通道播放;
2:通过DAC2通道播放;
3:通过DAC1和DAC2双通道播放.
Ramp_Set:0:禁止音量增/减调节;
1:仅允许音量增调节;
2:仅允许音量减调节;
第7章凌阳音频压缩算法286
3:允许音量增/减调节.
【返回值】无.
【备注】
①SACM_MS01的数据率有16Kbps\20Kbps\24Kbps三种,可在同一模块的几种算
法中自动选择一种.
②Speech_Index是定义在resource.inc文件中资源表(T_
SACM_MS01_SpeechTable)的偏移地址.
③中断服务子程序中F_FIQ_Service_SACM_MS01必须放在TMA_FIQ中断向量
上.
程序7-5采用SACM_MS01自动方式播放一段音调:(见光盘)
前台程序:
#definePWM0
#defineDAC_24K1
#defineDAC_20K2
#defineDAC_16K3
#defineDAC11
#defineDAC22
#defineRamp_UpDn_Off0
#defineRamp_Up_On1
#defineRamp_Dn_On2
#defineRamp_UpDn_On3
Main()
{
SACM_MS01_Initial(1);//MS01初始化
SACM_MS01_Play(Speech_1,DAC1+DAC2,Ramp_UpDn_On);//放音
while(SACM_MS01_Status()&0x01)//是否播放完一段语音
{
SACM_MS01_ServiceLoop();//解码并填充队列
}
}
背景程序:
_FIQ:
PUSHregisters
CALLF_FIQ_Service_SACM_MS01;//4通道的也配器服务程序
CLEARinterruptflag
POPregisters
RETI;
_IRQ2:
PUSHregisters
CALLF_IRQ2_Service_SACM_MS01;//2通道鼓点节奏服务程序
CLEARinterruptflag
第7章凌阳音频压缩算法287
POPregisters
RETI;
_IRQ4:
PUSHregisters
CALLF_IRQ4_Service_SACM_MS01;//控制节拍服务程序
CLEARinterruptflag
POPregisters
RETI;
4)【API格式】C:voidSACM_MS01_Stop(void);
ASM:CallF_SACM_MS01_Stop【功能说明】停止播放SACM_MS01乐曲.
【参数】无.
【返回值】无.
5)【API格式】C:voidSACM_SACM_MS01_Pause(void);
ASM:CallF_SACM_MS01_Pause
【功能说明】暂停播放SACM_MS01乐曲.
【参数】无.
【返回值】无.
6)【API格式】C:voidSACM_MS01_Resume(void);
ASM:CallF_SACM_MS01_Resume
【功能说明】恢复暂停播放的SACM_MS01语音或乐曲.
【参数】无.
【返回值】无.
7)【API格式】C:voidSACM_MS01_Volume(intVolume_Index);
ASM:R1=[Volume_Index]
CallFSACM_MS01_Volume
【功能说明】在播放SACM_MS01语音时改变主音量.
【参数】Volume_Index为音量数,音量从最小到最大可在0~15之间选择.
【返回值】无.
8)【API格式】C:unsignedintSACM_MS01_Status(void);
ASM:CallF_SACM_MS01_Status
[Return_Value]=R1
【功能说明】获取SACM_MS01合成音乐播放的状态.
【参数】无.
【返回值】当R1中bit0=0,表示语音播放结束;bit0=1,表示语音在播放中.
还有其它状态位(bit8~bit13),见图7.10.
第7章凌阳音频压缩算法288288
0:通道1关断
1:通道1接通(鼓点节奏2)
0:通道2关断
1:通道2接通(音符1)
图7.10SACM_MS01部分状态返回值
9)【API格式】C:voidSACM_MS01_ChannelOn(intChannel);
ASM:R1=[Channel]
CallF_SACM_MS01_ChannelOn
【功能说明】将SACM_MS01乐曲播放通道之一接通.
【参数】Channel为0~5之间整数,其中0,1代表鼓点节奏通道,2~5则代
表音符通道.
【返回值】无.
10)【API格式】C:voidSACM_MS01_ChannelOff(intChannel);
ASM:R1=[Channel]
CallF_SACM_MS01_ChannelOff
【功能说明】将SACM_MS01乐曲播放通道之一关断.
【参数】Channel为0~5之间整数,其中0,1代表鼓点节奏通道,2~5则代
表音符通道.【返回值】无.
程序7-6
intmain()
{
SACM_MS01_Initial(DAC_24K);//选择DAC24K播放方式,且6个通道都接通
SACM_MS01_ChannelOff(0);//通道0被关断(鼓点节奏1)
SACM_MS01_ChannelOff(5);//通道5被关断(音符4,频率Tone方式)
SACM_MS01_Play(SongIndex,DAC1+DAC2);//开始播放乐曲
while(SACM_MS01_Status()&0x01)//若状态返回值的bit0=1
{
SACM_MS01_ServiceLoop();//SACM_MS01乐曲播放的译码程序
}
}
11)【API格式】
C:voidSACM_MS01_SetInstrument(intChannel,intInstrument,intMode);
ASM:R1=[Channel]
0
0:通道4关断
1:通道4接通(音符3)
03关断
1:通道3接通(音符2)
0:通道5关断
1:通道5接通(音符4)
bit13bit12bit11bit10bit8bit9
:通道0
1
0关断
:通道0接通(鼓点节奏1)
:通道
第7章凌阳音频压缩算法289
R2=[Instrument]
R3=[Mode]
CallF_SACM_MS01_SetInstrument
【功能说明】在SACM_MS01的一个播放通道上改变乐曲配器类型.
【参数】Channel=0~5;其中0,1代表鼓点节奏通道,2~5则代表音符通道.
对于通道0,1,Instrument=0~Max_Drum#;表不同的鼓点节奏;
对于通道2~5,Instrument=0~34;表不同的乐曲配器类型.
Mod=0,1;分别代表配器类型可以或不可通过乐曲事件改变.
【返回值】无.
12)【API格式】ASM:CallF_FIQ_Service_SACM_MS01
ASM:CallF_IRQ2_Service_SACM_MS01
ASM:CallF_IRQ4_Service_SACM_MS01
【功能说明】SACM_MS01模块,FIQ中断服务子程序用于从前台程序
(SACM_MS01_ServiceLoop)的执行过程中获取乐曲译码资料;若未来事件不是音符
而是由鼓点节奏引起,则其自适应音频脉冲编码方式(ADPCM)资料将被传入IRQ2
进行译码,然后将二者混合在一起送出DAC通道播放.
【参数】无.
【返回值】无.
【备注】
①SACM_MS01语音背景子程序只有汇编指令形式
②中断服务子程序必须在TMA_FIQ中断源上.
③应将两个额外的中断服务子程序分别安置在IRQ2_TMB和IRQ4_1K中断源
上.
7.3.6SACM_DVR
SACM-DVR具有录音和放音功能,并采用SACM_A2000的算法,录音时采用16K
资料率及8K采样率获取语音资源,经过SACM_A2000压缩后存储在扩展的SRAM
628128A里,录满音后自动开始放音.
其相关API函数如下所示:
intSACM_DVR_Initial(intInit_Index)//初始化
voidSACM_DVR_ServiceLoop(void)//获取资料,填入译码队列
voidSACM_DVR_Encode(void)//录音
SACM_DVR_StopEncoder();//停止编码
SACM_DVR_InitEncoder(RceMonitorOn)//初始化编码器
voidSACM_DVR_Stop(void)//停止录音
voidSACM_DVR_Play(void)//开始播放
unsignedintSACM_DVR_Status(void)//获取SACM_DVR模块的状态
voidSACM_DVR_InitDecoder(intChannel)//开始译码
voidSACM_DVR_Decode(void)//获取语音资料并译码,中断播放
SACM_DVR_StopDecoder();//停止解码
第7章凌阳音频压缩算法290
unsignedintSACM_DVR_TestQueue(void)//获取语音队列状态
intSACM_DVR_Fetchqueue(void)//获取录音编码数据
voidSACM_DVR_FillQueue(unsignedintencoded-data)//填充资料到语音队列,等待播放
intGetResource(longAddress)——(Manual)//从资源文件里获取一个字型语音资

中断服务函数:
CallF_FIQ_Service_SACM_DVR//playing
CallF_IRQ1_Service_SACM_DVR//recode
具体函数如下:
1)【API格式】C:voidSACM_DVR_Initial(intInit_Index)
ASM:R1=[Init_Index]
CallF_SACM_DVR_Initial
【功能说明】SACM_DVR语音播放之前的初始化:设置中断源,定时器以及播
放方式(自动,手动)
【参数】Init_Index=0表示手动方式;Init_Index=1则表示自动方式.
【返回值】无
【备注】
①对于SACM_DVR模块,需要一些I/O口来连接外部的SRAM,用以存放录音
资料.
②录放音的格式采用SACM_A2000.
2)【API格式】C:voidSACM_DVR_ServiceLoop(void)
ASM:CallF_SACM_DVR_ServiceLoop
【功能说明】在录音期间从ADC通道获取录音资料,且将其以SACM_A2000格
式进行编码后存入外接SRAM中;而在播放期间从SRAM中获取语音资料,对其进行
解码,然后等候中断服务子程序将其送出DAC通道.
【参数】无.
【返回值】无.
3)【API格式】C:voidSACM_DVR_Encode(void);
ASM:CallF_SACM_DVR_Encode
【功能说明】开始以自动方式录制声音资料到外接SRAM中.
【参数】无.
【返回值】无.
【备注】该函数仅适用于SACM_DVR模块,且只有自动方式.
4)【API格式】C:voidSACM_DVR_Stop(void);
ASM:CallF_SACM_DVR_Stop
【功能说明】以自动方式停止录音.
【参数】无.
第7章凌阳音频压缩算法291
【返回值】无.
5)【API格式】
C:intSACM_DVR_Play(intSpeech_Index,intChannel,intRamp_Set);
ASM:CallSACM_DVR_Play【功能说明】以自动方式播放外接SRAM
中的录音资料.
【参数】无
【返回值】无.
【备注】该函数仅使用于自动方式下.
6)【API格式】C:unsignedintSACM_DVR_Status(void);
ASM:CallF_SACM_DVR_Status
[返回值]=R1
【功能说明】获取SACM_DVR模块的状态.
【参数】无.
【返回值】当R1中bit0=0,表示语音播放结束;bit0=1,表示语音在播放中.
SACM_DVR模块的状态返回值,如图7.11所示.
bit2bit1bit0
0:录音停止
1:录音中
0:播放停止
1:播放中
:非自动方式
1:自动方式
0
图7.11SACM_DVR状态返回值
【备注】该函数仅使用于DVR的手动方式下.
7)【API格式】C:voidSACM_DVR_InitDecoder(intChannel);
ASM:CallF_SACM_DVR_Decode
【功能说明】开始对SACM_DVR语音资料以非自动方式(编程控制)进行译码.
【参数】Channel=1,2,3;分别表示使用DAC1,DAC2通道以及DAC1和
DAC2双通道.
【返回值】无.
【备注】用户只能通过非自动方式对语音资料解压缩.
8)【API格式】C:voidSACM_DVR_Decode(void);
ASM:CallF_SACM_DVR_Decode
【功能说明】从语音队列里获取的SACM_DVR语音资料,并进行译码,然后通
过中断服务子程序将其送入DAC通道播放.
【参数】无.
【返回值】无.
【备注】用户仅能通过非自动方式对语音资料进行译码.
第7章凌阳音频压缩算法292
9)【API格式】C:unsignedintSACM_DVR_TestQueue(void);
ASM:CallF_SACM_DVR_TestQueue
[返回值]=R1
【功能说明】获取语音队列的状态.
【参数】无.
【返回值】R1=0,语音队列不空不满
=1,语音队列满
=2;语音队列空.
【备注:用户仅能通过非自动方式测试语音队列状态.
10)【API格式】C:intSACM_DVR_FetchQueue(void);
ASM:CallF_SACM_DVR_FetchQueue
[Return_Value]=R1
【功能说明】获取录音编码(SACM_A2000)数据.
【参数】无.
【返回值】16位录音资料.
【备注】
①采用--SACM_A2000编码格式编码
②仅用于非自动方式下
程序7-7外扩SRAM需要SRAM写初始化(InitWriteSRAM),及写(WriteSRAM)
子函数.
SACM_DVR_Initial(Manual);
Addr=0;
InitWriteSRAM();//用户需外接SRAM
SACM_DVR_InitEncoder();
while(Addr
{
SACM_DVR_Encode();//获取数据并译码
If(SACM_DVR_TestQueue()!=Empty)//若队列不空,则存储资料
{
ret=SACM_DVR_FetchQueue();//从队列中得到资料
writeSRAM(Addr,ret);//存入用户存储区
Addr+=2;//两个8位SRAM存储一个16位资料
}
}
11)【API格式】C:voidSACM_DVR_FillQueue(unsignedintencoded-data);
ASM:R1=[语音编码资料]
CallF_SACM_DVR_FillQueue
【功能说明】填充SACM_A2000语音资料到DVR译码器等待播放
【参数】encoded-data为语音编码资料.
【返回值】无.
第7章凌阳音频压缩算法293
【备注】
①语音资料格式为--SACM_A2000编码格式.
②从语音队列里至少每48ms获取48个字资料(16K资料采样率).
③仅用于非自动方式下.
12)【API格式】C:intGetResource(longAddress);
【功能说明】从资源文件里获取一个字型语音资料.
【参数】无.
【返回值】一个字型语音资料.
13)【API格式】ASM:CallF_FIQ_Service_SACM_DVR
ASM:CallF_IRQ1_Service_SACM_DVR
【功能说明】用作SACM_DVR语音背景程序的中断服务子程序.通过前台子
程序(自动方式的SACM_DVR_ServiceLoop及手动方式的SACM_DVR_Decode)对
语音资料进行译码,然后将其送入DAC通道播放.即FIQ中断服务子程序用于声音
播放的背景程序;而IRQ1中断服务子程序则用于声音录制的背景程序.
【参数】无.
【返回值】无.
【备注】SACM_DVR语音背景子程序只有汇编指令形式,且应将此子程序安
置在TMA_FIQ中断源上.额外的中断服务子程序安置在IRQ1_TMA中断源上.
程序7-8DVR以自动方式录放音
前台程序:
intkey;
Main()
{
System_Initial();//键盘初始化
SACM_DVR_Initial(Auto);
while(1)
{
Key=SP_GetCh();//获取键值
switch(Key)
{
case0x0000:
break;
case0x0001:
SACM_DVR_Record();//录音,存储资料到SRAM
break;
case0x0002:
SACM_DVR_Stop();//停止录/放音
break;
第7章凌阳音频压缩算法294
case0x0004:
SACM_DVR_Play();//从SRAM中取出语音资料并播放
break;
default:
break;
}
System_ServiceLoop();//键扫描
SACM_DVR_ServiceLoop();
}//while(1)结束
}
背景程序:
_FIQ:
PUSHregisters;
CALLF_FIQ_Service_SACM_DVR;//放音
CLEARinterruptflag
POPregisters;
RETI;
_IRQ1:
PUSHregisters
CALLF_IRQ1_Service_SACM_DVR;//录音
CLEARinterruptflag
POPregisters;
reti;
注:对于函数System_Initial(),System_ServiceLoop()和SP_GetCh()详见具体的
实验.
程序7-9非自动方式:(见光盘)
DVR手动方式主程序流程见图7.12:
第7章凌阳音频压缩算法295
获取语音队列状态
手动方式
初始化
采用A2000对语
音编码
判断存储语音
的地址是否超出
Sram大小
结束
开始
停止录音
DVR放音
初始化S
SRAM读初始化
录音解码
函数
判断是否满
是否播放完

放音完毕
解码
送入DAC通道
SRAM写初始化
获取数据并
编码
从队列中
获取数据
写数据到
SRAME
修改地址
两个8位
SRAM存储一
个16位数






图7.12DVR手动方式主程序流程
#DEFINEManual0
#DEFINEAuto1
#DEFINESRAM_Size0xffff-2
#DEFINERceMonitorOff0
#DEFINERceMonitorOn1
#DEFINEDAC11
#DEFINEDAC22
#DEFINEFull1
#DEFINEEmpty2
**************录音**************
main(){
SACM_DVR_Initial(Manual);//手动方式初始化
第7章凌阳音频压缩算法296
Addr=0;//定义语音存放的首址变量
InitWriteSRAM();
SACM_DVR_InitEncoder(RceMonitorOn);//开始对A2000的语音资料以非自动方式编

while(Addr
大小
{
SACM_DVR_Encode();//获取数据并编码
if(SACM_DVR_TestQueue()!=Empty)
{
Ret=SACM_DVR_FetchQueue();//从队列中获取资料
WriteSRAM(Addr,Ret);//存入用户定义的存储单元区
Addr+=2;//两个8位SRAM存储一个16位资料
}
}
SACM_DVR_StopEncoder();
}
*********放音*********
main()
{
SACM_DVR_Initial(Manual);//非自动方式播放的初始化
InitReadSRAM();
Addr=0;
SACM_DVR_InitDecoder(DAC1);//开始对A2000的语音资料以非自动方式译码
while(1)
{
if(SACM_DVR_TestQueue()!=Full)//测试并获取语音队列的状态
{
Ret=ReadSRAM(Addr);//从存储区里获取一个字型语音资料
SACM_DVR_FillQueue(Ret);//获取语音编码资料并填入语音队列等候译码
Addr+=2;
}
if(Addrsacm2000.exe16*.wav*.out*.16k
或(e:\>sacm2000.exe20*.wav*.out*.20k
e:\>sacm2000.exe24*.wav*.out*.24k)
SACM_S480:
1)PC机采用8K16位单声道录制一个WAV文件
2)用s480压缩生成4.8k(或7.2k)压缩率的文件
3)在MS-DOS下:
e:\>sacm.exe*.wav*.48k*.out-s48
或(e:\>sacm.exe*.wav*.72k*.out-s72)
第7章凌阳音频压缩算法298
图7.13是凌阳音频压缩编码(SACM)方法的流程:
将需要压缩的WAV文
件转换成8K16位
执行
SACM2000.EXE
进行压缩
(SACM_2000)
执行SACF.EXE,
用音乐编辑器编
辑(SACM_MS01)
文本编辑
生成*.bin文

*16K,20K,24K
的压缩文件
*.WAV文件用
作试听
执行
SACM.EXE进行
压缩
(SACM_480)
执行
SACM240.EXE进
行压缩
(SACM_240)
16k/20k/24kbps
*.WAV文件用
作试听
*.48k,*.72K
的压缩文件
4.8k/7.2kbps
2.4kbps
应用
*16K,20K,
24K的压缩文

应用




应用
应用
对比试听
图7.13凌阳音频压缩编码(SACM)流程
(2)WINDOWS下的压缩:
0是用于压缩的windows工具,可以选择一个或多个WAV文件进行压缩,具体步
骤可根据提示来操作.
第7章凌阳音频压缩算法299
图7.14用于压缩的windows工具
7.5键控放音程序介绍
首先介绍一下程序模块,程序模块中的文件大致分为两类:一类是程序,另一类
则是程序接口.所谓接口一般是针对高一级的程序模块而言.通过接口,高一级的程
序模块可以调用本级程序模块中的子程序或函数,或者使用本级模块中定义的全局变
量.这样做无疑会大大增加软件的可维护性.而程序既可以用C语言编写,亦可用
'nSP的汇编语言编写.
随着对语音编程越来越熟悉,可以考虑加入一些模块化程序,如键盘:这样可以
按键控制语音播放,停止,暂停,恢复以及音量的大小等,这里我们为用户提供了一
个资源使用模块,即接口文件Key.inc,其中定义了供系统级调用的与键扫描相关的一
些子程序.如:键扫描初始化子程序,键扫描子程序,键扫描防抖动处理子程序以及
获得键码子程序等等.模块中的Key.asm文件中则是上述接口中定义的各子程序的程
序实体,以及定义出程序中所需要的全局或局部变量.具体结构见下图.
Key.asm
键扫描初始化子程序
F_Key_Scan_Initial
键扫描子程序
F_Key_Scan_ServiceLoop
键扫描防抖动处理子程序
F_Key_DebounceCnt_Down
键值获取子程序
F_SP_GetCh
图7.15键盘程序结构
下面我们具体介绍一下几个常用的键盘API函数:
F_Key_Scan_Initial//键初始化
F_Key_Scan_ServiceLoop//键盘扫描
F_Key_DebounceCnt_Down//键盘防抖动处理
F_SP_GetCh()//获取键值
第7章凌阳音频压缩算法300
1)【API格式】C:voidKey_Scan_Initial(void)
ASM:CallF_Key_Scan_Initial
【功能说明】键盘扫描初始化.
【参数】无.
【返回值】无.
2)【API格式】C:voidKey_Scan_ServiceLoop(void)
ASM:CallF_Key_Scan_ServiceLoop
【功能说明】键盘扫描服务循环.
【参数】无.
【返回值】无.
3)【API格式】C:voidKey_DebounceCnt_Down(void)
ASM:CallF_Key_DebounceCnt_Down
【功能说明】键盘扫描过程中对键抖动的处理.
【参数】无.
【返回值】无.
4)【API格式】C:unsignedintSP_GetCh(void)
ASM:CallF_SP_GetCh()
[返回值]=R1
【功能说明】从扫描缓冲区内获得键值,并将缓冲区的键值清零.
【参数】无.
【返回值】被按下的键值.
然而在介绍了键盘API函数后我们就会想到要在程序中哪里去调用,这里为了使
程序更具模块化我们又为大家提供了一个系统资源模块:它是建立在上述诸多模块之
上的一个模块,其中许多子程序都调用了在它之下模块中的子程序.为了让上一级的
程序调用本模块System.asm文件中的子程序,有一个接口文件System.inc.这里我们
一般只需要三条调用语句,当然用户也可以在这里面添加一些模块,具体实现可以参
考下面模块框图:
第7章凌阳音频压缩算法301
System.asm
设定一些需要的模块诸
如:语音类型子程序及其
他的初始化
系统初始化
(F_System_Initial)
系统主循环子程序
调用键扫描子程序call
F_Key_Scan_ServiceLoop
调用
键扫描初始化子程序call
F_Key_Scan_Initial
调用
键扫描防抖动处理子程序call
F_Key_DebounceCnt_Down
添加其他服务程序
返回
返回
图7.16调用键盘程序的系统程序结构
这样,对于我们的一个含键盘程序的两个重要模块介绍完了,下面的问题是如何
在主程序中实现整体调用,见下图:
主程序
main.c
系统资源模块
System.asm
系统初始化子程序
System_Initial()
系统主循环子程序
System_ServiceLoop()
键扫描初始化call
F_Key_Scan_Initial
键扫描防抖动
处理子程序call
F_Key_DebounceCnt_Down
键扫描子程序call
F_Key_Scan_ServiceLoop
调用


调用
调用
调用
第7章凌阳音频压缩算法302
图7.17主程序结构
程序7-10(见光盘)
同前面放音一样在最后我们通过一个SACM_A2000按键控制自动放音的例子来
熟悉一下整个程序的执行过程:
********主程序(main.c)**********
main()
{
intKey=0;//初始化键值
intSpeechIndex=0;//初始化语音目录索引号
intVolumeIndex=7;//初始化音量
Ret=System_Initial();
Ret=SACM_A2000_Initial(Auto);
SACM_A2000_Play(SpeechIndex,DAC1+DAC2,Ramp_UpDn_On);
//播放
while(1)
{
Key=SP_GetCh();
switch(Key)
{
case0x00:
break;
case0x01:
SACM_A2000_Play(SpeechIndex,DAC1+DAC2,Ramp_UpDn_On);
//播放
break;
case0x02:
SACM_A2000_Stop();//停止放音
break;
case0x04:
SACM_A2000_Pause();//暂停放音
break;
case0x08:
SACM_A2000_Resume();//暂停后的恢复
break;
case0x10:
VolumeIndex++;
if(VolumeIndex>MaxVolume)
VolumeIndex=MaxVolume;
SACM_A2000_Volume(VolumeIndex);//音量增加
break;
case0x20:
if(VolumeIndex==0)
第7章凌阳音频压缩算法303
VolumeIndex=0;
else
VolumeIndex--;
SACM_A2000_Volume(VolumeIndex);//音量减
break;
case0x40:
SpeechIndex++;//播放下一首
if(SpeechIndex==MaxSpeechNum)
SpeechIndex=0;
SACM_A2000_Play(SpeechIndex,DAC1+DAC2,Ramp_UpDn_On);
break;
case0x80:
if(SpeechIndex==0)//播放前一首
SpeechIndex=MaxSpeechNum;
SpeechIndex--;
SACM_A2000_Play(SpeechIndex,DAC1+DAC2,Ramp_UpDn_On);
break;
default:
break;
}
System_ServiceLoop();//调用系统初始化
SACM_A2000_ServiceLoop();
//获取A2000资料并填入译码队列等待播放
}
}
***********系统子程序(System.asm)****************
.public_System_Initial;
.publicF_System_Initial;
_System_Initial:.PROC
F_System_Initial:
CALLF_Key_Scan_Initial;//键盘扫描
//可以添加一些语音类型子程序或初始化内容
RETF
.ENDP;.
.public_System_ServiceLoop;
.publicF_System_ServiceLoop;
_System_ServiceLoop:.PROC
F_System_ServiceLoop:
CALLF_Key_DebounceCnt_Down;//调用键扫描防抖动处理子程序
CALLF_Key_Scan_ServiceLoop;//调用键扫描子程序
//可在次添加其它服务程序
RETF;
.ENDP;
**************键盘子程序(Key.asm)*************
第7章凌阳音频压缩算法304
.ram
.varR_DebounceReg;
.DEFINEC_DebounceCnt0x0002;
.varR_DebounceCnt;
.varR_KeyBuf;
.varR_KeyStrobe;
.CODE
***键扫描初始化*********************************
F_Key_Scan_Initial:
R1=0x0000;
[R_DebounceReg]=R1;//R_DebounceReg初始化为0
[R_KeyBuf]=R1;//R_KeyBuf初始化为0
[R_KeyStrobe]=R1;//R_KeyStrobe初始化为0
r1=C_DebounceCnt;
[R_DebounceCnt]=R1;//设定记数初值
RETF;
***键扫描**************************************
F_Key_Scan_ServiceLoop:
R1=[P_IOA_Data];//由IOA口获取键值
R1=R1and0xff;//保留键值
R2=[R_DebounceReg];//将上次获取的键值送给R2
[R_DebounceReg]=R1;//将当前键值送给R_DebounceReg
CMPR2,[R_DebounceReg];//比较两次采样的键值是否相同
JEL_KS_StableTwoSample;//是,则转
R1=C_DebounceCnt;//否,则设定记数的时间
[R_DebounceCnt]=R1;
RETF;
L_KS_StableTwoSample:
R1=[R_DebounceCnt];//判断记数值是否为零
JZL_KS_StableOverDebounce;//是,则转
RETF;
L_KS_StableOverDebounce:
R2=[R_DebounceReg];//将当前采样的键值送给R2
R1=[R_KeyBuf];//暂存上次R_KeyBuf里的键值到R1
[R_KeyBuf]=R2;//当前键值送给R_KeyBuf
R1=R1xor0x00ff;//R1低8位取返
R1=R1and[R_KeyBuf]//R1低8位取返后和当前的键值与
R1=R1and0x00ff;//保留与的结果既最后确定的键值
R1=R1OR[R_KeyStrobe];
[R_KeyStrobe]=R1;//送键值到R_KeyStrobe单元
RETF;
***键扫描防抖动处理******************************
F_Key_DebounceCnt_Down:
第7章凌阳音频压缩算法305
R1=[R_DebounceCnt];
//读取记数单元R_DebounceCnt的值
JZL_DebounceCntZero;
//如果R_DebounceCnt单元为零则停止记数
R1-=0x0001;
[R_DebounceCnt]=R1;
L_DebounceCntZero:
RETF;
*******取键值**********************************
_SP_GetCh:
F_SP_GetCh:
R1=[R_KeyStrobe];//取键值
R2=0x0000;//清零R_KeyStrobe单元
[R_KeyStrobe]=R2;
RETF;
(注意:以上程序模块只介绍主要程序部分,未加入伪指令部分内容,仅供学习
参考)
7.6语音辨识
在前面我们已经介绍过语音辨识的一些相关的内容,在这里我们给出SPCE061的
特定语者辨识SD(SpeakerDependent)的一个例子以供有兴趣者参考.SD即语音样
板由单个人训练,也只能识别训练某人的语音命令,而他人的命令识别率较低或几乎
不能识别.
图7.18是语音辨识的一个整体框图:
辨识部分
初始化
BSR_DeleteSDG
roup(0)
辨识处理
BSR_GetResult
()
启动实时监控
BSR_EnableCPU
Indicator()
调用训练模块
TrainWord(int
WordID,int
RespondID)
初始化识别器
BSR_InitRecogni
zer(BSR_MIC)
图7.18语音辨识原理框图
同样语音辨识也将其一些功能作成模块,并通过API调用来实现这些功能,在这
里我们为大家介绍一些常用的API函数,如果有兴趣者可以登陆我们的网站去获得更
第7章凌阳音频压缩算法306
多的相关内容
初始化:
【API格式】C:intBSR_DeleteSDGroup(0);
ASM:F_BSR_DeleteSDGroup(0)
【功能说明】SRAM初始化.
【参数】该参数是辨识的一个标识符,0代表选择SRAM,并初始化.
【返回值】当SRAM擦除成功返回0,否则,返回-1.
训练部分:
1)【API格式】C:intBSR_Train(intCommandID,intTraindMode);
ASM:F_BSR_Train
【功能说明】训练函数.
【参数】
CommandID:命令序号,范围从0x100到0x105,并且对于每组训练语句都是
唯一的.
TraindMode:训练次数,要求使用者在应用之前训练一或两遍:
BSR_TRAIN_ONCE:要求训练一次.
BSR_TRAIN_TWICE要求训练两次.
【返回值】训练成功,返回0;没有声音返回-1;训练需要更多的语音数据来
训练,返回-2;当环境太吵时,返回-3;当数据库满,返回-4;当两次输入命令不
通,返回-5;当序号超出范围,返回-6.
【备注】
①在调用训练程序之前,确保识别器正确的初始化.
②训练次数是2时,则两次一定会有差异,所以一定要保证两次训练结果接近
③为了增强可靠性,最好训练两次,否则辨识的命令就会倾向于噪音
④调用函数后,等待2秒开始训练,每条命令只有1.3秒,也就是说,当训练
命令超出1.3秒时,只有前1.3秒命令有效.
辨识部分:
1)【API格式】C:voidBSR_InitRecognizer(intAudioSource)
ASM:F_BSR_InitRecognizer
【功能说明】辨识器初始化.
【参数】定义语音输入来源.通过MIC语音输入还是LINE_IN电压模拟量
输入.
【返回值】无.
2)【API格式】C:intBSR_GetResult();
ASM:F_BSR_GetResult
【返回值】=R1
【功能说明】辨识中获取数据.
【参数】无.
【返回值】
第7章凌阳音频压缩算法307
当无命令识别出来时,返回0;
识别器停止未初始化或识别未激活返回-1;
当识别不合格时返回-2;
当识别出来时返回命令的序号.
`【备注】该函数用于启动辨识,BSR_GetResult();
3)【API格式】C:voidBSR_StopRecognizer(void);
ASM:F_BSR_StopRecognizer
【功能说明】停止辨识.
【参数】无.
【返回值】无.
【备注】该函数是用于停止识别,当调用此函数时,FIQ_TMA中断将关闭.
中断部分:
【API格式】ASM:_BSR_InitRecognizer
【功能说明】在中断中调用,并通过中断将语音信号送DAC通道播放.
【参数】无.
【返回值】无.
【备注】
①该函数在中断FIQ_TMA中调用
②当主程序调用BSR_InitRecognizer时,辨识器便打开8K采样率的FIQ_TMA
中断并开始将采样的语音数据填入辨识器的数据队列中.
③应用程序需要设置一下程序段在FIQ_TMA中:
.PUBLIC_FIQ
.EXTERNAL_BSR_FIQ_Routine//定义全局变量
.TEXT
_FIQ:
PUSHR1,R4to[SP]//寄存器入栈保护
R1=[P_INT_Ctrl]
CALL_BSR_FIQ_Routine//调用子程序
R1=0x2000//清中断标志位
[P_INT_Clear]=R1
POPR1,R4from[SP];//寄存器组出栈
RETI
END
其中实时监控是用来观察辨识是否正常工作,如果辨识正常则会产生一16ms连
续稳定方波如图7.19否则如果CPU超载则会产生不稳定波形如图7.20,此时需要删
除命令,或是优化程序否则会丢失语音数据产生辨识出现错误的信息.
第7章凌阳音频压缩算法308
16ms16ms
16ms
图7.19辨识正常产生的方波
图7.20CPU超载产生的波形
程序7-11(见光盘)
以下是特定人辨识的一个范例:
在程序中我们通过三条语句的训练演示特定人连续音识别,其中第一条语句为触发名
称.另外两条为命令,训练完毕开始辨识当识别出触发名称后,开始发布命令,则会
听到自己设置的应答,具体命令如下:
****************训练******************************************
提示音输入语音
--------------------------------------------------------------------------------------------------------
"请输入触发名称""警卫"
"请输入第一条命令""开枪"
"请输入第二条命令""你在干什么"
"请再说一遍"(以上提示音每说完一遍出现此命令)
"没有听到任何声音"(当没有检测到声音时出现此命令)
"两次输入名称不相同"(当两次输入的名称不同时出现此命令)
"两次输入命令不相同"(当两次输入的命令有差异时出现此命令)
"准备就绪,请开始辨识"(以上三条语句全部训练成功时,进入识别)
*****************识别**********************************************************************
发布命令应答
----------------------------------------------------------------------------------------------------------
"警卫""在"/"长官"
"开枪""枪声"
"你在干什么""我在巡逻"/"我在休息"/"我在等人"
注意:在每次提示音结束后2-3秒再输入命令或当上次应答结束2-3秒后再发布命
第7章凌阳音频压缩算法309

主程序流程如0
图7.21主程序流程
#INCLUDE"bsrsd.h"
#DEFINENAME_ID0x100
#DEFINECOMMAND_ONE_ID0x101
#DEFINECOMMAND_TWO_ID0x102
#DEFINERSP_INTR0
#DEFINERSP_NAME1
#DEFINERSP_FIRE2
#DEFINERSP_GUARD3
#DEFINERSP_AGAIN4
#DEFINERSP_NOVOICE5
#DEFINERSP_NAMEDIFF6
#DEFINERSP_CMDDIFF7
#DEFINERSP_STAR8
#DEFINERSP_MASTER9
#DEFINERSP_HERE10
#DEFINERSP_GUNSHOT0
#DEFINERSP_PATROL11
#DEFINERSP_READY12
定义存储器为
调用第一条提示音播放
训练第一条命令
开始识别
训练第二条命令
训练名称
成功否
成功否
启动实时监控
辨识器初始化
调用提示辨识音播放
获取语音数据
辨识主循环


初始化


成功否


第7章凌阳音频压缩算法310
#DEFINERSP_COPY13
#DEFINERSP_NOISY14
//..................全程变量..................……………………………………………………………………….
intgActivated=0;
//该变量用于检测是否有触发命令,当有识别出语句为触发名称则该位置1
intgTriggerRespond[]={RSP_MASTER,RSP_HERE,RSP_MASTER};
//第一条命令应答
intgComm2Respond[]={RSP_PATROL,RSP_READY,RSP_COPY};
//第二条命令应答
externvoidClearWatchDog();
intPlayFlag=0;
voidPlayRespond2(intResult)
//枪声放音子程序
{
BSR_StopRecognizer();
SACM_A2000_Initial(1);
SACM_A2000_Play(Result,3,3);
while((SACM_A2000_Status()&0x0001)!=0)
{
SACM_A2000_ServiceLoop();
ClearWatchDog();
}
SACM_A2000_Stop();
BSR_InitRecognizer(BSR_MIC);
BSR_EnableCPUIndicator();
}
voidPlayRespond(intResult)//放音子程序
{
BSR_StopRecognizer();
SACM_S480_Initial(1);
SACM_S480_Play(Result,3,3);
while((SACM_S480_Status()&0x0001)!=0)
{
SACM_S480_ServiceLoop();
ClearWatchDog();
}
SACM_S480_Stop();
BSR_InitRecognizer(BSR_MIC);
BSR_EnableCPUIndicator();//启动实时监控
}
intTrainWord(intWordID,intRespondID)//命令训练
{
intres;
PlayRespond(RespondID);
第7章凌阳音频压缩算法311
while(1)
{
res=BSR_Train(WordID,BSR_TRAIN_TWICE);
if(res==0)break;
switch(res)
{
case-1://没有检测出声音
PlayRespond(RSP_NOVOICE);
return-1;
case-2://需要重新训练一遍
PlayRespond(RSP_AGAIN);
break;
case-3://环境太吵
PlayRespond(RSP_NOISY);
return-1;
case-4://数据库满
return-1;
case-5://检测出声音不同
if(WordID==NAME_ID)
PlayRespond(RSP_NAMEDIFF);//两次输入名称不同
else
PlayRespond(RSP_CMDDIFF);//两次输入命令不同
return-1;
case-6://序号错误
return-1;
}
}
return0;
}
intmain()
{
intres,timeCnt=0,random_no=0;
BSR_DeleteSDGroup(0);//初始化存储器为RAM
PlayRespond(RSP_INTR);//播放开始训练的提示音
//..........训练名称..............................
while(TrainWord(NAME_ID,1)!=0);
//..........训练第一条命令.......................
while(TrainWord(COMMAND_ONE_ID,2)!=0);
//..........训练第二条命令.......................
while(TrainWord(COMMAND_TWO_ID,3)!=0);
//..........开始识别命令.........................
BSR_InitRecognizer(BSR_MIC);//辨识器初始化
BSR_EnableCPUIndicator();
PlayRespond(RSP_STAR);//播放开始辨识的提示音
第7章凌阳音频压缩算法312
while(1)
{
random_no++;
if(random_no>=3)random_no=0;
res=BSR_GetResult();
if(res>0)//识别出命令
{
if(gActivated)
{
timeCnt=0;
switch(res)
{
caseNAME_ID:
PlayRespond(gTriggerRespond[random_no]);
break;
caseCOMMAND_ONE_ID:
PlayFlag=1;
PlayRespond2(RSP_GUNSHOT);
PlayFlag=0;
gActivated=0;
break;
caseCOMMAND_TWO_ID:
PlayRespond(gComm2Respond[random_no]);
gActivated=0;
}
}
else
{
if(res==NAME_ID)
{PlayRespond(gTriggerRespond[random_no]);
gActivated=1;
timeCnt=0;
}
}
}
elseif(gActivated)
{
if(++timeCnt>450)//超出定时
{PlayRespond(RSP_NOVOICE);//在设定时间内没有检测出声音
gActivated=0;
timeCnt=0;
}
}
}
第7章凌阳音频压缩算法313
}
中断流程见图7.22:
寄存器组入栈
是定时器A中断吗
停止辨识吗
中断辨识,调用
_BSR_FIQ_Routine
转至BSR_Busy
清中断状态
寄存器组出栈
返回
清中断状态
寄存器组出栈
返回
S480放音
中断放音吗
转至BSR_Busy
清FIQ_TMA中断状态
寄存器组出栈
返回
A2000放音






图7.22特定人连续语音识别中断程序流程
第7章凌阳音频压缩算法314
.PUBLIC_FIQ
.EXTERNAL_BSR_FIQ_Routine
.EXTERNAL__gIsStopRecog//变量值=0辨识器忙
//=1辨识器停止
.PUBLIC_BREAK,_IRQ0,_IRQ1,_IRQ2,_IRQ3,_IRQ4,_IRQ5,_IRQ6,_IRQ7
.EXTERNAL_PlayFlag
.INCLUDEs480.inc;
.INCLUDEA2000.inc;
.INCLUDEresource.inc
.INCLUDEhardware.inc
.TEXT
_FIQ:
pushR1,R4to[SP]
R1=[P_INT_Ctrl]
R1&=0x2000
jznotTimerA//当不为TIQ_TMA,则转
R1=[__gIsStopRecog]
jnzBSR_NotBusy
//[__gIsStopRecog]为1则转至放音处理
call_BSR_FIQ_Routine//为0,调用辨识子程序
jmpBSR_Busy//返回中断
BSR_NotBusy://放音处理
R2=[_PlayFlag]
jnzPlay2000//[_PlayFlag]为1则是播放2000
callF_FIQ_Service_SACM_S480;//为0,播放480
jmpBSR_Busy//返回中断
Play2000://2000播放子程序
callF_FIQ_Service_SACM_A2000;
BSR_Busy://返回中断
R1=0x2000
[P_INT_Clear]=R1
popR1,R4from[SP];
reti;
notTimerA:
R1=0x8800;
[P_INT_Clear]=R1;
popR1,R4from[SP];
reti;
.END
第7章凌阳音频压缩算法315
7.7本章小结
本章主要向大家介绍了表7.3中的各种压缩算法的API(ApplicationProgramming
Interface)函数功能及各自的应用,并进一步介绍了两个接口文件Key.asm和
System.asm的具体内容及应用方法.还举出了使用SPCE061A进行辨识的一个应用实
例.
表7.3凌阳语音压缩算法及其编码
凌阳压缩算法编码方法编码率
SACM_A2000SUB-BAND16/20/24Kbps
SACM_S480CELP4.8/7.2Kbps
SACM_S240LPC1.2/2.4Kbps
SACM_MS01FM音乐合成
SACM_DVR(A2000压缩)SUB-BAND16K资料率/8K采样率录音
1)通过本章介绍大家都了解到自动方式放音包括SACM_A2000,SACM_S480和
SACM_S240三种方式,而且也发现每种算法除了压缩比不同外程序结构基本相同,
所以非常容易掌握并应用,在这里我们巩固一下前面的内容,图7.23是自动方式下整
个程序的流程:
初始化
Model-Index_Initial()
开始播放
Model-Index_Play()
解码程序
Model-Index_Serviceloop()
中断服务子程序(播放程序)
F_FIQ_Service_Mod_Index
图7.23自动方式下程序的流程
2)另外SACM_A2000和SACM_DVR除了自动方式外还有非自动方式,图7.24
是在手动方式下声音录制与播放流程(当然SACM_A2000只有声音播放部分):
第7章凌阳音频压缩算法316
SRAM地址复位
初始化解码器
内部缓存器
编码器(前台程序)
编码队列
取编码数据
SACM_DVR_Fetc
hQueue()
写入外接SRAM
SRAM地址复位
初始化解码器
从SRAM里读出
数据并指向下
一个地址
填入队列
SACM_DVR_Fill
Queue()
编码队列
解码器(前台程序)
内部缓存器
ADC
中断服务子程序(背
景程序)
F_FIQ_Service_Mod
_Index
中断服务子程序
(背景程序)
F_FIQ_Service_Mod
_Index
DAC
声音录制声音播放
图7.24手动方式下声音录制与播放流程
至于键控部分,如果同学们感兴趣的话可以结合7.5小节内容自己尝试做一些键
控放音的实验以进一步更好的掌握语音编程.
备注:
有时候我们在一个较复杂的程序里,可能不只用到语音,还有A/D,中断,定时
等,这样,在放音过程中很有可能会和程序中的一些寄存器发生冲突,所以了解API
函数中占用了哪些寄存器就很有必要的,列出了各个函数所占用的寄存器.
第7章凌阳音频压缩算法317
表7.4API函数中所占用的寄存器
函数
SACM_A2000_Initial(intInit_Index)
SACM_S480_Initial(intInit_Index)
SACM_S240_Initial(intInit_Index)
SACM_MS01_Initial(intInit_Index)
SACM_DVR_Initial(intInit_Index)
使用寄存器
[P-_SystemClock]
[P_TimerA_Ctrl]
[P_TimerA_Data]
[P_DAC_Ctrl]
[P_INT_Clear]
[P_TimerB_Ctrl]
[P_TimerB_Data]
SACM_A2000_Play()
SACM_A2000_InitDecoder()[ManualMode]
SACM_S480_Play()
SACM_S240_Play()
SACM_MS01_Play()
SACM_DVR_Play()
SACM_DVR_InitDecoder()[ManualMode]
[P_INT_Clear]
[P_TimerA_Data]
SACM_DVR_Record()
SACM_DVR_InitDecoder()
[P_ADC_Ctrl]
[P_TimerA_Data]
[P_INT_Ctrl]
SACM_A2000_Stop()
SACM_A2000_StopDecoder()
SACM_S480_Stop()
SACM_S240_Stop()
SACM_MS01_Stop()
SACM_DVR_Stop()
SACM_StopDecoder()
SACM_StopEncoder()
[P_INT_Ctrl]
[P_INT_Clear]
[P_ADC_Ctrl]
SACM_A2000_ServiceLoop()
SACM_A2000_Decoder()[ManualMode]
SACM_S480_ServiceLoop()
SACM_S240_ServiceLoop()
SACM_MS01_ServiceLoop()
SACM_DVR_ServiceLoop()
SACM_DVR_Encoder()[ManualMode]
[P_INT_Ctrl]
[P_INT_Clear]
F_FIQ_Service_SACM_A2000
F_FIQ_Service_SACM_S480
F_FIQ_Service_SACM_S240
F_FIQ_Service_SACM_MS01
F_FIQ_Service_SACM_DVR
[P_DAC1]
[P_DAC2]
F_IRQ1_Service_SACM_DVR[P_ADC]
第7章凌阳音频压缩算法318
第7章凌阳音频压缩算法............................................................................................261
7.1背景介绍..........................................................................................................261
7.1.1音频的概述(特点,分类).................................................................261
7.1.2数字音频的采样和量化........................................................................261
7.1.3音频格式的介绍....................................................................................261
7.1.4语音压缩编码基础................................................................................263
7.1.5语音合成,辨识技术的介绍:.............................................................264
7.2凌阳音频简介..................................................................................................266
7.2.1凌阳音频压缩算法的编码标准.............................................................266
7.2.2压缩分类...............................................................................................266
7.2.3凌阳常用的音频形式和压缩算法.........................................................266
7.2.4分别介绍凌阳语音的播放,录制,合成和辨识..................................267
7.3常用的应用程序接口API的功能介绍及应用................................................267
7.3.1概述.......................................................................................................267
7.3.2SACM_A2000.........................................................................................268
7.3.3SACM_S480...........................................................................................275
7.3.4SACM_S240...........................................................................................279
7.3.5SACM_MS01..........................................................................................284
7.3.6SACM_DVR...........................................................................................289
7.4语音压缩方法..................................................................................................297
7.5键控放音程序介绍...........................................................................................299
7.6语音辨识..........................................................................................................305
7.7本章小结..........................................................................................................315