题目:16k采样率音频数据下采样到8k采样率

求解方案分析:直接每隔一个取一个采样值,这样就可以得到8k采样率的数据。但是这样明显会有问题。按照采样率变换理论,首先应该通过一个低通滤波器,滤掉[pi/2, pi]这个区间上的频率,以防止下采样造成的频率混叠。这个低通滤波器在很多书上都用FIR滤波去实现,并且可以用FIR滤波的多相结构去实现。这样滤波和下采样过程可以互换位置。即先下采样再进行多相FIR滤波。

在嵌入式设备上FIR滤波会占用较长的时间,为此,我们可以采用IIR滤波器来做。滤波器的设计采用MATLAB的FDATool工具。相关的参数如下:

采用最小P阶范数设计IIR滤波器的幅频特性较好。滤波器阶数设定为6阶,需要滤除4k到8k的频率段,才能保证无混叠失真。实际由于滤波器的特性没法做到理想的状态,选择滤波器截止频率为3800hz,3600到3800为过渡带宽。其它选项采用默认设置。设计的滤波器幅度响应如下图:

生成的滤波器系数文件如下:

/*

* Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool

*

* Generated by MATLAB(R) 7.6 and the Signal Processing Toolbox 6.9.

*

* Generated on: 03-Dec-2010 10:41:03

*

*/

/*

* Discrete-Time IIR Filter (real)

* ——————————-

* Filter Structure    : Direct-Form II, Second-Order Sections

* Number of Sections  : 3

* Stable              : Yes

* Linear Phase        : No

*/

/* General type conversion for MATLAB generated C-code  */

#include “tmwtypes.h”

/*

* Expected path to tmwtypes.h

* D:/MATLAB/R2008a/extern/include/tmwtypes.h

*/

#define MWSPT_NSEC 7

const int NL[MWSPT_NSEC] = { 1,3,1,3,1,3,1 };

const real64_T NUM[MWSPT_NSEC][3] = {

{

0.09065504059673,                 0,                 0

},

{

1,  -0.1323122149853,   0.9999674089086

},

{

1,                 0,                 0

},

{

1,   0.1670351201308,   0.9999889247428

},

{

1,                 0,                 0

},

{

1,    1.417032671609,   0.9978019623105

},

{

1,                 0,                 0

}

};

const int DL[MWSPT_NSEC] = { 1,3,1,3,1,3,1 };

const real64_T DEN[MWSPT_NSEC][3] = {

{

1,                 0,                 0

},

{

1,    -0.40321085647,   0.7334254033056

},

{

1,                 0,                 0

},

{

1,  -0.6868636040216,   0.2670185171768

},

{

1,                 0,                 0

},

{

1,  -0.2880720042256,   0.9480010462991

},

{

1,                 0,                 0

}

};

上述系数是3个2阶节IIR结构的级联。可以转换为我们熟悉的b/a的形式如下:

double a[3][3] = {

{1,  -0.6868636040216,   0.2670185171768},

{1,    -0.40321085647,   0.7334254033056},

{1,  -0.2880720042256,   0.9480010462991}

};

double b[3][3] = {

{1,   1.417032671609,   0.9978019623105},

{1,   0.1670351201308,   0.9999889247428},

{1,  -0.1323122149853,   0.9999674089086},

};

注意上面系数文件中还有一个增益:

double gain =  0.09065504059673;

这个增益最好在第一级实现以后加入运算。这样可以减小误差,保证数据 动态范围不被溢出。尤其是在定点计算的时候尤为如此。

2阶节IIR滤波的直接实现

一个2阶节结构是下面这样一个表达式:

实现上面这个表达式需要4个过去的历史值,把它定义在结构体

typedef struct tag_ IIR_State_2order

{

float y2;

float y1;

float x1;

float x0;

} IIR_State_2order;

调用下面函数之前需要把上述结构体所有值初始化为零。滤波按一帧一帧数据进行。

#define  ONE_FRAME_SAMPLE_SIZE   1024

void cy_signal_filter_by_iir(signed short* pcmIn, IIR_State_2order* filter_state, float a[], float b[], signed short*pcmOut)

