CSI-DSP  Version 1.0.0
CSI DSP Software Library
函数
归一化 LMS 滤波器

函数

void csky_lms_norm_f32 (csky_lms_norm_instance_f32 *S, float32_t *pSrc, float32_t *pRef, float32_t *pOut, float32_t *pErr, uint32_t blockSize)
 浮点归一化LMS滤波器处理函数 更多...
 
void csky_lms_norm_init_f32 (csky_lms_norm_instance_f32 *S, uint16_t numTaps, float32_t *pCoeffs, float32_t *pState, float32_t mu, uint32_t blockSize)
 浮点归一化LMS滤波器初始化函数 更多...
 
void csky_lms_norm_init_q15 (csky_lms_norm_instance_q15 *S, uint16_t numTaps, q15_t *pCoeffs, q15_t *pState, q15_t mu, uint32_t blockSize, uint8_t postShift)
 Q15归一化LMS滤波器初始化函数 更多...
 
void csky_lms_norm_init_q31 (csky_lms_norm_instance_q31 *S, uint16_t numTaps, q31_t *pCoeffs, q31_t *pState, q31_t mu, uint32_t blockSize, uint8_t postShift)
 Q31归一化LMS滤波器初始化函数 更多...
 
void csky_lms_norm_q15 (csky_lms_norm_instance_q15 *S, q15_t *pSrc, q15_t *pRef, q15_t *pOut, q15_t *pErr, uint32_t blockSize)
 Q15归一化LMS滤波器处理函数 更多...
 
void csky_lms_norm_q31 (csky_lms_norm_instance_q31 *S, q31_t *pSrc, q31_t *pRef, q31_t *pOut, q31_t *pErr, uint32_t blockSize)
 Q31归一化LMS滤波器处理函数 更多...
 

简要说明

这组函数实现了常用的自适应滤波器。 归一化LMS在最小均方 (LMS) 自适应滤波器的基础上,附加了额外的归一化因子,提高了滤波器的自适应速率。 CSI DSP 库内的归一化LMS滤波器函数支持 Q15, Q31和浮点数据类型。

一个归一化最小均方 (NLMS) 滤波器包括以下两部分。

归一化 LMS 滤波器有两个输入信号。一个是接受的输入信号,另一个是参考的输入信号, 输出两个信号,一个是FIR滤波器的输出信号,另一个是与参考输入相比的误差信号。 滤波器根据输出和参考输入之间的差值更新系数, 直到FIR滤波器的FIR滤波器的输出跟参考输入相符。 误差通过滤波器的调解倾向于0。

LMS.gif
归一化LMS滤波器中间结构

函数以块为单位处理数据,每次调用滤波器函数处理 blockSize 个样本。 pSrc 指向输入信号, pRef 指向参考信号, pOut 指向输出信号和 pErr 指向误差信号。 所有的数组都包括 blockSize 个值。

函数以块为单位操作。 滤波器内部系数 b[n] 以样本为单位更新。

算法:
输出信号 y[n] 通过标准FIR滤波器计算:
     y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1]
 
误差信号等于参考信号 d[n] 和滤波器输出的差值:
     e[n] = d[n] - y[n].
 
计算每个误差信号的每个样本后,滤波器状态变量的瞬时能量:
    E = x[n]^2 + x[n-1]^2 + ... + x[n-numTaps+1]^2.
 
滤波器系数 b[k] 以样本为单位更新:
     b[k] = b[k] + e[n] * (mu/E) * x[n-k],  for k=0, 1, ..., numTaps-1
 
其中 mu 是步进大小,控制系数收敛速率。
接口中, pCoeffs 指向系数数组,大小是 numTaps. 系数保存的顺序如下:
    {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}
 
pState 指向状态数组,数组大小是 numTaps + blockSize - 1. 样本在状态缓存中的保存顺序是:
    {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2]....x[0], x[1], ..., x[blockSize-1]}
 
注意:状态缓存的长度超过了系数数组 blockSize-1 个样本. 增长的状态缓存长度可以取代传统FIR滤波器使用的循环寻址,显著提高速度。 状态变量在每块数据处理后更新。
结构体实例
滤波器的系数和状态变量都保存在数据结构的实例中。 每个滤波器都必须有一个单独的结构体实例。 系数数组可能可以在几个实例之间共享,但是状态变量数组不能共享。 为支持的3种数据类型分别提供了不同的结构体实例声明。
初始化函数
为每种支持的数据类型都提供了一个相应的初始化函数。 初始化函数处理以下操作:
  • 设置内部结构体字段的值
  • 清零状态缓存中的值 如果手动初始化,而不调用初始化函数,需要指定结构体实例的以下字段: numTaps, pCoeffs, mu, energy, x0, pState. pState中的所有值置0. 对 Q7, Q15, 和 Q31 类型,下列字段必须被初始化: recipTable, postShift
结构体实例不能被放入常量数据段,推荐使用初始化函数初始化它。
定点行为:
使用Q15和Q31版本的归一化LMS滤波器函数需要注意。 下列问题必须考虑:
  • 系数缩放
  • 溢出和饱和
系数缩放:
滤波器系数表示为一个小数值,被限制在范围 [-1 +1) 之间。 定点函数有一个附加的缩放参数 postShift。 滤波器的输出累加器是一个可移位的寄存器,结果移动 postShift 位。 基本上就是将滤波器系数缩放 2^postShift , 允许将滤波器的系数扩展到超过范围 [+1 -1)postShift 的值根据用户系统模型期望的增益设定
溢出和饱和:
Q15和Q31版本的溢出和饱和分别描述在各个函数各自的文档部分。

