CSI-DSP  Version 1.0.0
CSI DSP Software Library
Content | 函数
直接I型IIR滤波器

Content

 高精度Q31直接I型IIR滤波器
 

函数

void csky_biquad_cascade_df1_f32 (const csky_biquad_casd_df1_inst_f32 *S, float32_t *pSrc, float32_t *pDst, uint32_t blockSize)
 
void csky_biquad_cascade_df1_fast_q15 (const csky_biquad_casd_df1_inst_q15 *S, q15_t *pSrc, q15_t *pDst, uint32_t blockSize)
 
void csky_biquad_cascade_df1_fast_q31 (const csky_biquad_casd_df1_inst_q31 *S, q31_t *pSrc, q31_t *pDst, uint32_t blockSize)
 
void csky_biquad_cascade_df1_init_f32 (csky_biquad_casd_df1_inst_f32 *S, uint8_t numStages, float32_t *pCoeffs, float32_t *pState)
 浮点二阶级联滤波器的初始化函数 更多...
 
void csky_biquad_cascade_df1_init_q15 (csky_biquad_casd_df1_inst_q15 *S, uint8_t numStages, q15_t *pCoeffs, q15_t *pState, int8_t postShift)
 
void csky_biquad_cascade_df1_init_q31 (csky_biquad_casd_df1_inst_q31 *S, uint8_t numStages, q31_t *pCoeffs, q31_t *pState, int8_t postShift)
 
void csky_biquad_cascade_df1_q15 (const csky_biquad_casd_df1_inst_q15 *S, q15_t *pSrc, q15_t *pDst, uint32_t blockSize)
 Q15二阶级联滤波器处理函数 更多...
 
void csky_biquad_cascade_df1_q31 (const csky_biquad_casd_df1_inst_q31 *S, q31_t *pSrc, q31_t *pDst, uint32_t blockSize)
 Q31二阶级联滤波器处理函数 更多...
 

简要说明

这些函数实现了任意阶递归(IIR)滤波器。 滤波器是由二阶单元Biquad级联实现。 为Q15,Q31和浮点数据类型都提供了函数。

函数以块单位操作输入输出数据。每次调用函数通过滤波器处理 blockSize 个样本。 pSrc 指向输入数组数据, pDst 指向输出数组数据。 两个数组都包含 blockSize 个数值.

算法
每个二阶阶段都使用差分方程实现一个二阶滤波:
    y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] + a1 * y[n-1] + a2 * y[n-2]
直接I型每个阶段使用5个系数和4个状态变量。
Biquad.gif
单个二阶滤波阶段
系数 b0, b1 和 b2 与输入信号 x[n] 相乘,并且被称为前馈系数。 系数 a1a2 与输出信号 y[n] 相乘,并且被称为反馈系数。
需要注意反馈系数的符号. 有些设计工具使用差分方程:
    y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
这种情况下,反馈系数 a1a2 在使用CSI DSP库的时候,必须取相反数。
高阶滤波器通过级联的二阶单元实现。 numStages 指定使用了多少二阶阶段。 比如,第8阶滤波器是numStages=4 的二阶阶段。
BiquadCascade.gif
使用二阶级联的8阶滤波器
第9阶滤波器可以看做 numStages=5 的二阶阶段,系数配置为第一阶 (b2=0a2=0).
pState 指向状态变量数组. 每个二阶阶段有4个状态变量 x[n-1], x[n-2], y[n-1],y[n-2]. 状态变量被排列在 pState :
    {x[n-1], x[n-2], y[n-1], y[n-2]}
阶段1使用最开始的4个状态变量,阶段2使用接下来的4个状态变量,依次类推。 状态变量数组总共有 4*numStages 个值。 每个块数据处理会更新状态变量,不会更新系数。
结构体实例
滤波器的系数和状态变量都保存在数据结构中。 每个滤波器都必须有一个单独的结构体实例。 系数数组可能可以在几个实例共享,但是变量数组不能共享。 支持的3种数据类型都有定义不同的结构体实例类型.
初始化函数
每种数据类型都有相应的初始化函数。 初始化函数处理以下操作:
  • 设置数据结构字段的值.
  • 清零状态buffer的值. 不使用初始化函数,手动处理这些操作,需要设置结构体实例内的以下字段: numStages, pCoeffs, pState. 将pState的所有值置0.
是否使用初始化函数是可选的. 但是,如果使用初始化函数,则结构体实例不能被放在常量数据段。 想要将结构体实例放在常量数据段,则必须手动的初始化结构体实例。 在静态初始化之前,先把状态buffer中的值置0。 下列代码演示了静态初始化3中不同数据类型的滤波器的结构体实例。
    csky_biquad_casd_df1_inst_f32 S1 = {numStages, pState, pCoeffs};
    csky_biquad_casd_df1_inst_q15 S2 = {numStages, pState, pCoeffs, postShift};
    csky_biquad_casd_df1_inst_q31 S3 = {numStages, pState, pCoeffs, postShift};
