导入
从连续时间到离散时间
学习如何从连续时间信号中获取数字样本。
现实生活中的大多数信号,例如心跳、脑电波、声音、音乐以及无线通信波形等,都是连续时间信号。为了使用数字信号处理(DSP)技术对这类信号进行处理,必须将其转换为一组数值序列。这一过程可以通过周期性采样来实现,借助一种称为**模数转换器(ADC)**的设备完成。
...
An ADC transforms an analog signal into a digital signal
时域
考虑一个随时间变化的模拟信号 ,如下面图示。图中还展示了该信号的频谱。
...
A signal and its spectrum
在数字信号处理中,需要将该信号转换为一系列样本,即转换为离散时间版本 。这可以通过以每 秒为间隔对 进行采样来实现。该过程在数学上表示为:
记作 的时间间隔称为采样间隔,其倒数即为采样率。
采样率是我们最常听到的 DSP 参数之一,例如音频应用中的 44.1 kHz 和 48 kHz。这意味着每秒记录 44100 或 48000 个语音信号的样本!
选择采样率 ,或等价地选择采样间隔 ,是设计 DSP 系统的关键环节。运行以下代码并观察采样后的信号:
1import numpy as np 2import matplotlib.pyplot as pl 3 4figWidth = 5 5figHeight = 7.5 6 7f = 1 8T = 1/f 9A = 1 10phi = 0 11 12fs1 = 5 # 1st sample rate 13Ts1 = 1/fs1 # 1st sample time 14fs2 = 10 # 2nd sample rate 15Ts2 = 1/fs2 # 2nd sample time 16fs3 = 20 # 3rd sample rate 17Ts3 = 1/fs3 # 3rd sample time 18 19# 1st sample rate 20 21t1 = np.arange(0, T, Ts1) 22 23s1 = A*np.cos(2*np.pi*f*t1 + phi) 24 25 26fig, axs = pl.subplots(3, figsize=(figWidth, figHeight)) 27 28axs[0].vlines(t1, ymin=s1, ymax=0, color='g', linewidth=1) 29axs[0].plot(t1, s1, linewidth=1, color='b') 30axs[0].plot(t1, s1, 'o', color='r', markersize=7) 31 32# Axes lines 33axs[0].axhline(y=0, color='k', linewidth=2) 34axs[0].axvline(x=0, color='k', linewidth=2) 35 36 37axs[0].set_xlim(-Ts3, T+Ts3) 38axs[0].set_xticks(np.linspace(0, T, 5)) 39axs[0].set_ylim(-1.1, 1.1) 40axs[0].set_yticks(np.linspace(-1, 1, 5)) 41 42# Hide the right and top spines 43axs[0].spines['right'].set_visible(False) 44axs[0].spines['top'].set_visible(False) 45 46 47axs[0].set_title("$f_S=5$") 48axs[0].set_xlabel("n") 49axs[0].set_ylabel("$x_1[n]$") 50axs[0].grid() 51 52 53# 2nd sample rate 54 55t2 = np.arange(0, T, Ts2) 56 57s2 = A*np.cos(2*np.pi*f*t2 + phi) 58 59axs[1].vlines(t2, ymin=s2, ymax=0, color='g', linewidth=1) 60axs[1].plot(t2, s2, linewidth=1, color='b') 61axs[1].plot(t2, s2, 'o', color='r', markersize=7) 62 63# Axes lines 64axs[1].axhline(y=0, color='k', linewidth=2) 65axs[1].axvline(x=0, color='k', linewidth=2) 66 67 68axs[1].set_xlim(-Ts3, T+Ts3) 69axs[1].set_xticks(np.linspace(0, T, 5)) 70axs[1].set_ylim(-1.1, 1.1) 71axs[1].set_yticks(np.linspace(-1, 1, 5)) 72 73# Hide the right and top spines 74axs[1].spines['right'].set_visible(False) 75axs[1].spines['top'].set_visible(False) 76 77 78axs[1].set_title("$f_S=10$") 79axs[1].set_xlabel("n") 80axs[1].set_ylabel("$x_2[n]$") 81axs[1].grid() 82 83t1 = np.arange(0, T, Ts1) 84 85s1 = A*np.cos(2*np.pi*f*t1 + phi) 86 87 88# 3rd sample rate 89 90t3 = np.arange(0, T, Ts3) 91 92s3 = A*np.cos(2*np.pi*f*t3 + phi) 93 94axs[2].vlines(t3, ymin=s3, ymax=0, color='g', linewidth=1) 95axs[2].plot(t3, s3, linewidth=1, color='b') 96axs[2].plot(t3, s3, 'o', color='r', markersize=7) 97 98# Axes lines 99axs[2].axhline(y=0, color='k', linewidth=2) 100axs[2].axvline(x=0, color='k', linewidth=2) 101 102 103axs[2].set_xlim(-Ts3, T+Ts3) 104axs[2].set_xticks(np.linspace(0, T, 5)) 105axs[2].set_ylim(-1.1, 1.1) 106axs[2].set_yticks(np.linspace(-1, 1, 5)) 107 108# Hide the right and top spines 109axs[2].spines['right'].set_visible(False) 110axs[2].spines['top'].set_visible(False) 111 112 113axs[2].set_title("$f_S=20$") 114axs[2].set_xlabel("n") 115axs[2].set_ylabel("$x_3[n]$") 116axs[2].grid() 117 118fig.tight_layout() 119 120# saving figure 121pl.savefig('output/cosine-sampled.png')
有趣的是,上述信号绘制了三种不同的采样率:
- 样本/秒
- 样本/秒
- 样本/秒
采样率 样本/秒似乎效果最好,因为它呈现出最平滑的波形。但这真的是最优选择吗?
事实上,这并非数字信号处理科学家所采用的方式。系统的采样率并不是这样随意选择的。
频域
让我们思考一下采样过程在频域中会产生什么影响。以正弦信号为例:
其以 样本/秒的速率进行采样后的离散版本为:
令人惊讶的是,连续频率 被采样率 缩放,形成了一个离散频率 。这个离散频率才是我们在实际 DSP 应用中真正使用的频率量,而非原始的连续频率。