首页
会员中心
到顶部
到尾部
MATLAB毕业设计

DSP语音压缩、存储和回放

时间:2020/10/13 22:22:10  作者:  来源:  查看:0  评论:0
内容摘要: 目  录    一、实验背景与内容……………………………………………………3 二、设计内容……………………………………………………………3 三、设计方案、算法原理说明…………………………………………4&...
目  录
 
 
 
 
一、实验背景与内容……………………………………………………3
 
二、设计内容……………………………………………………………3
 
三、设计方案、算法原理说明…………………………………………4
 
四、程序设计、调试与结果分析………………………………………5
    
五、设计(安装)与调试的体会………………………………………16
   
六、参考文献……………………………………………………………16
 
 
 
 
 
 
 
 
 
一、实验背景与内容
目前语音信号压缩技术发展十分迅速,出现了很多高效率的语音压缩编码方法。以语音信号压缩的国际标准G.729为例,它可将经过采样的64kb/s语音信号高保真地压缩到8kb/s,但其模型编码算法的运算量很大。同时又要求对语音信
号进行实时采样实时压缩处理,这样对数据采集和处理系统提出了更高的要求。本实验是使用通用数字信号处理器(DSP)强大的数据处理能力,由于DSP采用内部多总线结构,使数据的存储和指令的执行更加快捷。最重要的一点是,DSP具有快速的指令周期,如TMS320系列己经从第一代的200ns降低到5ns(1600MIPS)以下,如此高的运算速度使其可以满足许多实时处理的需要。语音信号的幅度(发音强度)并非均匀分布,由于小信号占的比例比大信号大很多,因此可以进行非均匀量化。达到这一目标的基本做法是,对大信号使用大的量化间隔,而小信号则使用小的台阶。ITU-T G.711建议的PCM A律和µ律语音压缩标准可以分别将13比特和14比特压缩为8比特,达到语音压缩的目的。pcm是原始数据原封不动地量化编码(这种量化的位宽大),A律pcm是经过压扩后的非均匀量化(小信号细量化大信号粗量化),U律pcm是经过压扩后的均匀量化(A/U律量化的位宽小)。 所以本实验采用A律的效果应该比较理想。但是也采用了U律进行了对比。
 
 
二、设计内容
l 实验目的
①、应用DSP算法实现对语音信号的压缩、存储和回放。
②、熟悉使用C语言编写较复杂的程序; 
③、熟悉C语言对外设(DSK板或示波器)的访问(软件编程、硬件连接); 
④、熟练使用软件CCS5000对程序的完整调试过程。
 
l 实验设计要求
①使用DSP实现语音压缩和解压缩的基本算法,算法类型自定,例如可以采用G.711、G.729等语音压缩算法。
②采用A/D转换器从MIC输入口实时采集语音信号,进行压缩后存储到DSP的片内和片外RAM存储器中,存储时间不小于10秒。
③存储器存满之后,使用DSP进行实时解压缩,并从SPEAKER输出口进行回放输出。
④使用指示灯对语音存储和回放过程进行指示。
三、设计方案、算法原理说明
语音信号的编码方式一般为PCM( PulCode Modulation)编码。由于需要采集、存储、传输和处理的音频数据量极大,只有进行压缩后才能正常进行传输和存储。目前,用于语音压缩编码的算法有ADPCM,CE LP,RP E-LTP,等。其中最常用的是u/A律压缩解压。u/A 律 压 缩解压编码是国际电报电话协会(CCIT)最早推出的G711语音压缩解压编码的一种格式的主要内容。其中欧洲和中国等国家采用A律压缩解压编码,美国和日本采用u律压缩解压编码。两个算法使用了非线性,把量化间隔变换成人耳能检测的线性空间。
A律限制采样值为12+1比特,将压缩后的格式码定义为PSSSQQQQ ,相当于将
正负值输入分成8 个区段(0~7) 。其中P 为符号位,0代表正,1 代表负;SSS 表示3 位高位的区段码;QQQQ表示区段内小格码,区分不同输入的范围值。这种编码方式使压缩、解压缩变得简洁而有效率。表1 为输入值与压缩编码间的关系,其中X 为压缩中舍弃的位,输入值越大,被舍弃的位数就越多,每个输入值有其对应的最高有效位。A 律对数PCM,就是压缩器的压缩特性具有如下关系的压缩率:
DSP语音压缩、存储和回放 
式中: F(x)为归一化的压缩器输出电压;x 为归一化的压缩器输入电压;A 为压扩参数,表示压缩的程度(在欧洲,A=87.6)。
DSP语音压缩、存储和回放A律13折线
DSP语音压缩、存储和回放 
 由表1 可见,输入值与压缩后的编码值之间的关系如下:
