各位前辈,我在用DSP5509A做音频的采集与播放的时候,当输出白噪声时,扬声器能够正常发出声音,但是通过FIR滤波后扬声器不能发出声音,检测了一下白噪声的输出数值和FIR滤波后的输出数值,相差不大,为什么经过FIR滤波处理后的数值不能输出呢?
程序如下:
/*移位子函数*/
/*实现功能:将x6=x5,x5=x4,这样逐步移动,x0用于接收新的数据,丢弃高数据*/
int ShiftArray(float *Sx,float lastx,int T)//ANC模块,移位操作
{
for(i=T-1;i>0;i–)
{
Sx[i]=Sx[i-1];
}
Sx[0]=lastx;
return(0);
}
/*FIR滤波子函数*/
/*用于将信号与次级传函相滤波*/
float dotProd(float *Firx,float *Firh)
{
float sum;
sum=0.0;
float stemp;
stemp=0.0;
for(i=0;i<N;i++)
{
stemp=Firx[i]*Firh[i];
sum=sum+stemp; //此处进行右移位操作的话
}
return(sum);
}
/*FXLMS算法子函数*/
float fxlms(float *xx,float *XX,float ee) //*xx代表与wn的卷积,用于求输出yn;*XX代表与LMS算法相乘,用于更新滤波器权系数
{
float yy;
yy=0.0;
float temp;
temp=0.0;
for(i=0;i<N;i++)
{
yy+=xx[i]*wn[i];
}
ErrorSignal_anc=ee-yy;
temp=MMu*ErrorSignal;
for(i=0;i<N;i++)
{
wn[i]=wn[i]+temp*XX[i];
}
return(yy);
}
/*次级通道辨识子函数*/
void LMS_Filter()
{
float alpha;
/*————-构造当前时刻参考信号向量————*/
/*
for(i=NN;i>0;i–)
{
x[i]=x[i-1];
}
x[0]=(float)whiteNoise/32768; //对白噪声信号进行类型转换及归一化得到参考信号
*/
/*进行滤波计算*/
float y=0.0; //滤波器输出信号
for(i=0;i<NN;i++)
{
y=y+w[i]*CZ[i];
}
/*计算误差信号,更新滤波器系数*/
ErrorSignal=desizedSignal-y;
alpha=Mu*ErrorSignal;
for(i=0;i<NN;i++) //更新权值
{
w[i]=w[i]+alpha*CZ[i];
}
}
void main()
{
int outputTemp,inputTemp;
float output;
t=0;
//int y[N];
// float xn=0.0,Xn=0.0,en=0.0;
int time_flag;
time_flag=1; /*辨识程序开始标志*/
CSL_init();
PLL_config(&myConfig); //锁相环配置,CPU时钟频率设置为144MHZ
/*修改寄存器IVPH,IVPD,重新定义中断向量表*/
/* Initialize CSL library – This is REQUIRED !!! */
/* Set IVPH/IVPD to start of interrupt vector table */
/*修改寄存器IVPH,IVPD,重新定义中断向量表*/
IRQ_setVecs((Uint32)(&VECSTART));
/* Temporarily disable all maskable interrupts */
/*禁止所有可屏蔽的中断源*/
old_intm = IRQ_globalDisable();
/* Open Timer 0, set registers to power on defaults */
/*打开定时器0,设置其为上电的的默认值,并返回其句柄*/
mhTimer0 = TIMER_open(TIMER_DEV0, TIMER_OPEN_RESET);
/* Get Event Id associated with Timer 0, for use with */
/* CSL interrupt enable functions. */
/*获取定时器0的中断ID号*/
eventId0 = TIMER_getEventId(mhTimer0);
/* Clear any pending Timer interrupts */
/*清除定时器0的中断状态位*/
IRQ_clear(eventId0);
/* Place interrupt service routine address at */
/* associated vector location */
/*为定时器0设置中断服务程序*/
IRQ_plug(eventId0,&timer0Isr);
/* Write configuration structure values to Timer control regs */
/*设置定时器0的控制与周期寄存器*/
TIMER_config(mhTimer0, &timCfg0);
/* Enable Timer interrupt */
/*使能定时器的中断*/
IRQ_enable(eventId0);
/* Enable all maskable interrupts */
/*设置寄存器ST1的INTM位,使能所有的中断*/
IRQ_globalEnable();
/* Start Timer */
/*启动定时器0*/
TIMER_start(mhTimer0);
aic_23init(); //初始化AIC23芯片
sdram_init(); //初始化SDRAM外部存储器
int temp;//存储器配置
/*初始化辨识参数*/
n_iden=0; //定义辨识次数
N_iden=7000; //设置辨识次数上限,最多8000,改大需修改CMD文件中的相关值
timer_flag=0; //定时器状态标志位初始化
Mu=0.1; /*次级通道辨识,收敛步长,可修改此值,改大加快收敛速度,注意发散,Q15表示定标*/
MMu=0.001; /*ANC模块收敛步长*/
/*初始化滤波器权系数,辨识部分*/
for(i=0;i<NN;i++)
{
w[i]=0.0;
}
/*初始化ANC模块参数*/
for(i=0;i<N;i++)
{
xn[i]=0.0; //ANC模块估计参考信号初始化,存储滤波器阶数这么大的数组,xn=en-yn*hn
wn[i]=0.0; //ANC模块LMS滤波器权系数初始化
h[i]=0.0; //ANC模块次级通达函数初始化,由次级通道估计赋值而来,h=w
x_lms[i]=0.0; //ANC模块输入到LMS算法的输入信参考信号,x_lms=xn*hn
yn[i]=0.0; //ANC模块经过LMS滤波器后得到的扬声器输出信号,用于驱动扬声器,yn=xn*wn
yn_e[i]=0.0; //ANC模块LMS滤波后与次级传函的滤波后的数据,用于估计参考信号yn_e=yn*hn
}
/*回放音频*/
while(1)
{
if(time_flag==1) //次级通道辨识标志
{
time_flag=0; //次级通道辨识置0
while(n_iden<N_iden) //次级通道辨识次数应小于设定次数
{
for(i=0;i<NN;i++)
{
whiteNoise=rand()-0x4000; //生成白噪声信号,取值范围-16384至16383
while(!MCBSP_xrdy(hMcbsp)){};
MCBSP_write16(hMcbsp,whiteNoise); //输出白噪声信号,每次一个值
anc_outTemp[t]=whiteNoise;
while(!MCBSP_rrdy(hMcbsp)){};
temp=MCBSP_read16(hMcbsp); //读取白噪声信号,每次读取一个值
desizedSignal=(float)temp/32768; //对输入信号进行类型转换及归一化得到期望信号,即进行Q定标操作
CZ[i]=desizedSignal;
}
LMS_Filter(); //调用LMS自适应滤波程序
//ErrorSignal_H[n_iden]=ErrorSignal; //记录LMS滤波过程中,残余误差信号,用于绘制收敛图和导出数据
n_iden=n_iden+1; //辨识次数增加
}
/*将辨识得到的次级通道传递函数赋值给ANC模块的次级通道估计,存在问题:每次调用ANC模块均要重新赋值,需要解决*/
for(i=0;i<NN;i++)
{
h[i]=w[i];
}
}
else
{
ANC_flag=1; //将ANC标志位置1,以便于启动标志位,考虑用中断替代
if(ANC_flag==1)
{
if(t<ANC_iden) //限制ANC降噪次数,实际可取消一直降噪
{
ANC_flag=0; //开始ANC模块后将标志位置0,可优化
while(!MCBSP_rrdy(hMcbsp)){};
inputTemp = MCBSP_read16(hMcbsp); //读取误差麦克风的值,每次读取一个
DesiredSignal=(float)inputTemp/32768;
y_e=dotProd(yn,h); //计算当前时刻到达yn经过次级传函到达en的值,用于估计参考信号,即y_e=yh*h
x_0=DesiredSignal-y_e; //计算当前时刻的参考信号估计值
ShiftArray(xn,x_0,N); //将当前时刻的参考信号通过移位操作进入参考信号数组
x_lms_0=dotProd(xn,h); //计算进去LMS算法的参考信号当前值,x'n=xn*h
ShiftArray(x_lms,x_lms_0,N); //将计算得到的当前时刻的进入LMS算法的估计参考信号通过移位操作送入到估计参考信号数组中,用于LSM算法
output=fxlms(xn,x_lms,DesiredSignal); //调用LMS算法,当前计算输出值
ShiftArray(yn,output,N); //将当前输出值通过移位操作进去yn数组,用于估计参考信号
outputTemp=(int)(output*327680); //将计算得到的扬声器输出值送至扬声器
// anc_outTemp[t]=outputTemp; //存储输出到扬声器的值,用于查看并修正输出
while(!MCBSP_xrdy(hMcbsp)){};
MCBSP_write16(hMcbsp,outputTemp); //将输出信号经过扬声器进行输出
t=t+1; //记录ANC模块运行次数
}
}
}
}
}
mangui zhang:
对数据做做频谱分析吧看数据差不多是看不出来的
,
Susan Yang:
DSP5509A的问题请您到 C5000™ 超低功耗 DSP 发帖询问,谢谢
,
Susan Yang:
DSP5509A的问题请您到 C5000™ 超低功耗 DSP 发帖询问,谢谢
,
user6559028:
你白噪声训练收敛吗