{

int i;

float x2;

float tmp;

for ( i = 0; i < ONE_FRAME_SAMPLE_SIZE; i++ )

{

x2 = filter_state->x1;

filter_state->x1 = filter_state->x0;

filter_state->x0 = pcmIn[i];

tmp = ( float )(b[0]* filter_state->x0 + b[1]* filter_state->x1 +

b[2] * x2 - a[1] * filter_state->y1 - a[2] * filter_state->y2);

if(tmp >= 32767)

{

tmp = 32767;

}

if(tmp <= -32768)

{

tmp = -32768;

}

pcmOut[i] = (signed short)tmp;

filter_state->y2 = filter_state->y1;

filter_state->y1 = tmp;

}

}

有一个简单的技巧可以把上面的计算简化,使得历史状态数由4减少为2。定义下面的表达式:

结构体定义如下:

typedef struct tag_ IIR_State_2order

{

float st1;

float st2;

} IIR_State_2order;

void cy_signal_filter_by_iir(signed short* pcmIn, IIR_State_2order* filter_state, float a[], float b[], signed short*pcmOut)

{

int i;

float st;

float Tmp_fl;

for ( i = 0; i < ONE_FRAME_SAMPLE_SIZE; i++ )

{

st = (float)(pcmIn[i] -  a[1] * filter_state->st1  - a[2] * filter_state-> st2);

Tmp_fl = b[0] *  st + b[1] * filter_state->st1 + b[2] * filter_state->st2;

filter_state->st2= filter_state->st1;

filter_state->st1 = st;

if(Tmp_fl >= 32767.0)

{

Tmp_fl = 32767;

}

if(Tmp_fl <= -32768)

{

Tmp_fl = -32768;

}

pcmOut[i] = (signed short)Tmp_fl;

}

}

6阶节IIR滤波的实现

有个上面的基础,我们来实现上面设计的6阶IIR滤波器。

6阶节分解为3个2阶节级联实现。每个2阶节需要2个历史状态,总共需要6个历史状态。结构体定义如下:

typedef struct tag_IIR_State_3Order

{

double w01;

double w02;

double w11;

double w12;

double w21;

double w22;

}IIR_State_6order;

代码中数组a,b,还有gain的定义见第一部分。

void cy_signal_filter_by_6th_iir(signed short* pcmIn, IIR_State_6order* filter_state, int sample_size)

{

double x1, x2, x3, Tmp_f00, Tmp_f10, Tmp_f20;

int i;

double Tmp_pcm;

for (i = 0; i < sample_size; i++)

{

Tmp_pcm = pcmIn[i];

Tmp_f00 = Tmp_pcm - a[0][1] * filter_state->w01 - a[0][2] * filter_state->w02;

x1 = Tmp_f00 + b[0][1] * filter_state->w01 + b[0][2] * filter_state->w02;

filter_state->w02 = filter_state->w01;

filter_state->w01 = Tmp_f00;

x1 = gain * x1;

Tmp_f10 = x1 - a[1][1] * filter_state->w11 - a[1][2] * filter_state->w12;

x2 = Tmp_f10 + b[1][1] * filter_state->w11 + b[1][2] * filter_state->w12;

filter_state->w12 = filter_state->w11;

filter_state->w11 = Tmp_f10;

Tmp_f20 = x2 - a[2][1] * filter_state->w21 - a[2][2] * filter_state->w22;

x3 = Tmp_f20 * b[2][0] + b[2][1] * filter_state->w21 + b[2][2] * filter_state->w22;

filter_state->w22 = filter_state->w21;

filter_state->w21 = Tmp_f20;

if (x3 >= 32767)

{

x3 = 32767;

}

if (x3 <= -32768)

{

x3 = -32768;

}

pcmIn[i] = (signed short)x3;

}

}

最后看下滤波的效果:

滤波之后的频谱:

滤波效果不错,下面可以进行下采样了。

