CSI-DSP  Version 1.0.0
CSI DSP Software Library
函数
有限冲激响应 (FIR) 插值器

函数

void csky_fir_interpolate_f32 (const csky_fir_interpolate_instance_f32 *S, float32_t *pSrc, float32_t *pDst, uint32_t blockSize)
 浮点FIR插值器处理函数 更多...
 
csky_status csky_fir_interpolate_init_f32 (csky_fir_interpolate_instance_f32 *S, uint8_t L, uint16_t numTaps, float32_t *pCoeffs, float32_t *pState, uint32_t blockSize)
 浮点FIR插值器的初始化函数 更多...
 
csky_status csky_fir_interpolate_init_q15 (csky_fir_interpolate_instance_q15 *S, uint8_t L, uint16_t numTaps, q15_t *pCoeffs, q15_t *pState, uint32_t blockSize)
 Q15 FIR插值器的初始化函数 更多...
 
csky_status csky_fir_interpolate_init_q31 (csky_fir_interpolate_instance_q31 *S, uint8_t L, uint16_t numTaps, q31_t *pCoeffs, q31_t *pState, uint32_t blockSize)
 Q31 FIR插值器的初始化函数 更多...
 
void csky_fir_interpolate_q15 (const csky_fir_interpolate_instance_q15 *S, q15_t *pSrc, q15_t *pDst, uint32_t blockSize)
 Q15 FIR插值器处理函数 更多...
 
void csky_fir_interpolate_q31 (const csky_fir_interpolate_instance_q31 *S, q31_t *pSrc, q31_t *pDst, uint32_t blockSize)
 Q31 FIR插值器处理函数 更多...
 

简要说明

函数组合了一个过采样器 (零填充) 和一个FIR滤波器。

这些函数用于多速率系统中,在不引入高频图像的情况下增加信号的采样率。

从概念上讲,这些功能等同于下面的框图:

FIRInterpolator.gif
FIR插值器中的组件

通过因子 L 过采样后, 信号需要用一个截止频率 1/L 的低通滤波器滤波,以便消除频谱的高频拷贝。 函数的调用者负责提供滤波器的系数。

CSI DSP库中的FIR插值函数提供了过采样器和FIR滤波器的一种组合方式。 过采样器在样本中插入了 L-1 个0. 滤波器设计成不会与这些插值出来的0相乘,而是直接跳过,这样可以提高效率,减少计算量。 函数以块为单位操作输入输出数据。 pSrc 指向一个大小为 blockSize 的输入数组, pDst 指向一个大小为 blockSize*L 的输出数组.

DSP库为Q15,Q31和浮点数据类型分别提供了不同的函数。

算法:
函数使用一个多相滤波器结构:
   y[n] = b[0] * x[n] + b[L]   * x[n-1] + ... + b[L*(phaseLength-1)] * x[n-phaseLength+1]
   y[n+1] = b[1] * x[n] + b[L+1] * x[n-1] + ... + b[L*(phaseLength-1)+1] * x[n-phaseLength+1]
   ...
   y[n+(L-1)] = b[L-1] * x[n] + b[2*L-1] * x[n-1] + ....+ b[L*(phaseLength-1)+(L-1)] * x[n-phaseLength+1]
这种方式比直接过采样,然后滤波的算法更效率。 这种方式的计算量减少到标准FIR滤波器的 1/L.
pCoeffs 指向一个系数数组,数组大小为 numTaps. numTaps 必须是插值因子的 L 的倍数,并且会在初始化函数里检查。 函数内部会将FIR滤波器的冲激响应除成更短的长度 phaseLength=numTaps/L. 系数的保存顺序如下:
   {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}
pState 指向状态数组,数组的大小为 blockSize + phaseLength - 1. 状态缓存中的保存顺序如下:
   {x[n-phaseLength+1], x[n-phaseLength], x[n-phaseLength-1], x[n-phaseLength-2]....x[0], x[1], ..., x[blockSize-1]}
状态变量在数据块处理的时候会更新,系数不会更新。
结构体实例
滤波器的系数和状态变量都保存在数据结构的实例中。 每个滤波器都必须要有一个结构体实例。 系数数组可能可以在几个实例之间共享,但是状态变量数组必须单独分配。 为浮点,Q31和Q15数据类型分别提供了不同的结构体实例声明。
初始化函数
每种数据类型都有一个相应的初始化函数。 初始化函数处理以下操作:
  • 设置内部结构体字段的值
  • 清零状态缓存
  • 确保滤波器的长度是插值因子的整数倍 如果手动初始化,而不调用初始化函数,需要指定结构体实例的以下字段: L (插值因子), pCoeffs, phaseLength (numTaps / L), pState. pState中的所有值置0
是否使用初始化函数是可选的。 但是,使用了初始化函数,则不能将结构体实例放在常量数据段。 要将结构体实例放在常量数据段,则必须手动初始化结构体实例。 下面的代码,为3种不同的滤波器,静态的初始化了结构体实例。
csky_fir_interpolate_instance_f32 S = {L, phaseLength, pCoeffs, pState};
csky_fir_interpolate_instance_q31 S = {L, phaseLength, pCoeffs, pState};
csky_fir_interpolate_instance_q15 S = {L, phaseLength, pCoeffs, pState};
其中 L 是插值因子; phaseLength=numTaps/L 是FIR 滤波器内部使用的更短的长度, pCoeffs 是系数缓存的地址; pState 是状态缓存的地址. 在静态初始化之前,要确保状态缓存中的值已经清零。
定点行为
使用定点FIR插值器滤波函数需要注意。 特别是要考虑,在每个函数内使用的累加器的溢出和饱和行为。 具体参考每个函数各自的文档和使用说明。