其中 numStages 是滤波器中二阶阶段的数量; pState 是状态buffer的地址; pCoeffs 是系数buffer的地址; postShift 是移位数.
定点行为
使用Q15和Q31版本的二阶级联滤波函数需要多加注意。 需要考虑以下问题:
  • 系数的缩放
  • 滤波的增益
  • 溢出和饱和
系数的缩放: 滤波器系数表示为小数值,并且系数限制在[-1 +1) 范围之间. 定点函数有一个额外的缩放参数 postShift , 用于给滤波器系数放大到超过[+1 -1)范围。 滤波器的累加器的输出是一个移位寄存器,结果移动postShift 位.
BiquadPostshift.gif
定点二阶累加后带移位
这本质上将滤波器的系数缩放了2^postShift倍. 比如,为了表示系数
   {1.5, -0.8, 1.2, 1.6, -0.9}
可以设置pCoeffs数组为:
   {0.75, -0.4, 0.6, 0.8, -0.45}
并且设置postShift=1
滤波器增益: 二阶滤波器的频率响应是它函数的一个系数。 通过滤波器的增益可能超过1.0,这意味着滤波器增加了某些频率的幅度。 这意味着幅度小于1.0的输入信号可能导致输出大于 1.0,因此基于滤波器的实现,这些信号可能会饱和或溢出。 为了避免这种行为,滤波器需要按比例缩小,使得其峰值增益小于1.0,或输入信号必须按比例缩小,以便输入和滤波器的组合不会溢出
溢出和饱和: 对于Q15和Q31版本, 在各自函数的说明文档分别描述.

函数说明

