FIR加速器

来源:互联网 发布:powershell安装软件 编辑:程序博客网 时间:2024/04/26 13:41

FIR滤波器的作用:它可以对音响进行纠正,使用任何的测量工具测得房间的脉冲响应,我们知道FIR系数的傅里叶变换即为频率响应,那么就可以得到房间最适合音响的一种音质,这对于音响的保护和产生最佳音质是有及其重要的作用,越来越多的数字音频设备中将FIR加入它们的设备中,是一个极大的卖点。

我们来看看Sysmtrix(思美)的FIR滤波器是怎么样的,如下图。这是一个1024 TapsFIR滤波器,它直接点击Load Table选择,选择滤波器系数文件(*.csv)文件就可实现系数的导入,滤波器图形显示这是一个2k的低通滤波器。


好,接下来我们看看如何实现这个功能呢,大部分的DSP内部函数都带有了FIR函数,直接调用即可。但是FIR滤波器是很占资源的,使用CPU去做,很难达到理想的一种应用,要在时间和处理之间进行平衡。ADISHARC DSP呢,它自带有FIR硬件加速器,使用加速器不占用CPU时间,是非常棒的。

那么FIR加速器如何使用呢,用过VDSP的朋友应该知道,VDSP5.0有一个Accelerators插件,使用它我们可以通过参数配置的方式轻松得到一份代码例子(没有的朋友请到官网进行下载,按照文档安装)。


我们看左边的FIR Accelerator,它有很多参数,下面逐一解释:

GlobalSettings for all channels

-No ofChannels : 需要做FIR滤波器的通道数,FIR采用TDM方式将外部数据搬移到加速器。

-DataFormat: 数据格式指定定点还是浮点,既然是SHARC DSP,它肯定是浮点了。

-AutoIterate?: 自动迭代,一帧数据处理完后是否自动从TCB加载数据处理。设置为否,需要CPU启动。

-RoundingMode: 舍入模式,此处默认即可,既然是浮点,影响不大。

-DMAInterrupt: 指定DMA中断发生在CPU哪个中断脚。

-Statusinterrupt: 状态中断,正常状态下无需设置。

-InterruptWhen: 何时中断,是所有通道都处理完了中断还是单个通道处理完了就中断CPU

ChannelSpecific Setting: 这里的设置我们先不管吧,主要对BUFFER进行设置,使用这个软件进行设置还不如直接进行代码修改来得快。注意到里面有一个Sample Rate Convertion,也就是说它还有采样率转换,比如输入48KFIR滤波之后得到8k的数据,降采样,这个时候我们将Ratio设置为6。本文将采用单速率的方式,此处不需要进行设置。

好,我们来看看产生的代码例子,#defineTAPS 512#define WINDOWSIZE 512,具体根据应用情况进行修改。

/*  This file includes the initialization codes for FIR, IIR and FFT Accelerators  */

 

#include  "def21489.h"

#include  "Cdef21489.h"

 

void  Init_FIR();

 

/*  Declaring the external buffers needed for FIR Accelerator*/

extern  int FIR_IP_buff1[];  //输入数据BUFFER,大小为TAPS+WINDOWSIZE-1

extern  int FIR_OP_buff1[]; //输出BUFFER,大小为WINDOWSIZE

extern  int FIR_CF_buff1[]; //系数BUFFER,大小为TAPS

 

extern  int FIR_IP_buff2[];

extern  int FIR_OP_buff2[];

extern  int FIR_CF_buff2[];

 

//这个很重要,DMA TCB配置

/*Adding  the TCB for FIR channels*/