a) 输入值的12 位即为符号位P ;
b) 将输入值右移6 位后,求得此时最高有效位的值加1 ,即为其对应压缩码的区段码SSS;
c) 最高有效位后紧邻的4 位即为其对应压缩码的小格码QQQQ。
 
 
 
 
 
 
四、程序设计、调试与结果分析
①流程图
DSP语音压缩、存储和回放
TMS320VC5402 mcbsp的串口的初始化
首先将DSP的串口1复位,再对串口116个寄存器进行编程,使串口1工作在以下状态:禁止SPI模式,但数据相,每帧一字,每字16位,帧同步脉冲低电平有效,并且帧同步信号和移位信号有外部时钟产生。
   hHandset = codec_open(HANDSET_CODEC);  
此语句调用了函数codec_open()对串口1进行了初步设置,设置成功返回codec的句柄放在变量 hHandset中,作为调用其他函数的实参。
AD50的初始化:
该初始化过程调用了5个函数对AD505项参数进行了设置,包括adcdac的工作模式,模拟输入和输出的增益;以及AD,DA的转换速率。
codec_dac_mode(hHandset, CODEC_DAC_15BIT);      /* DAC in 15-bit mode */
codec_adc_mode(hHandset, CODEC_ADC_15BIT);      /* ADC in 15-bit mode */
codec_ain_gain(hHandset, CODEC_AIN_6dB);      /* 6dB gain on analog input to ADC */
codec_aout_gain(hHandset, CODEC_AOUT_MINUS_6dB); /* -6dB gain on analog output from DAC */
codec_sample_rate(hHandset,SR_16000);     /* 16KHz sampling rate */
④从McBSP的接收通道读取A/D转换的值,然后经过压缩解压后将其发送到McBSP的发送通道,讲解压后的数据将数据写入D/A转换器。
程序如下:
while (1)
    {
       /* Wait for sample from handset */
       while (!MCBSP_RRDY(HANDSET_CODEC)) 
       {};
/* Read sample from and write back to handset codec */
       data=*(volatile int*)DRR1_ADDR(HANDSET_CODEC);
      pre=int2alaw(data);       /*or pre=int2ulaw(data);*/
      data=alaw2int(pre);        /*or data=ulaw2int(pre);*/
       *(volatile int*)DXR1_ADDR(HANDSET_CODEC)=data;
 
实验程序
l C程序
/******************************************************************/
/*                     头文件                                      */
/*******************************************************************/
#include <type.h>
#include <board.h>
#include <codec.h>
#include <mcbsp54.h>
/*******************************************************************/
/*                   变量宏定义                                    */
/*******************************************************************/
#define SIGN_BIT       (0x80)     /* Sign bit for a A-law byte. */
#define QUANT_MASK     (0xf)      /* Quantization field mask. */
#define NSEGS          (8)        /* Number of A-law segments. */
#define SEG_SHIFT      (4)        /* Left shift for segment number. */
#define SEG_MASK       (0x70)     /* Segment field mask. */
/******************************************************************/
/*                    函数声明                                     */
/*******************************************************************/
 
 
void delay(s16 period);
void led(s16 cnt);
void initcodec(void);
void flashenable(void);
unsigned char data2alaw(s16 pcm_val);
int alaw2data(unsigned char a_val);
static int search(int val,short *table,int size);
/*******************************************************************/
/*                    全局变量                                     */
/*******************************************************************/
 
HANDLE hHandset;
s16 data;
s16 data1;
u16 i=0;
u16 temp1;
u16 j=0;
u16 k,l=0;
u8 temp2;
u16 buffer[22000];
static short seg_end[8]={0x1F,0x3F,0x7F,0xFF,0x1FF,0x3FF,0x7FF,0xFFF};
 
/*******************************************************************/
/*                   主函数                                       */
/*******************************************************************/
 
void main()
{
    if (brd_init(100))
        return;
    led(2);                  //闪灯两次
    initcodec();             //初始化codec
    flashenable();           //选择片外FLASH为片外存储器
 
 
   while (1)
    {
       while (!MCBSP_RRDY(HANDSET_CODEC)) {};       //等待接收handset处的采样
       if (i==0) brd_led_toggle(BRD_LED0);         //点亮二极管0,表示录音开始
       data = *(volatile u16*)DRR1_ADDR(HANDSET_CODEC);  //从handset处读取采样
       temp1=data2alaw(data);                            //对采样进行a律压缩
     /*****************************************************************/
/*  把低地址数据放在高八位高地址数据放在低八位                     */
     /*******************************************************************/      
       i=i+1;          
   if(i%2==1)
buffer[j]=(temp1<<=8);       
/*奇数数据左移8位  temp1=abcdefgh00000000
buffer[j]=temp1*/
}
 else
     {
         buffer[j]=(buffer[j]|temp1);  
/*偶数数据与temp1取或 组成新的数据
buffer[j]=abcdefghiabcdefghi*/
        j++;   //j加1
       }
       
 if(i>=44000) 
   {
i=0;
}
if(j>=22000)
{
j=0;
brd_led_toggle(BRD_LED0);     //熄灭数码管0 表示录音结束
brd_led_toggle(BRD_LED1);     //点亮二极管1 表示放音开始
       /*******************************************************************/
/*                      放音部分                                 */
/*******************************************************************/  for(k=0;k<44000;k++)
{
if(k%2==0)
{      
temp2=(buffer[l]>>8)&0x0ff;
}
else
{
temp2=buffer[l]&0x0ff;
l++;
}
if(l>=22000)
l=0;
data1=alaw2data(temp2);
       while (!MCBSP_XRDY(HANDSET_CODEC)) {};    
*(volatile u16*)DXR1_ADDR(HANDSET_CODEC) = data1;
}
       /*******************************************************************/
/*                           放音结束                              */
/*******************************************************************/
if(k==44000) brd_led_toggle(BRD_LED1); //熄灭二极管1 表示放音结束    
        }
    }       
 }                                               //主程序结束
 