void csky_biquad_cascade_df1_f32 ( const csky_biquad_casd_df1_inst_f32 S,
float32_t pSrc,
float32_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向一个浮点二阶级联结构实例
[in]*pSrc指向输入数据块
[out]*pDst指向输出数据块
[in]blockSize每个块需要处理的样本数量
返回
none.
void csky_biquad_cascade_df1_fast_q15 ( const csky_biquad_casd_df1_inst_q15 S,
q15_t pSrc,
q15_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向Q15二阶级联数据结构实例.
[in]*pSrc指向输入数据块
[out]*pDst指向输出数据块
[in]blockSize处理的样本数量
返回
none.

缩放和溢出行为:

快速版本使用一个2.30格式的32位累加器。 累加器维持了中间乘法结果的所有精度,但是只有一个守护位。 因此,如果累加器结果溢出,会往符号位覆盖,而不是截断。 为了防止溢出,输入信号必须先缩小两个位,到[-0.25 +0.25)范围。 2.30累加器的结果移动 postShift 位,并且结果通过丢弃低16位,截断为1.15格式。
参考函数 csky_biquad_cascade_df1_q15() 使用了64位累加器实现了一个更慢的版本防止精度丢失。慢的和快的版本使用了相同的结构体实例。 使用函数 csky_biquad_cascade_df1_init_q15() 初始化滤波器结构.
void csky_biquad_cascade_df1_fast_q31 ( const csky_biquad_casd_df1_inst_q31 S,
q31_t pSrc,
q31_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向Q31二阶级联结构体实例
[in]*pSrc指向输入数据块
[out]*pDst指向输出数据块
[in]blockSize处理样本数量
返回
none.

缩放和溢出行为:

该函数针对速度进行了优化,牺牲了定点精度和溢出保护. 每个1.31和1.31相乘的结果截断为2.30格式。 这些中间结果相加到一个2.30累加器。 最后,累加器饱和并且转换为1.31的结果。 快速版本具有与标准版本相同的溢出行为,但是提供较低的精度,因为它丢弃每个乘法结果的低32位。 为了防止溢出,输入信号必须先缩小两个位,到[-0.25 +0.25)范围。 使用初始化函数 csky_biquad_cascade_df1_init_q31() 来初始化滤波器结构体.
参数函数 csky_biquad_cascade_df1_q31() 是这个函数的一个更慢的实现,为更高精度使用了一个64位累加器。慢速和快速的版本都使用了相同的结构体。 使用函数 csky_biquad_cascade_df1_init_q31() 来初始化滤波器结构体.
void csky_biquad_cascade_df1_init_f32 ( csky_biquad_casd_df1_inst_f32 S,
uint8_t  numStages,
float32_t pCoeffs,
float32_t pState 
)
参数
[in,out]*S指向浮点二阶级联滤波器结构体实例
[in]numStages滤波器中二阶阶段的数量
[in]*pCoeffs指向滤波器系数数组
[in]*pState指向状态数组
返回
none

系数和状态顺序:

系数按以下顺序保存在数组pCoeffs :
    {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
其中 b1xa1x 是第一个阶段的系数, b2xa2x 是第二个阶段的系数,依次类推。 pCoeffs 数组总共有5*numStages个数值.
pState 是指向状态数组的指针. 每个二阶阶段有4个状态变量x[n-1], x[n-2], y[n-1],y[n-2]. 状态变量排列在pState 数组的顺序如下:
    {x[n-1], x[n-2], y[n-1], y[n-2]}
最前面是第一阶段的4个状态变量, 然后是第二阶段的4个状态变量,依次类推。 状态数组总共有4*numStages 个数值. 状态变量在数据块处理之后更新,系数不会更新。
void csky_biquad_cascade_df1_init_q15 ( csky_biquad_casd_df1_inst_q15 S,
uint8_t  numStages,
q15_t pCoeffs,
q15_t pState,
int8_t  postShift 
)
参数
[in,out]*S指向Q15二阶级联结构体实例
[in]numStages滤波器内二阶阶段的数量
[in]*pCoeffs指向滤波器系数
[in]*pState指向状态buffer
[in]postShift累加器结果的移位数
返回
none

系数和状态顺序:

系数按以下顺序保存在数组 pCoeffs :
    {b10, 0, b11, b12, a11, a12, b20, 0, b21, b22, a21, a22, ...}
其中 b1xa1x 是第一阶段的系数, b2xa2x 是第二阶段的系数,依次类推。 pCoeffs6*numStages 个值. b1b2 中间的填充的16位的0, 是为了让系数能够32位对齐。
状态变量保存在数组 pState. 每个二阶阶段有4个状态变量 x[n-1], x[n-2], y[n-1],y[n-2]. 状态变量排列在 pState 数组中的形式如下:
    {x[n-1], x[n-2], y[n-1], y[n-2]}
阶段1使用最开始的4个状态变量,阶段2使用接下来的4个状态变量,依次类推。 状态数组总共有 4*numStages 个值. 每个块数据处理会更新状态变量,不会更新系数。
void csky_biquad_cascade_df1_init_q31 ( csky_biquad_casd_df1_inst_q31 S,
uint8_t  numStages,
q31_t pCoeffs,
q31_t pState,
int8_t  postShift 
)
参数
[in,out]*S指向Q31二阶级联结构体实例
[in]numStages滤波器中二阶阶段的数量
[in]*pCoeffs指向滤波器系数buffer
[in]*pState指向状态buffer
[in]postShift累加器结果的移位数
返回
none

系数和状态顺序:

保存在数组 pCoeffs 的系数,按照以下顺序排列:
    {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
其中 b1xa1x 是第一阶段的系数, b2xa2x 是第二阶段的系数,依次类推。 pCoeffs 数组总共有 5*numStages 个值.
pState 指向状态变量数组。 每个二阶阶段有4个状态变量 x[n-1], x[n-2], y[n-1],y[n-2]. 状态变量在数组 pState 中的排列顺序:
    {x[n-1], x[n-2], y[n-1], y[n-2]}
阶段1使用最开始的4个状态变量,阶段2使用接下来的4个状态变量,依次类推。 状态变量数组总共有 4*numStages 个值. 每个块数据处理会更新状态变量,不会更新系数。
示例:
csky_graphic_equalizer_example_q31.c.
void csky_biquad_cascade_df1_q15 ( const csky_biquad_casd_df1_inst_q15 S,
q15_t pSrc,
q15_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向Q15二阶级联结构体实例
[in]*pSrc指向输入数据块
[out]*pDst指向输出数据块
[in]blockSize每次处理的数据数量
返回
none.

缩放和溢出行为:

函数实现使用了一个内部64位累加器。 系数和状态变量都用1.15格式表示,相乘的结果是2.30格式。 2.30格式的中间结果用一个64位的累加器累加成34.30格式的结果。 这里可以保留中间结果的精度,并且不会溢出。 最后的结果,饱和转换为1.15格式。
参考:函数 csky_biquad_cascade_df1_fast_q15() 是一个更快的版本,但是丢失了部分精度。
void csky_biquad_cascade_df1_q31 ( const csky_biquad_casd_df1_inst_q31 S,
q31_t pSrc,
q31_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向Q31二阶级联滤波器结构体实例
[in]*pSrc指向输入数据块
[out]*pDst指向输出数据块
[in]blockSize处理样本的数量
返回
none.

缩放和溢出行为:

函数实现使用了一个内部64位累加器。 累加器是2.62格式,维护了中间结果的所有精度,但是只有一个保护位。 因此,如果累加器结果溢出,会往符号位溢出,而不是截断。 为了防止溢出,输入信号必须缩小2位,缩放到 [-0.25 +0.25) 区间. 在处理5个相乘结果累加之后, 2.62 累加器移动 postShift 位,并且丢弃低32位,将结果截断为1.31格式。
参考:函数 csky_biquad_cascade_df1_fast_q31() 是一个快速版本,但是丢失了更多精度的实现。
示例:
csky_graphic_equalizer_example_q31.c.