int  FIR_TCB_CH2[13]={

                                     0,//链式指针寄存器

                                     512 TAPS,//系数buffer长度寄存器,我们修改为宏定义TAPS

                                     1  -1, //系数修改寄存器,根据加速器

                                     FIR_CF_buff2,

                                     FIR_OP_buff2,

                                     512  WINDOWSIZE, //输出BUFFER长度寄存器

                                     1,

                                     FIR_OP_buff2+0,

                                     FIR_IP_buff2,

                                     512  TAPS+ WINDOWSIZE-1,//输入BUFFER长度寄存器

                                     1,

                                     FIR_IP_buff2+0,

                                     511|(511<<14)  TAPS -1|((WINDOW_SIZE-1)<<14)

                            };

 

 

//TCB1亦如是配置

int  FIR_TCB_CH1[13]={

                                     FIR_TCB_CH2+12,

                                     512,

                                     1,

                                     FIR_CF_buff1,

                                     FIR_OP_buff1,

                                     512,

                                     1,

                                     FIR_OP_buff1+0,

                                     FIR_IP_buff1,

                                     512,

                                     1,

                                     FIR_IP_buff1+0,

                                     511|(511<<14)

                            };

 

 

/*  Adding the Initialization Code for FIR Accelerator Now */

 

void  Init_FIR()

{

 

         int temp;

//链式指针寄存器

         FIR_TCB_CH2[0]=FIR_TCB_CH1+12;

  //这里映射DMA中断到PI0

         //Mapping the FIR DMA interrupt

         temp=*pPICR0;

         temp&=~(P0I0|P0I1|P0I2|P0I3|P0I4);

         temp|=P0I0|P0I1|P0I3|P0I4;

         *pPICR0=temp;

//选择FIR加速器,FIR,IIR,FFT只能使用一个,能不能同时使用三个,这是不行的

         //Selecting the FIR Accelerator

         temp=*pPMCTL1;

         temp&=~(BIT_17|BIT_18);

         temp|=FIRACCSEL;

         *pPMCTL1=temp;

 

         //PMCTL1 effect latency

                   asm("nop;nop;nop;nop;");

 

                   //Initializing the chain  pointer register

         *pCPFIR=FIR_TCB_CH1+12-0x80000;

//使能加速器,一旦配置好,加速器就会运行,这里将它注释掉

         //Now Enabling the FIR Accelerator

         *pFIRCTL1=FIR_EN|FIR_DMAEN|FIR_CH2|FIR_RND0;

 

}

 

 

上面呢,将加速器的使能语句注释掉了,是什么原因呢。在音频系统里面,DSP是按音频的采样率取帧进行处理,也就是采集到了一个WINDOWSIZE即产生中断,开始音频处理任务。如果你FIR加速器马上使能或者让它自动迭代处理,无法配合我们的应用程序完成数据同步的问题。最好的办法是音频处理完一帧,使能FIR加速器,在音频的下一帧处理中,我们就可以引用加速器处理之后的数据了,再将需要处理的数据扔回给加速器。

最后,还有一个问题,细心的朋友可能会发现,输入BUFFER长度是TAPS+WINDOWSIZE -1,那么输入数据该如何填充呢?OK,这是一个循环buffer,初始化的时候定义一个指针指向TAPS-1位置。在填充数据时,使用circptr内联函数将指针重定义位置,直接看代码吧。

float*  inptr = fir_ip_bufffer(0)+handle->taps-1;        //初始化为taps-1位置

.........

//填充数据代码段

for(i=0;i<WINDOWSIZE;i++){

         out_ptr[i] = optr[i];    //optFIR输出buffer

         *handle->inptr = in_ptr[i]; //音频采样过来的数据,填给FIR输入buffer

         handle->inptr =  circptr(handle->inptr,1,iptr, handle->taps + WINDOW_SIZE - 1);//移动指针

}

这样明了吗,有什么不明白的地方请在公众号ddongcloud发信息给我!


作为一名技术工程师,我希望将我的知识分享给大家,帮助到大家一点点。如有写得有误的地方请指教,欢迎探讨!原创不易,尤其一个一个文字敲打出来,这都是实践中总结出来的步骤和方法。大家喜欢,请关注我的公众号:ddongcloud ,更多的原创文章和您分享。


0 0
原创粉丝点击