函数说明

void csky_lms_norm_f32 ( csky_lms_norm_instance_f32 S,
float32_t pSrc,
float32_t pRef,
float32_t pOut,
float32_t pErr,
uint32_t  blockSize 
)
参数
[in]*S指向浮点归一化LMS滤波器结构体实例
[in]*pSrc指向输入数据块
[in]*pRef指向参考数据块
[out]*pOut指向输出数据块
[out]*pErr指向误差数据块
[in]blockSize处理的样本数量
返回
none.
示例:
csky_signal_converge_example_f32.c.
void csky_lms_norm_init_f32 ( csky_lms_norm_instance_f32 S,
uint16_t  numTaps,
float32_t pCoeffs,
float32_t pState,
float32_t  mu,
uint32_t  blockSize 
)
参数
[in]*S指向浮点归一化LMS滤波器结构体实例
[in]numTaps滤波器系数数量
[in]*pCoeffs指向系数缓存
[in]*pState指向状态缓存
[in]mu控制滤波器系数更新的步进大小
[in]blockSize处理的样本数量
返回
none.
说明描述:
pCoeffs 指向滤波器系数的数组,保存的顺序如下:
   {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}
初始化滤波器系数作为自适应滤波器的起始点。 pState 指向一个长度为 numTaps+blockSize-1 样本数组, 其中 blockSize 是处理的输入样本数量,传入函数 csky_lms_norm_f32().
示例:
csky_signal_converge_example_f32.c.
void csky_lms_norm_init_q15 ( csky_lms_norm_instance_q15 S,
uint16_t  numTaps,
q15_t pCoeffs,
q15_t pState,
q15_t  mu,
uint32_t  blockSize,
uint8_t  postShift 
)
参数
[in]*S指向Q15归一化LMS滤波器结构体实例
[in]numTaps滤波器系数数量
[in]*pCoeffs指向系数缓存指向系数缓存
[in]*pState指向状态缓存
[in]mu控制滤波器系数更新的步进大小
[in]blockSize处理的样本数量
[in]postShift系数的移位数
返回
none.

说明描述:

pCoeffs 指向滤波器系数的数组,保存的顺序如下:
   {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}
初始化滤波器系数作为自适应滤波器的起始点。 pState 指向一个长度为 numTaps+blockSize-1 样本数组, 其中 blockSize 是处理的输入样本数量,传入函数 csky_lms_norm_q15().
void csky_lms_norm_init_q31 ( csky_lms_norm_instance_q31 S,
uint16_t  numTaps,
q31_t pCoeffs,
q31_t pState,
q31_t  mu,
uint32_t  blockSize,
uint8_t  postShift 
)
参数
[in]*S指向Q31归一化LMS滤波器结构体实例
[in]numTaps滤波器系数数量
[in]*pCoeffs指向系数缓存指向系数缓存
[in]*pState指向状态缓存
[in]mu控制滤波器系数更新的步进大小
[in]blockSize处理的样本数量
[in]postShift系数的移位数
返回
none.

说明描述:

pCoeffs 指向滤波器系数的数组,保存的顺序如下:
   {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}
初始化滤波器系数作为自适应滤波器的起始点。 pState 指向一个长度为 numTaps+blockSize-1样本数组, 其中 blockSize 是处理的输入样本数量,传入函数 csky_lms_norm_q31().
void csky_lms_norm_q15 ( csky_lms_norm_instance_q15 S,
q15_t pSrc,
q15_t pRef,
q15_t pOut,
q15_t pErr,
uint32_t  blockSize 
)
参数
[in]*S指向Q15归一化LMS滤波器结构体实例
[in]*pSrc指向输入数据块
[in]*pRef指向参考数据块
[out]*pOut指向输出数据块
[out]*pErr指向误差数据块
[in]blockSize处理的样本数量
返回
none.

缩放和溢出行为:

函数实现使用了一个内部64位累加器。 系数和状态变量都表示为1.15格式。 中间乘法生成2.30格式的结果,结果在34.30格式的64位累加器累加。 因为有33位保护位,所以不会有溢出的风险。同时还可以保存所有的中间乘法结果的精度。 最后,34.30格式的丢弃低15位截断为34.15,然后饱和生成1.15格式的结果。
这个滤波器中,滤波器系数会根据样本更新,并且系数更新是饱和的。
void csky_lms_norm_q31 ( csky_lms_norm_instance_q31 S,
q31_t pSrc,
q31_t pRef,
q31_t pOut,
q31_t pErr,
uint32_t  blockSize 
)
参数
[in]*S指向Q31归一化LMS滤波器结构体实例
[in]*pSrc指向输入数据块
[in]*pRef指向参考数据块
[out]*pOut指向输出数据块
[out]*pErr指向误差数据块
[in]blockSize处理的样本的数量
返回
none.

缩放和溢出行为:

函数实现使用了一个内部64位累加器。 累加器是2.62格式,并且维持了中间乘法结果的所有精度,但是只有一个保护位。 为了防止溢出,输入信号必须缩小 log2(numTaps) 位. 参考信号不应该缩小。 在所有的乘累加处理后,2.62格式累加器右移,然后饱和生成1.31最后的结果 输出信号和错误信号是 1.31 格式.
这个滤波器中,滤波器系数会根据样本更新,并且系数更新是饱和的。