【转载】二阶滤波器级联(C浮点实现)相关推荐

  1. EQ、双二阶滤波器设计

    1. EQ 看这篇即可.链接: 音频EQ系数的生成 双线性变换 通用二阶滤波器的实现 二阶滤波器级联(C浮点实现) 1.1 高通/低通 巴特 滤波器的Q值对滤波的影响 2. Phase correct ...

  2. mel滤波器组频率响应曲线_了解二阶滤波器的奈奎斯特图

    在之前的文章中,我介绍了奈奎斯特图,然后我们通过检查奈奎斯特曲线和截止频率与一阶无源滤波器之间的关系,更详细地探索了这些类型的图.在本文中,我们将查看二阶滤波器的奈奎斯特图. 二阶过滤器 当我说&qu ...

  3. 飞控中的IIR二阶滤波器

    之前我们讲过一阶滤波器,思路就是把一个连续的滤波器形式,通过离散化的方式,转换成差分方程. 同事拿着我的文章,对照着代码里的二阶滤波,表示完全看不懂,我说不可能,二阶不过是一阶的升级版,思路应是一样的 ...

  4. 什么是二阶滤波器?有什么优点?

    原文来自公众号:工程师看海 滤波器是常见的信号调理电路,其中低通滤波器最为普遍,我们常听说一阶滤波器.二阶滤波器,二者有什么差别呢? 低通滤波器有3个重要参数:通带.阻带和过度带,理想的滤波器是没有过 ...

  5. 基于OP放大器的有源模拟滤波器设计--双二阶滤波器

    "双二阶滤波器由两个积分器和一个单位增益的反相放大器组成." 01 - 双二阶滤波器推导 双二阶滤波器的两个积分器有一个是有耗型的,反相放大器仅仅是进行极性反转,如果两个积分器中的 ...

  6. 【万能逼近】基于自适应模糊控制技术的万能逼近原理以及自适应二阶滤波器对AUV五个自由度的外界不规则干扰进行估计和补偿simulink仿真

    1.软件版本 matlab2017b 2.本算法理论知识 自适应二阶滤波器,大概的原理如下所示: 在原来的基础上,对wn参数进行自适应更新 即,更新wn参数,wn的更新由滤波器的误差,通过PID将误差 ...

  7. 【测控电路】信号分离电路 二阶滤波器 RC滤波电路

    ref <测控电路 第五版> 文章目录 一阶滤波器 二阶低通&高通滤波器 二阶带通&带阻滤波器 一二阶常通滤波器 一阶有源滤波电路 压控电压源型滤波电路 无限增益多路反馈型 ...

  8. 多级LC滤波器级联问题

    ····首先参考森荣二<LC滤波器设计与制作>的第二章节最后例题,我们要对一个400hz,±0.5V的方波信号进行滤除3.5.7次谐波,得到400hz的正弦波. ····利用m推演型LC滤 ...

  9. 简单二阶滤波器截止频率的计算

    最近刚好学习到这了,而我在网上查资料的时候却非常难找,不少资料讲解不够详细,所以经过我努力也为了为大家做点贡献的想法,以自己的见解写下这篇文章.废话不多说,先从一阶滤波器讲起. 一阶低通滤波器: 这个 ...

最新文章

  1. php捕获Fatal error错误与异常处理
  2. 设计模式--Builder
  3. netstat 详解
  4. Linux中修改登录提示文件
  5. IOS开发之Swift学习笔记
  6. python prt_Python中的self
  7. XPath 轴 Axes
  8. php key sort,PHP中的sort(), rsort(),asort(),arsort(),ksort(),krsort()函数
  9. QOS边界信任COS-交换机
  10. 回归的误差服从正态分布吗_10大机器学习的回归类型,你会如何选择?
  11. Arduino下载与配置
  12. android色温值转成rgb
  13. cad详图怎么画_CAD施工图怎样能画的快?老师傅教你20个制图诀窍,远超他人!
  14. 电容滤波器和电感滤波器详解(工作原理,设计详解,典型电路图)
  15. mac php fpm.pid,php-fpm的常用配置和优化
  16. [HTML/CSS]Flex布局中space-evenly的兼容性
  17. 找工作神器,提取各大网站有效的招聘信息(前程无忧、智联招聘、猎聘网)...
  18. SpringBoot 前后端分离 实现验证码操作
  19. Vue3 Application died in status LOADING_SOURCE_CODE: You need to export the functional lifecycles in
  20. 关于caj格式文件保存后总会生成xml的问题

热门文章

  1. vue3 如何给动态渲染的组件添加ref
  2. linux irc工具,构建基于Linux下的IRC服务器和WEBIRC登陆平台
  3. JAVA多线程使用场景和注意事项
  4. border渐变 ios_iOS给视图添加渐变色
  5. movie_recommendation_spark1
  6. line-height的理解
  7. this关键字及 this关键字的应用
  8. 2020年的科技趋势:随时准备改变企业的未来!
  9. CSS 层叠样式表(2)
  10. Java 输出杨辉三角