函数说明

void csky_fir_interpolate_f32 ( const csky_fir_interpolate_instance_f32 S,
float32_t pSrc,
float32_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向浮点FIR插值器结构体实例
[in]*pSrc指向输入信号块
[out]*pDst指向输出信号块
[in]blockSize处理的信号数量
返回
none.
csky_status csky_fir_interpolate_init_f32 ( csky_fir_interpolate_instance_f32 S,
uint8_t  L,
uint16_t  numTaps,
float32_t pCoeffs,
float32_t pState,
uint32_t  blockSize 
)
参数
[in,out]*S指向浮点FIR插值器的结构体实例
[in]L过采样因子
[in]numTaps滤波器中系数的数量
[in]*pCoeffs指向系数缓存
[in]*pState指向状态缓存
[in]blockSize处理的输入样本数量
返回
如果初始化成功,则返回 CSKY_MATH_SUCCESS 如果 numTaps 不是插值因子 L 的整数倍, 则返回 CSKY_MATH_LENGTH_ERROR.

描述说明:

pCoeffs 指向滤波器系数数组,保存的顺序如下:
   {b[numTaps-1], b[numTaps-2], b[numTaps-2], ..., b[1], b[0]}
滤波器的长度 numTaps 必须是插值因子 L 的整数倍.
pState 指向状态变量数组。 pState 的长度是 (numTaps/L)+blockSize-1 。 其中 blockSize 是处理的输入样本数量,传给 csky_fir_interpolate_f32().
csky_status csky_fir_interpolate_init_q15 ( csky_fir_interpolate_instance_q15 S,
uint8_t  L,
uint16_t  numTaps,
q15_t pCoeffs,
q15_t pState,
uint32_t  blockSize 
)
参数
[in,out]*S指向Q15 FIR插值器的结构体实例
[in]L过采样因子
[in]numTaps滤波器中系数的数量
[in]*pCoeffs指向系数缓存
[in]*pState指向状态缓存
[in]blockSize处理的输入样本数量
返回
如果初始化成功,则返回 CSKY_MATH_SUCCESS 如果 numTaps 不是插值因子 L 的整数倍, 则返回 CSKY_MATH_LENGTH_ERROR.

描述说明:

pCoeffs 指向滤波器系数数组,保存的顺序如下:
   {b[numTaps-1], b[numTaps-2], b[numTaps-2], ..., b[1], b[0]}
滤波器的长度 numTaps 必须是插值因子L的整数倍.
pState 指向状态变量数组. pState 的长度是 (numTaps/L)+blockSize-1 , 其中 blockSize 是处理的输入样本数量,传给 csky_fir_interpolate_q15().
csky_status csky_fir_interpolate_init_q31 ( csky_fir_interpolate_instance_q31 S,
uint8_t  L,
uint16_t  numTaps,
q31_t pCoeffs,
q31_t pState,
uint32_t  blockSize 
)
参数
[in,out]*S指向Q31 FIR插值器的结构体实例
[in]L过采样因子
[in]numTaps滤波器中系数的数量
[in]*pCoeffs指向系数缓存
[in]*pState指向状态缓存
[in]blockSize处理的输入样本数量
返回
如果初始化成功,则返回 CSKY_MATH_SUCCESS 如果 numTaps 不是插值因子 L 的整数倍, 则返回 CSKY_MATH_LENGTH_ERROR.

描述说明:

pCoeffs 指向滤波器系数数组,保存的顺序如下:
   {b[numTaps-1], b[numTaps-2], b[numTaps-2], ..., b[1], b[0]}
滤波器的长度 numTaps 必须是插值因子 L 的整数倍.
pState 指向状态变量数组。 pState 的长度是 (numTaps/L)+blockSize-1 , 其中 blockSize 是处理的输入样本数量,传给 csky_fir_interpolate_q31().
void csky_fir_interpolate_q15 ( const csky_fir_interpolate_instance_q15 S,
q15_t pSrc,
q15_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向Q15 FIR插值器结构体实例
[in]*pSrc指向输入数据块
[out]*pDst指向输出数据块
[in]blockSize处理的输入样本数量
返回
none.

缩放和溢出行为:

函数实现使用了一个内部64位累加器。 输入数据表示为1.15格式。 中间乘法生成2.30格式的结果,结果在34.30格式的64位累加器累加。 因为有33位保护位,所以不会有溢出的风险。同时还可以保存所有的中间乘法结果的精度。 最后,34.30格式的丢弃低15位截断为34.15,然后饱和生成1.15格式的结果。
void csky_fir_interpolate_q31 ( const csky_fir_interpolate_instance_q31 S,
q31_t pSrc,
q31_t pDst,
uint32_t  blockSize 
)
参数
[in]*S指向Q31 FIR插值器结构体实例
[in]*pSrc指向输入数据块
[out]*pDst指向输出数据块
[in]blockSize输入样本的数量
返回
none.

缩放和溢出行为:

函数实现使用了一个内部64位累加器。 输入数据表示为1.31格式。 中间乘法生成2.62格式的结果,结果在2.62格式的64位累加器累加。 因为只有一个保护位,所以需要缩小输入信号来防止溢出。 因为最多会有numTaps/L个加法进位,所以需要缩小1/(numTaps/L)才可以保证没有溢出。 最后,2.62格式右移31位,然后饱和生成1.15格式的结果。