数字信号处理实验语音信号滤波.docx
《数字信号处理实验语音信号滤波.docx》由会员分享,可在线阅读,更多相关《数字信号处理实验语音信号滤波.docx(12页珍藏版)》请在冰点文库上搜索。
数字信号处理实验语音信号滤波
实验一长序列卷积实现与DSP定点运算模拟
一、实验名称
长序列分段卷积与DSP定点运算模拟
二、实验要求
1.学习长序列分段卷积实现的两种方法
(1)重叠相加法
(2)重叠保留法
2.改写语音滤波C程序
(1)说明程序中错误的原因
(2)说明选择短数据类型的原因
(3)分析重叠保留法过程
3.模拟DSP定点化运算
(1)设计思路
(2)分析运算过程
三、实验内容
1.长序列卷积的两种方法
FIR离散时间系统,单位脉冲响应为h(n),n=0,1,2,因为系统为因果,所以n<0时,h(n)值为0。
长序列X(n)分段,将分出的小段x(n)分别于h(n)做卷积,得到相应段的y(n)。
y(n)=x(n)*h(n),设x(n)长为5,h(n)长为3。
(1)重叠相加法
第一段(0~4)卷积:
y(0)=h(0)x(0)y
(1)=h(0)x
(1)+h
(1)x(0)y
(2)=h(0)x
(2)+h
(1)x
(1)+h
(2)x(0)
y(3)=h(0)x(3)+h
(1)x
(2)+h
(2)x
(1)y(4)=h(0)x(4)+h
(1)x(3)+h
(2)x
(2)
从n=5开始,缺少后一段元素的卷积将丢失元素项。
y(5)=缺项+h
(1)x(4)+h
(2)x(3)y(6)=缺项+缺项+h
(2)x(4)
y(5)缺失项为h(0)x(5),y(6)的缺失项为h(0)x(6)与h
(1)x(5)。
第二段(5~9)卷积:
y(5)=h(0)x(5)+缺项+缺项y(6)=h(0)x(6)+h
(1)x(5)+缺项
y(5)缺失项为h
(1)x(4)与h
(2)x(3),y(6)的缺失项为h
(2)x(4)。
因此,第二段与第一段的重叠部分y(5)与y(6)相加得到正确的值,是为重叠相加法。
(2)重叠保留法
若已知滤波器n=M,则在X(n)序列前端补M-1个零。
第一段(-2~4)卷积:
y(-2)=h(0)x(-2)y(-1)=h(0)x(-1)+h
(1)x(-2)y(0)=h(0)x(0)+h
(1)x(-1)+h
(2)x(-2)
y
(1)=h(0)x
(1)+h
(1)x(0)+h
(2)x(-1)y
(2)=h(0)x
(2)+h
(1)x
(1)+h
(2)x(0)
y(3)=h(0)x(3)+h
(1)x
(2)+h
(2)x
(1)y(4)=h(0)x(4)+h
(1)x(3)+h
(2)x
(2)
y(5)=缺项+h
(1)x(4)+h
(2)x(3)y(6)=缺项+缺项+h
(2)x(4)
第二段(3~9)卷积:
保留上一段中的x(3)与x(4)到该段作为卷积项。
y(3)=h(0)x(3)+缺项+缺项y(4)=h(0)x(4)+h
(1)x(3)+缺项
y(5)=h(0)x(5)+h
(1)x(4)+h
(2)x(3)y(6)=h(0)x(6)+h
(1)x(5)+h
(2)x(4)
y(7)=h(0)x(7)+h
(1)x(6)+h
(2)x(5)y(8)=h(0)x(8)+h
(1)x(7)+h
(2)x(6)
y(9)=h(0)x(9)+h
(1)x(8)+h
(2)x(7)y(10)=缺项+h
(1)x(9)+h
(2)x(8)
y(11)=缺项+缺项+h
(2)x(9)
其中标红的部分为保留项。
恰好保证了连续性,卷积结果由之前的7项增加到9项,每段卷积前需接入上段段尾M–1个数据。
2.改写语音滤波C程序
(1)程序错误
a.打开文件函数错误
应该设置文件名路径,并设置为r+b读写可修改模式。
b.采样错误
原程序中读取语音文件一帧数据的处理函数为getw(),存储该帧数据的数组类型为int,读取每点为32bit,不符合实验要求的每点16bit。
使用fread(indata,2,LENGTH,fp1),选取2字节数据,为16bit。
c.wav文件处理时需要跳过头文件的44字节
使用fseek(fp1,44,SEEK_SET),跳过文件开头字节。
(2)选择short型数据
short型数据的长度为16bit,可保证读取一点的16bit数据存入具有合适数据类型的数组。
即每次读取180点,每点16bit,存入数组indata[LENGTH],而indata为short型。
(3)重叠保留法过程
已知h(n)为19点滤波器,即n=19。
x(n)分段序列n=180。
采用重叠舍去法,每一次卷积需要180+19-1=198个点的数组空间。
数组0~17位为补足位,第一段卷积时补零,后段卷积时,补上前一段末尾18个数据。
输出赋值时从数组的第M位开始,前M-1位舍去。
程序中卷积计算数组为x1[LENGTH+FILTER_LEN-1],LENGTH为180,FILTER_LEN为19。
初始补零位为x1[0]~x1[17],数据读入从x1[18]开始,读180点,如下图所示:
时域卷积过程如下,使用i+n-1代替i,不去计算舍去的前18项,从第19项开始计算:
后段卷积前选取前一段18个点的数据作为补充点,如图:
3.模拟DSP定点化运算
由于滤波器系数为小数,在DSP中做浮点运算占用资源且耗时长,因此设计C定点程序提高运算效率。
滤波器原系数如下图:
对滤波器系数进行整数化操作,每个系数乘以2的15次方,即32768。
如下图:
在滤波过程中将结果右移15位,效果等同于除以2的15次方,如下图所示:
DSP中整数操作和移位操作比浮点乘除法操作速度快很多。
提高了效率。
四、实验结果
完整程序如下图所示:
/******************************************
*语音信号800HZ19点FIR低通滤波C语言浮点程序
*
*Author:
caoxin
*Date:
15-04-09
*
*******************************************/
#include
#include
#defineLENGTH180
#defineFILTER_LEN19
#defineSUCCESS0
/*语音帧长为180点=22.5ms@8kHz采样*/
voidfilter(intxin[],intxout[],intn,floath[]);/*滤波子程序说明*/
/*19点滤波器系数*/
staticfloath[FILTER_LEN]={0.01218354,-0.009012882,-0.02881839,-0.04743239,-0.04584568,
-0.008692503,0.06446265,0.1544655,0.2289794,0.257883,
0.2289794,0.1544655,0.06446265,-0.008692503,-0.04584568,
-0.04743239,-0.02881839,-0.009012882,0.01218354};
staticshortx1[LENGTH+FILTER_LEN-1];
staticlonglonginth_temp[FILTER_LEN];
voidfilter(shortxin[],shortxout[],intn,longlonginth_temp[])
{
inti,j;
floatsum=0.0;
longlongintsum_temp;
/*取180点的数据,x1起始点为x1[18],读入数据为indata*/
for(i=0;i{
x1[n+i-1]=xin[i];
}
/*滤波过程,时域卷积*/
for(i=0;i{
sum_temp=0;
for(j=0;j{
sum_temp+=h_temp[j]*x1[i-j+n-1];
}
sum=sum_temp>>15;//除以2的15次方
xout[i]=(short)sum;
}
/*截取尾部18个数据*/
for(i=0;i<(n-1);i++)
{
x1[n-i-2]=xin[LENGTH-1-i];
}
}
/*主程序*/
intmain()
{
inti;
intfp_start=44,fp_end;
FILE*fp1,*fp2;
charfname_in[20]="d:
\\bluesky1.wav";
charfname_out[20]="d:
\\bluesky1_out.wav";
intframe=0;
shortindata[LENGTH],outdata[LENGTH];
/*浮点转定点*/
for(i=0;i{
h_temp[i]=h[i]*32768;//乘以2的15次方
}
fp1=fopen(fname_in,"r+b");/*输入语音文件*/
fp2=fopen(fname_out,"r+b");/*滤波后输出语音文件*/
fseek(fp1,44,SEEK_SET);
while(LENGTH==fread(indata,2,LENGTH,fp1))
{
fp_end=ftell(fp1);//获取当前文件指针位置
frame++;//帧计数,一帧为180点
printf("frame=%d\n",frame);
filter(indata,outdata,FILTER_LEN,h_temp);/*调用低通滤波程序*/
/*将滤波后的样值写入文件*/
if(SUCCESS==fseek(fp2,fp_start,SEEK_SET))
{
/*判定条件:
设定写入文件的方式,180项2字节数*/
if(LENGTH==fwrite(outdata,2,LENGTH,fp2))
{
fseek(fp2,fp_end,SEEK_SET);//设置当前处理完的指针
fp_start=fp_end;//后移处理指针,下一个180项
}
}
else
{
printf("存储结果失败\n");
break;
}
if(frame>4000)
{
printf("DATAOVERFLOW\n");
break;
}
}
fcloseall();
getchar();
return0;
}
程序运行结果如下图:
对音频文件的处理结果:
输入文件为:
bluesky1.wav
输出文件为:
bluesky1_out.wav
使用cooledit观察频谱如下图所示:
滤波处理前:
滤波处理后:
滤波处理前:
滤波处理后: