信号时间采样

近期在信号与系统课程中讲完了“信号的采样与恢复”的内容。通常情况下对于信号的采样都是沿着时间轴对信号的幅值进行采样,获得信号的离散时间点上的数据。

如果将信号的波形绘制在直接坐标系中,那么该曲线就是分布在二维空间上的曲线。曲线上的点可以沿着时间轴进行排列,当然也可以按照幅值的大小进行排列。也就是按照取值间隔,将信号通过该间隔的时间进行保存,这就是对信号的时间采样。

▲ 声音的时间波形

沿着时间轴对信号的幅值进行采样,Nyquist-Shannon定理告诉我们如何进行采样和如何进行信号恢复。但是,如何对信号时间进行采样,如何恢复是一个经典的未解决问题。

Logan定理[Logan,Jr.,1977]对一种特殊信号给出了采样与恢复的描述:如果一个信号的频谱具有倍频的性质,即信号频谱分布在一个频率范围内,最高频率是最低频率的两倍。那么这个信号可以通过它的过零点的时间值进行恢复。恢复的信号与原始信号仅仅相差一个比例因子。

信号采样与恢复

1. 幅度采样

下面是一段普通语音信号的复制采样波形。通过简单的DA转换和低通滤波便可以恢复出原始的声音波形。

▲ 幅度采集声音波形

这段语音信号的内容为:

voice2.wav来自TsinghuaJoking00:0000:27

2. 时间采样

如果仅仅保留该信号的过零时间点的信息,它的幅值全部去掉,所形成的波形大体上如下图所示。这很像将原来的语音信号通过一个过零点比较器,输出的信号反映了信号的极性。

▲ 声音信号过零点采样

当然,这个信号中包含有原来信号的部分信息。但它并不是原来语音信号的完美的回复。

尽管如此,播放这个信号,还是可以听到原来语音的信息。虽然有很大的失真和噪声。这说明原来的信号信息还是部分保留在这些过零点中。

经过比较器之后的语音信号为:

clipvoice2.wav来自TsinghuaJoking00:0000:27

如果语音信号满足Logan定理的要求,那么理论上是可以恢复出原来的信号的。但如何来恢复?

如果信号本身是一个周期信号,也就是信号的频谱是离散的频谱。相对回复信号的算法比较简单。Sam Roweis等人在论文“Signal Reconstruction from Zero-Crossings"中给出了通过求解数据矩阵零空间向量的方法,来通过信号的过零时间点来重构信号的方法。

重建算法

1. 基本原理

已知到信号具有倍频窄带频谱,它的频率范围分布在 范围内。

▲ 倍频信号频谱示意图

已知信号的周期,,以及个信号过零点:

重构信号的计算步骤如下:

(1)计算相关参数: 以及 ;

(2)构造矩阵: ;

(3)寻找数据矩阵零空间向量:构造数据矩阵,矩阵大小是。对该矩阵进行奇异值分解,得到。其中是空间上的正交矩阵,是空间上的正交矩阵。是奇异值向量,长度为。

零空间向量是奇异值向量中最小(理论上应该为0,但由于计算误差的存在,它可能是一个很小的数)对应的中的向量,由于SVD算法往往把结果按照绝对值从大到小排列,所以的最后一个向量就对应着数据矩阵的零空间向量。

(4)构造信号函数:将数据空间矩阵中零空间向量前个数值当做,后个数值当做,重建信号公式为:

这种回复信号的过程,实际上就是根据信号的过零点来求解上面的函数中的参数。具体的理论分析在这里就不再展开了。

2. 测试函数

(1)实验信号的数学表达式:

选择一个频率分布在10Hz到20Hz之间的一个信号进行实验,随机指定对应的cos,sin信号的系数,如下:

▲ 信号的数学表达式

这是一个周期为1的倍频信号。

(2)信号的产生Python程序:

使用下面python程序,可以产生该信号的数据。也可以通过该函数完搜索信号的过零点。

def sfunc1(x):    pi2 = 2 * pi    retdata  = cos(pi2*11*x) + sin(pi2*11*x)/2 + \            cos(pi2*12*x)/33 + sin(pi2*12*x)/4 + \            cos(pi2*13*x) + sin(pi2*13*x)/8 + \            cos(pi2*14*x) + sin(pi2*14*x)/7 + \            cos(pi2*15*x)/22 + sin(pi2*15*x)/3 +\            cos(pi2*16*x) + sin(pi2*16*x)/12 +\            cos(pi2*17*x) + sin(pi2*17*x)/40 +\            cos(pi2*18*x) + sin(pi2*18*x)/2 +\            cos(pi2*19*x)/3 + sin(pi2*19*x)/2    return retdata

(3)实验信号的波形:

下面绘制出0~2秒两个周期内的波形。

▲ 测试函数sfunc1信号波形

绘制该信号的过零点饱和信号,它仅仅保留了该信号的过零点的时间和相位信息。计算公式为:

▲ 该信号的幅值饱和信号

(4)信号的过零点:

通过数值计算,来获得信号的过零点。下面重新绘制出信号一个周期内的波形,没有添加任何噪声。

▲ 一个周期(0~1)之间的信号波形

通过对区间(0,1)采集10^6^个数值,然后通过寻找过零点,获得二十八个信号的过零点的值。

搜寻函数值过零点的python程序如下crosszero(t,val)。其中是函数的自变量,是函数值的采样。函数返回是对应函数过零点时的的数值。

def crosszero(t, val):    valsign = sign(val)    valsignchange = [int(x!=y) for x,y in zip(valsign[0:-1],valsign[1:])]    tvalue = [(x,y) for x,y in zip(t[0:-1], valsignchange)]    zerot = filter(lambda t: t[1]!= 0, tvalue)    return [zt[0] for zt in zerot]

通过scipy.optimize.root来寻找信号的根,用于确定信号的过零点。利用上面搜索的结果作为初始值。

sol = scipy.optimize.root(tssub.sfunc1, czt, method='lm')

tssub.sfunc1:定义的信号函数;

czt:是前面通过数值过零点搜索获得的28个根的数值;

如下是sol['x']中的数值,包含了最终优化后的数值,对比前面通过搜索获得数值,可以看到基本上在10^-6^的内存在一定的误差。

将通过数值计算所得到的28个函数的根绘制在信号波形上,看到他们的分布。

▲ 寻找到的信号过零点

3. 重建结果

根据前面所叙述的方法,使用28个过零点信息重构出的信号波形如下图所示。重构的信号与原始的信号之间波形基本一致,只是相差了一个比例因子。

▲ 重建的波形结果

前面实验中的程序和数据可以在CSDN博文中看到。

http://zhuoqing.blog.csdn/net

你可能感兴趣的:(信号时间采样)