/*******************************************************************/                                                                                      
/*                       子函数                                    */                                                                        
/****************************************************************/
 
/*******延时******/
void delay(s16 period)
{
    int i, j;
 for(i=0; i<period; i++)
    {
        for(j=0; j<period>>1; j++);
    }
}
 
/*******闪灯******/
void led(s16 cnt)
{
while ( cnt-- )
{
brd_led_toggle(BRD_LED0);
delay(1000);
brd_led_toggle(BRD_LED1);
delay(1000);
brd_led_toggle(BRD_LED2);
delay(1000);
}
}
 
/*****初始化codec**/
void initcodec(void)
{
    /* Open Handset Codec */
    hHandset = codec_open(HANDSET_CODEC);             // Acquire handle to codec 
    /* Set codec parameters */
    codec_dac_mode(hHandset, CODEC_DAC_15BIT);             // DAC in 15-bit mode 
    codec_adc_mode(hHandset, CODEC_ADC_15BIT);             // ADC in 15-bit mode 
    codec_ain_gain(hHandset, CODEC_AIN_6dB);  // 6dB gain on analog input to ADC 
    codec_aout_gain(hHandset, CODEC_AOUT_MINUS_6dB);    
                                          // -6dB gain on analog output from DAC 
    codec_sample_rate(hHandset,SR_8000);                 // 8KHz sampling rate 
}
 
/*****设置flash****/
void flashenable(void)
{
CPLD_CTRL2_REG|=0x0010;
CPLD_DMCTRL_REG|=0x0040;
}
 
/*****a律压缩******/
unsigned char data2alaw(s16 pcm_val)      
{
Int  mask;
Int  seg;
unsigned char 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);           
// Combine the sign, segment, and quantization bits. 
    if (seg >= 8)       // out of range, 返回最大数. 
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的子程序**/
static int search(int val,short *table,int size)
{
Int  i;
for (i = 0; i < size; i++) 
{
if (val <= *table++)
return (i);
}
return (size);
}
 
/*****a律解压******/
int alaw2data(unsigned char a_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) 
{
t += 8;
t=(t>>3);
}
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);
}
/*******************************************************************/
/*                      结束                                       */
/*******************************************************************/
 
