通过系统传递函数处理 WAVE 文件

Posted by XTXTMTXTX on 2020-07-02
Tech


这是什么

我实在好无聊就写了个这个。虽然还没有复习预估两个月之后的要考的一大堆课,但显然我看不下去。

代码见 Github 项目: System-Transfer-Function-For-Wave

把文件拖到它上面输入各种各样参数就可以跑起来了。至于是什么参数,请学习信号系统中的线性时不变因果和系统函数。此外,由于本质是 LTI 系统,因此改改代码是可以做到 Real-Time 处理信号的,但是我好懒。

原理

参见 Signals and Systems (Second Edition) (著: Alan V. Oppenheim, Alan S. Willsky, S. Hamid Nawab) 第九章及第十章,对于连续时间系统做拉普拉斯变换,离散时间系统做 z 变换,我们可以得到系统函数 H(s) 或 H(z), 通过 Matlab 的 tfbode 函数可以得到系统函数的波特图,而通过 lsim 函数则可以计算输入信号对应的输出信号,在此不多赘述。

对于有理离散系统函数 H(z)=(a[n]zn+a[n-1]zn-1+…+a[0]z0)/(b[n]zn+b[n-1]zn-1+…+b[0]z0) 通过直接型方框图表示为:DS

对于有理连续系统函数 H(s)=(a[n]sn+a[n-1]sn-1+…+a[0]s0)/(b[n]sn+b[n-1]sn-1+…+b[0]s0) 通过直接型方框图表示为:CS

可以看到长得比较像,稍加推导也很容易推出来。

图中 z-1 为延时器, s-1 为积分器。对于离散信号要将连续系统函数离散化,方法很多,代码中直接将离散系统延时器的部分改成了前向差分法面积近似积分。

至于 Wav 文件格式的读写,因为未压缩 Wav 文件用 PCM 格式储存数据,说白了就是某一个采样的值,而这个值在量化位数大于等于 16 则是有符号值,一开始处理的时候还踩了坑。

我设计了一个很优越的有理连续系统,碍于你写的连续系统函数离散化方式实在不行,不能体现优越性,怎么办?

可以试试先用 matlab 的 tfbodelsim 函数看看这个系统的效果,如果对离散化方式有要求,可以用 matlab 的 c2d 函数将有理系统离散化,然后再将生成的离散有利系统函数系数输入本程序,使用方式请 help c2d

当然也可以手算,见 cnki: 连续系统离散化方法的比较与解析初探

双线性变换法

用一阶保持积分器积分效果太差了,可以说 bode 图长得完全不是原来那样,因此我又将代码中的积分部分改成了线性插值积分,公式及求解见下:tustin


当你在凝视深渊的时候 深渊也正在凝视着你