DSP课程设计
实验报告
小组成员:自动化0801宋晓美08212012
自动化0801 王丹08212014
指导教师: | 高海林 |
2011年1月
概述
数字信号处理(DSP)课程设计是信息与通信、自动化和电子科学技术专业本 科生进行综合能力培养的实践课程,是培养学生DSP系统的软硬件工程设计 能力的重要实践教学环节,对于全面、系统、深入地理解与掌握信号处理知识 与设计方法具有重要的教学意义。作为通信专业的毕业生,理应牢固掌握数 字信号处理的相关知识,了解集成开发环境的使用和调试方法,内化信号处 理的基本理论知识。
| 本次实验采用DSP C5402 实验板实现语音信号的压缩与解压的。 |
| 语音信号是信息的重要形式,语音信号处理有着广泛的应用领域,而语音压 |
及有较成熟的发展并且已经广泛应用。 |
片上外设,其控制器可以在不影响CPU的情况下完成数据的传输,因此数据传输速度快,其数据的源和目的可以是片内存储器片上外设和片外设备。C5402的DMA拥有6个独立的可编程通道,允许6个不同的DMA操作。另外DMA控制器还相应HPI的服务请求。SEED-VC5402DSK实验板上集成了SRAM,FLASH,音频输入输出接口等部件。这些外设为我们提供了极大的方便.
| 语音信号模数、数模转换采用AD50,这是一款SIGMA-DELTA 型单片音频 接口芯片(AIC)。它内部集成了16 位的D/A 和A/D转换器,采样速率最高可 |
达22。05kb/s,其采样速率可通过DSP编程来设置。在DAC之前有一个插值滤波器以保证输出信号平滑和ADC之后有一个抽取滤波器以提高输入信号的信噪比。
一、设计任务书
1、设计要求及目标
(1)使用DSP实现语音压缩和解压缩的基本算法,算法类型自定,例如可以采用G.711、G。729等语音压缩算法。
(2)采用A/D转换器从MIC输入口实时采集语音信号,进行压缩后存储到DSP的片内和片外RAM存储器中,存储时间不小于10秒。
(3)存储器存满之后,使用DSP进行实时解压缩,并从SPEAKER输出口进行回放输出. |
语音信号的幅度(发音强度)并非均匀分布,由于小信号占的比例比大信号大很多,因此可以进行非均匀量化。达到这一目标的基本做法是,对大信号使用大的量化间隔,而小信号则使用小的台阶。ITU—TG。711建议的PCMA律和µ律语音压缩标准可以分别将13比特和14比特压缩为8比特,达到语音压缩的目的。
3、设计任务
(1)编写C语言程序,并在CCS集成开发环境下调试通过。
(2)实现设计所要求的各项功能。
(3)按要求撰写设计报告.
二、实验原理
1。语音编码
(1)概念:语音编码一般分为两类:一类是波形编码,一类是被称为“声码器技术”的编码.PCM编码即脉冲编码调制。波形编码的最简单形式就是脉冲编码调制(Pulsecodemodulation),这种方式将语音变换成与其幅度成正比的二进制序列,而二进制数值往往采用脉冲表示,并用脉冲对采样幅度进行编码,所以叫做脉冲编码调制.脉冲编码调制没有考虑语音的性质,所以信号没有得到压缩。
(2)量化:脉冲编码调制用同等的量化级数进行量化,即采用均匀量化,而均匀量化是基本的量化方式。但是均匀量化有缺点,在信号动态范围较大而方差较小的时
候,其信噪比会下降 。 |
由于语音信号是模拟信号,要对语音信号进行压缩、存储就必须对语音信号进行模/数转换,把转换后的语音数字信号输入DSP系统,由DSP系统对语音数字信号进行处理.把处理后的数字信号进行数/模转换,转变成原来的模拟语音信号,然后通过耳机或其他音频输出设备把语音进行回放。语音的采集和回放的基本结构图如图3所示。
模拟 | A/D 转 | 数字逻 | D/A 转 | 模拟信 |
辑电路 | ||||
信号源 | 换电路 | 换电路 | 号输出 | |
DSP | ||||
图3 语音的采集和回放的基本结构图 |
往在模/数转换的过程中就须要压缩主要程序。目前通信系统中最常用的就是A律和u律两种压缩编码技术。
u律/A律压缩解压编码是CCITT国际电报电话协会最早推出的G.711语音压缩解压编码的一种格式的主要内容。其中欧洲和中国等国家采用A律压缩解压编码,美国和日本等国家采用u律压缩解压编码。A律算法:本实验所用的A律压缩解压编码,通过DSP将传输来的压缩后的数据进行行解压成16位,然后对解压后的数据进行分析、处理。然后将处理后的数据按照要求压缩成8位的数据格式输出到相应设备,供其它设备读取.
A律算法公式:
下图是DSP将数据解压的值,DSP将压缩的8位数据解压成16位的DSP通用数据格式。其中高13位为解压后的数据,低3位补0.这是因为G。711的A律压缩只
能对13位的数据操作。DSP将解压后的数据放在缓冲串口的发送寄存器中。只要 |
图4数据压缩解压流程图
DSP的内部缓冲串口带有硬件实现的u律和A律压缩解压,用户只需在相应寄存器中设置就可以了。TMS320C5402硬件支持μ律和A律压缩算法无需重新设置,直接编程调用查找表即可,在进行A律压缩时,对于采样到的12(应改为13)位数据,默认其最高位为符号位,压缩时要保证最高位即符号位不变,原数据后11(应改为12)位要压缩成7位。这7位码由3位段落码和4位段内码组成。
压缩后数据的最高位(第7位)表示符号,量价分别为1、1、2、4、8、16、32、64,由压缩后数据的第6位到第4位决定,第三位到第0位是段内码。压缩后的数据有一定的失真,数据压缩前后的对照表如表1所示。
12位码(十进制) | 量价 | 符号位 | 段落码(二进制) | 段内码(二进制) |
0~ | | | | ~1111 |
16~31 | 1 | 0 | 001 | 0000~1111 |
32~63 | 2 | 0 | 010 | 0000~1111 |
64~127 | 4 | 0 | 011 | 0000~1111 |
128~255 | 8 | 0 | 100 | 水印0000~1111 |
256~511 | 16 | 0 | 101 | 0000~1111 |
512~1 | | | | 00~1111 |
1024~2 | | | | 00~1111 |
表1A律数据压缩表
μ律算法:采用μ律算法对采集的语音数据进行处理,μ律编码是一种针对语音信号进行对数压缩非均匀量化的方案。采用μ律对信号进行对数形式的压缩,以便在不提高数据量的前提下提高信噪比,尽管量化的位数保持不变,但动态范围增加了。μ律压缩的语音信号一般用8比特抽样数据表示,携带小信号信息量比大信号信息量多。从统计意义上讲,有用信号更可能在小信号区间而非大信号区间。因此,在小信号区间需要更多的量化点数.
μ律算法公式:
其中Xmax是信号x(n)的最大幅度,u是控制压缩程序的参数,u越大压缩就越厉害
数位用于表示后4个有效位,还有一位符号位没有给出.16比特输入数据是由线性
数据变换成8比特μ律数据(模拟传输),然后再从μ律转成16比特的线性数据(模拟
接收),再输出到编解码器。
|
0 0 0 0 0 1a b c d 1 ╳╳╳╳ | 5 | 010a b c d |
0 0 0 0 1 a b c d 1╳ ╳╳╳ ╳ | 6 | 0 1 1 abc d |
0 0 0 1 a b c d1 ╳╳╳╳ ╳╳ | 7 | 1 0 0 ab c d |
00 1 a b c d 1 ╳╳ ╳╳╳╳╳ | 8 | 1 0 1 a b c d |
01 a b c d 1 ╳╳╳╳╳╳╳╳ | 9 | 1 1 0a b c d |
1 a b c d 1╳╳╳ ╳╳╳╳╳╳ | 10 | 11 1 a b c d |
表2 线性到U律转换表(压缩表)
上表为压缩表:其中压缩后的数据为8位,符号位未写出。其解压表与之相反:由8位U律变换到线性16位。
上图给出了按m律压扩算法的输入输出特性曲线,m为确定压缩量的参数,它反映
最大量化间隔和最小量化间隔之比。由图可见,m值越大,压缩量越大。由于m
律压扩的输入和输出关系是对数函数关系,所以这种编码又称为对数PCM。
A律压扩与m律压扩相比,则压缩的动态范围略小些,小信号振幅时质量要比m律稍差.无论是A律还是m律算法,它们的特性在输入信号振幅小时都呈线性,在输入信号振幅大时呈对数压缩特性.
对于采样频率为8kHz,样本精度为16位的输入信号,使用A律压扩或m律压扩编码,经过PCM编码器之后每个样本的精度为8位,输出的数据率为64kb/s。这
个数据就是CCITT,(国际电话与电报顾问委员会)推荐的G.711标准:话音频率脉冲编码调制。
3。存储和回放
通过定义适当大的缓冲区,将压缩后的8位或4位数据经过相应的整合,存储到16位的RAM中,这种操作目的主要是充分利用存储器中的资源,以保证能够录入足够多的语音数据。利用缓冲区的目的是进行音效的实时处理.系统中各模块是同时进行处理的,一部分信号正在ADC中进行转换,而另一部分信号则在DSP处理器中同时进行算法处理,即整个系统是以流水线的方式进行工作的。
通过解压缩,将8位或4位数据还原成相应的语音数据,在经过AD50C将数字
信号还原成语音信号(即模拟信号)通过多通道缓冲串口输出,达到放音的目的. |
开始
实验板初始化
CODEC与McBSP
初始化与工作方式设置
输入语音信号
语音压缩、存储
定时器延时
解压、回放
是否结束?
1.DSK板的初始化:
首先将DSP的串口1复位,再对串口1的16个寄存器进行编程,使串口1工作在以下状态:禁止SPI模式,但数据相,每帧一字,每字16位,帧同步脉冲低电平有效,并且帧同步信号和移位信号有外部时钟产生.DSP给AD50编程用查询方式,A/D转换数据的接收和D/A转换的数据发送采用查询方式.
此语句调用了函数codec_open()对串口1进行了初步设置,设置成功返回codec的句柄放在变量hHandset中,作为调用其他函数的实参.
2.AD50(即CODEC)的初始化:
| hHandset = codec_open(HANDSET_CODEC); | |
codec_dac_mode(hHandset,CODEC_DAC_15BIT);式*/ | /* DAC15bit模 | |
codec_adc_mode(hHandset, CODEC_ADC_15BIT);/*ADC15bit模式*/ |
| codec_ain_gain(hHandset, CODEC_AIN_6dB); | /* 输入6dB 增益 |
*/
codec_aout_gain(hHandset,CODEC_AOUT_MINUS_6dB);/*输出-6dB
增益*/
| codec_sample_rate(hHandset,SR_16000); | /* 16KHz采样率*/ |
该初始化过程调用了5个函数对AD50的5项参数进行了设置,包括ADC和DAC的工
作模式,模拟输入和输出的增益;以及AD/DA的转换速率。
1) 用TMS320VC5402实现语音的A率压缩解压有两种方法:
(1)使用多通道缓冲串口(McBSP)的缩展器
在多缓冲通道串口(McBSP)内部装置了硬件电路,支持A律格式缩展器,对数据进行压缩与
扩展,A律缩展器允许14比特的动态范围。
(2)用软件实现 | |
#include<type.h〉 | /* 头文件*/ |
#include〈board。h〉
#include<codec。h〉
#include〈mcbsp54.h>
/*宏定义*/
#defineﻩSIGN_BIT(ﻩ0x80)*/ﻩSignbit foraA-lawbyte.*/#defineQUANT_MASK(0xf) /*Quantizationfieldmask.*/#define NSEGS (8) ﻩﻩ */NumberofA-law segments.*/ #defineSEG_SHIFT(ﻩ4)*/ ﻩﻩLeftshiftforsegmentnumber。*/
#defineﻩSEG_MASK(ﻩ0x70)ﻩ | */Segment field mask. */ | |
/* | 函数声明 |
voiddelay(s16period);
voidled(s16cnt);
voidinitcodec(void);
voidflashenable(void);
unsignedchardata2alaw(s16pcm_val);
intalaw2data(unsignedcharﻩa_val);
static int search(int val,short | *table,int size); | */ | |
/* | 全局变量 |
HANDLEhHandset;
s16data;
s16data1;
u16i=0;
u16temp1;
u16j=0;
u16k,l=0;
u8temp2;
u16buffer[20000];
static short seg_end[8]={0x1F,0x3F,0x7F,0xFF,0x1FF,0x3FF,0x7FF,0xFFF};/* 主函数 */ | |
led(2); | //闪灯两次 |
initcodec();//初始化codec
flashenable(); //选择片外FLASH为片外存储器
/*
delay(100);
brd_led_toggle(BRD_LED0);
for(i=0x9000;i<0xefff;i++)
{
REG_WRITE(i,*(volatileu16*)DRR1_ADDR(HANDSET_CODEC)); delay(20);
}
brd_led_toggle(BRD_LED1); delay(200); | |
{
*(volatileu16*)DXR1_ADDR(HANDSET_CODEC)=REG_READ(i); delay(20);
}
brd_led_toggle(BRD_LED2);
*/
while(1)
{
while(!MCBSP_RRDY(HANDSET_CODEC)){};//等待接
收handset处的采样
brd_led_toggle(BRD_LED0);
data=*(volatileu16*)DRR1_ADDR(HANDSET_CODEC); //从h
andset处读取采样
temp1=data2alaw(data); //对采样进行a 律压缩 |
*/ﻩﻩ奇数数据左移8位temp1=abcdefgh00000000ﻩﻩ ﻩbuffer[j]=temp1*/
ﻩ }
ﻩelse
{
ﻩ ﻩbuffer[j]=(buffer[j]|temp1);
ﻩ */偶数数据与temp1取或组成新的数据
buffer[j]=abcdefghiabcdefghi*/
j++;//j加1
}
ﻩ
if(i>=40000)
ﻩ | ﻩﻩi=0; | { | |
}ﻩ ﻩ | |
ﻩ ﻩ
ﻩif(j〉=20000)
ﻩ ﻩ {
ﻩﻩ ﻩj=0;
ﻩﻩﻩ ﻩbrd_led_disable(BRD_LED0);
ﻩ ﻩbrd_led_toggle(BRD_LED1);
//点亮二极管1表示放音开始
/*放音部分
*/
ﻩﻩfor(k=0;k<40000;k++)
{ﻩﻩ ﻩ
ﻩ ﻩ ﻩﻩif(k%2==0)
ﻩ {
ﻩ ﻩﻩﻩﻩtemp2=(buffer[l]>〉8)&0x0ff;
ﻩﻩ }
ﻩelse
{ﻩﻩﻩ ﻩ | |
ﻩ ﻩ | ﻩwhile (!MCBSP_XRDY(HANDSET_CODEC));}{ |
ﻩ | (*volatile u16*)DXR1_ADDR(HANDSET_CODEC) = data1; |
//将数据写入D/A转换器
}ﻩ ﻩ
/* | 放音结束 | */ |
ﻩ ﻩ
ﻩ ﻩbrd_led_toggle(BRD_LED0);
brd_led_toggle(BRD_LED1); ﻩ
ﻩ
} | } | |
|
} | 子函数 | */ | //主程序结束 |
/* |
/*******延时******/
voiddelay(s16period)
{
inti, j;
for(i=0;i〈period;i++)
{
for(j=0;j〈period>>1;j++);
}
} /*******闪灯******/ | | |
{ | while ( cnt-- ) |
{ﻩ
ﻩbrd_led_toggle(BRD_LED0); //切换LED指示灯0的显示状态
ﻩﻩdelay(1000);
ﻩbrd_led_toggle(BRD_LED1);
ﻩﻩdelay(1000);
ﻩbrd_led_toggle(BRD_LED2);
ﻩdelay(1000;)
}
}
/*****初始化codec**/
voidinitcodec(void)
{
/* Open Handset Codec获取设置codec 的句柄*/ | |
hHandset=codec_open(HANDSET_CODEC); // Acquire handl |
etocodec
/* Setcodecparameters*/
codec_dac_mode(hHandset,CODEC_DAC_15BIT); // DACin 15-bitmode
codec_adc_mode(hHandset,CODEC_ADC_15BIT);//ADCin15-bitmode
codec_ain_gain(hHandset,CODEC_AIN_6dB); //6dBgainonanaloginputto ADC
codec_aout_gain(hHandset,CODEC_AOUT_MINUS_6dB);
//-6dBgainonanalogoutputfromDAC
codec_sample_rate(hHandset,SR_8000);//8KHzsamplingrate
}
/*****设置flash****/
voidflashenable(void)
{
CPLD_CTRL2_REG|=0x0010; | |
{ | |
intﻩmask;
int seg;
ﻩunsignedcharﻩaval;
ﻩif(pcm_val>=0)
{
ﻩmask= 0xD5;ﻩ //标记(7th)bit=1
}
ﻩelse
{ﻩ
mask=0x55; //标记bit=0
pcm_val=-pcm_val;
} //ﻩConvert the scaled magnitude to segment number。 | |
seg = search(pcm_val,seg_end, 8); | |
//Combinethesign,segment,andquantizationbits。
if (seg>=8) //outofrange,返回最大数.
return(0x7F^ mask);
else
{
ﻩaval=seg <〈SEG_SHIFT;
ﻩﻩif(seg<2)
ﻩaval|= (pcm_val>>1)& QUANT_MASK;
ﻩelse
ﻩﻩaval|=(pcm_val>>seg)&QUANT_MASK;
ﻩreturn(aval^mask);
}ﻩ
}
/****alaw的子程序**/
staticint search(int val,short | *table,int size) |
{ |
return(size);
}
/*****a律解压******/
intalaw2data(unsignedchara_val)
{
ﻩintﻩt;
ﻩintﻩseg;
a_val^= 0x55;
t= (a_val&QUANT_MASK)<<4;
ﻩseg=((unsigned)a_val&SEG_MASK)>>SEG_SHIFT;ﻩif(seg==0)
{ | |
}
ﻩif((seg〈4)&&(seg〉0))
{
t+=0x108;
ﻩt=(t>>(4-seg));
}ﻩ
ﻩif(seg〉3)
{ﻩ
ﻩﻩt+=0x108;
ﻩﻩt=(t〈〈=(seg—4));
}
return((a_val&SIGN_BIT)?t :-t);
}
/* 结束 | */ |