l 存储器的分配(*.cmd)
 MEMORY
{
   PAGE 0: VECS:     origin = 0080h, length = 0080h  /* Internal Program RAM */
           PRAM:     origin = 7600h, length = 8000h  /* Internal Program RAM */
 
   PAGE 1: SCRATCH:  origin = 0060h, length = 0020h  /* Scratch Pad Data RAM */
           DMARAM:   origin = 0C00h, length = 0300h  /* DMA buffer */
           DATA:     origin = 1100h, length = 0080h  /* Internal Data RAM    */
           STACK:    origin = 1180h, length = 0560h  /* Stack Memory Space   */
           INRAM:    origin = 1900h, length = 0100h  /* Internal Data RAM    */
           HPRAM0:   origin = 1A00h, length = 0002h  /* HPI memory accessible by Host and DSP */
           HPRAM1:   origin = 1A02h, length = 0280h  /* HPI memory accessible by Host and DSP */
           HPRAM2:   origin = 1C82h, length = 0280h  /* HPI memory accessible by Host and DSP */
           EXRAM:    origin = 1F10h, length = 5A00h  /* External Data RAM    */
}
 
 
SECTIONS
{
   .cinit    > PRAM  PAGE 0
   .text     > PRAM  PAGE 0
   .vectors  > VECS  PAGE 0
    
   init_var  > PRAM  PAGE 0
   detect    > PRAM  PAGE 0
   vrcprg  > PRAM  PAGE 0
   matprg  > PRAM  PAGE 0
   
   .stack    > STACK PAGE 1
   .trap     > SCRATCH PAGE 1
 
   .const    > EXRAM PAGE 1
   .data     > EXRAM PAGE 1
   .bss      > EXRAM PAGE 1
   .cio      > EXRAM PAGE 1
 
   .switch   > EXRAM PAGE 1
   
   tables    > EXRAM PAGE 1
   var       > EXRAM PAGE 1
   svctab    > EXRAM PAGE 1         /* SS_V LSP table */
   vctab     > EXRAM PAGE 1         /* V LSP table */
   uvctab    > EXRAM PAGE 1         /* UV LSP table */
   cuvtab    > EXRAM PAGE 1         /* Stochastic codebook */
   cdbktab   > EXRAM PAGE 1         /* various codebook tables*/
   
   logtab    > EXRAM PAGE 1          /* table for log2 */
   powtab    > EXRAM PAGE 1          /* table for pow2 */
   hamtab    > EXRAM PAGE 1          /* table for hamming */
   lgwtab    > EXRAM PAGE 1          /* table for lag window */
   acostab   > EXRAM PAGE 1          /* table for arccos */
   sqrtab    > EXRAM PAGE 1          /* table for square root */
   acbtab    > EXRAM PAGE 1          /* table for thresholds in acb */
   pm03tab   > EXRAM PAGE 1          /* table for x^(-0.3) computation */
   costab    > EXRAM PAGE 1          /* table for cosine */
 
   V23       > INRAM PAGE 1
   FSK       > INRAM PAGE 1
 
   hpibuff0  > HPRAM0 PAGE 1
   hpibuff1  > HPRAM1 PAGE 1
   hpibuff2  > HPRAM2 PAGE 1
   dma_buff  > DMARAM PAGE 1
}
 
实验操作步骤
①将SEED-VC5402 DSK板与计算机的并口相连,在DSK板的麦克风/扬声器接口分别接上话筒和耳机。
②连接DSK板的电源后首先进行复位,并启动计算机。
③双击桌面上的CCS 2( C5000) 图标运行CCS程序,在CCS并行调试管理器窗口中选择打开“C5402 DSK/CPU-1”选项启动DSK板的驱动程序,注意在启动CCS之前先按一下DSK板的复位按钮。正常启动CCS之后,在CCS的左上角出现“C5402 DSK/CPU-1”的提示。
④将本工程目录拷贝至C:\ti\myproject目录下。
⑤向工程中添加文件:(.C)文件、(.cmd)文件、(.lib)库文件、(.h)头文件。
⑥编译无错误后导入,运行。
实验结果
对语音信号开始采样后,灯闪两次,初始化codec。二级管灯0亮开始采集语音数据,二极管灯0熄灭录音结束,二极管灯1亮开始放音,二极管灯1熄灭放音结束,二极管灯0亮重新开始采样语音信号。如此再循环运行程序。
采样信号时域图
DSP语音压缩、存储和回放 
 
压缩信号时域图
DSP语音压缩、存储和回放 
 
 
解压缩信号时域图
DSP语音压缩、存储和回放 
五、设计(安装)与调试的体会
通过此次实验,使我们懂得ccs的基本调试以及加深了对c语言的理解。另外对信号压缩有了初步地认识。在实验过程中,遇到了很多的问题,总是出现莫名的错误。如:实验采样放音后,出现了错误,不能继续循环,通过询问老师,知道我们可以restart等。此外,我们查询了很多资料,A律、U律的压缩解压缩等等很多知识点。
通过此次实验,也暴露了我们很多问题。如创新能力不足,缺乏新意,实验能力不强。在今后的实验中,这是我们需要加强的地方。
 
 
六、参考文献
[1]  高海林、钱满义.DSP技术及其应用讲义.2005年10月
[2]. 周霖. DSP通信工程技术应用[M]. 北京: 国防工业出版社,2003.115
    [3].陈后金、薛健、胡健.数字信号处理.高等教育出版社.
  


相关评论
本类推荐
    广告联系QQ:45157718 点击这里给我发消息 电话:13516821613 杭州余杭东港路118号雷恩国际科技创新园  网站技术支持:黄菊华互联网工作室 浙ICP备06056032号