数字信号处理/离散运算
在离散数据集上可以执行许多不同的操作。
假设我们有两个数据集,A[n] 和 B[n]。我们将定义这两个集合具有以下值
A[n] = [W X& Y Z] B[n] = [I J& K L]
离散数据集上的算术运算以逐项方式执行。以下是一些示例
A[n] + B[n] = [(W+I) (X+J)& (Y+K) (Z+L)]
如果零位置没有对齐(就像我们示例中方便地对齐的那样),我们需要在加法之前手动对齐零位置。
A[n] - B[n] = [(W-I) (X-J)& (Y-K) (Z-L)]
与加法相同,只是我们减去。
在这种情况下,我们使用“星号”(*) 来表示乘法。实际上,我们应该使用“" 符号来表示乘法。在后面的示例中,我们将使用星号进行其他操作。
A[n] * B[n] = [(W*I) (X*J)& (Y*K) (Z*L)]
A[n] / B[n] = [(W/I) (X/J)& (Y/K) (Z/L)]
尽管我们使用方括号来表示离散数据集,但它们不应该与矩阵混淆。这些不是矩阵,我们不会对这些集合执行矩阵运算。
如果我们对离散数据集进行时间移位,我们实际上是在移动集合的零时间参考点。零点表示“现在”,创建我们对数据的视图的起点,并且该点的定位通常由我们参与的处理的需要决定。
假设我们具有数据集 F[n],其值如下
F[n] = [1 2 3& 4 5 ]
那么我们可以将此集合向后移位 1 个数据点,如下所示
F[n-1] = [1 2& 3 4 5]
我们可以以类似的方式将数据向前移位 1 个数据点
F[n+1] = [1 2 3 4& 5]
离散数据值是时间定向的。零点右侧的值称为“未来值”,左侧的值称为“过去值”。当数据集填充在零参考点的两侧时,“未来”和“过去”是相对于零点“现在”的合成术语,并不指当前的物理时间。在这种情况下,数据值已经收集完毕,因此只能来自我们的过去。
重要的是要了解,正在接收数据的可实现的数字系统无法对未来值执行操作。要求未来值才能进行计算是没有意义的,因为这些系统通常从传感器实时获取输入,而未来值根本不存在。
假设我们有相同的数据集 F[n]
F[n] = [1 2 3& 4 5]
我们可以将数据集反转,如下所示
F[-n] = [5 4 3& 2 1]
我们保持零点的位置不变,并将所有数据项翻转过来。从本质上讲,我们正在对数据集进行镜像,而零点是镜像。
在离散时间域中,卷积操作比在连续时间域中容易得多。假设我们有两个数据集,A[n] 和 B[n]
A[n] = [1& 0 1 2] B[n] = [2& 2 2 1]
在本节中,我们将使用星号 (*) 来表示卷积;它在这里不表示“乘法”。我们的卷积函数显示如下
Y[n] = A[n] * B[n]
它指定我们将卷积值存储在名为 Y[n] 的集合中。
卷积是通过遵循一系列涉及两组数据点的步骤来执行的。首先,我们将其中一个数据集进行时间反转。哪个数据集无关紧要,因此我们可以选择最简单的选项
A[n] = [1& 0 1 2] B[-n] = [1 2 2 2&]
接下来,我们将数据垂直对齐,以使只有一个数据项重叠
A[n] -> [1& 0 1 2] B[-n] -> [1 2 2 2&]
现在,我们将对两个集合进行零填充,使它们长度相等,根据需要在空位置中填入零
A[n] -> [0 0 0 1& 0 1 2] B[-n] -> [1 2 2 2& 0 0 0]
现在,我们将对每列的内容进行乘法,然后将它们加在一起
A[n] -> [0 0 0 1& 0 1 2]
B[-n] -> [1 2 2 2& 0 0 0]
Y[m] =
这将为我们提供第一个数据点:Y[m] = [2]。
接下来,我们需要将 B[-n] 在时间上向前移位一个点,并执行相同的过程:将各列相乘,然后加起来
A[n] -> [0 0 0 1& 0 1 2]
B[-n-1] -> [1 2 2 2& 0 0 0]
Y[m+1] =
重复“时间移位、乘法和加法”步骤,直到不再有数据点重叠。
A[n] -> [0 0 0 1& 0 1 2]
B[-n-2] -> [1 2 2 2& 0 0 0]
Y[m+2] =
A[n] -> [0 0 0 1& 0 1 2]
B[-n-3] -> [1 2 2 2& 0 0 0]
Y[m+3] =
A[n] -> [0 0 0 1& 0 1 2]
B[-n-4] -> [1 2 2 2& 0 0 0]
Y[m+4] =
A[n] -> [0 0 0 1& 0 1 2]
B[-n] -> [1 2 2 2& 0 0 0]
Y[m+5] =
A[n] -> [0 0 0 1& 0 1 2]
B[-n+6] -> [1 2 2 2& 0 0 0]
Y[m+6] =
现在,我们拥有了完整的数据集 Y[m]
Y[m] = [2 2 4 7 6 5 2]
我们拥有了值,但是我们将零点放在哪里?事实证明,结果的零点出现在两个操作数的零点在我们移位计算中重叠的位置。结果集变为
Y[n] = [2& 2 4 7 6 5 2]
重要的是要注意,结果集的长度等于未填充操作数长度的总和减 1。或者,如果您愿意,结果集的长度与任何一个零填充集相同(因为它们长度相等)。
所有这些离散运算都可以在 Matlab 中使用特殊运算符执行。
- 除法和乘法
- Matlab 基于矩阵,因此正常的乘法和除法运算将是矩阵运算,这不是我们在 DSP 中想要做的。要按项进行乘法,我们需要在运算符前面加上一个句点。例如
Y = X .* H %X times H Y = X ./ H %X divided by H
如果我们忘记了句点,Matlab 将尝试执行矩阵运算,并提醒您矩阵的维度与运算符不兼容。
- 卷积
- 可以使用 Matlab 中的 conv 命令执行卷积运算。例如,如果我们要计算 X[n] 和 H[n] 的卷积,我们将使用以下 Matlab 代码
Y = conv(X, H);
或
Y = conv(H, X);
在处理离散集时,您可能想知道我们究竟如何在离散时间域中执行微积分。实际上,我们应该质疑我们所知的微积分是否可能!事实证明,在离散时间域中,我们可以使用多种技术来逼近微分的微积分运算和积分。我们将这些技术称为 差分微积分。
微分到底是什么?在连续时间域中,函数的导数是函数在任何给定时间点的斜率。因此,要找到离散时间信号的导数,我们需要找到离散数据集的斜率。
离散时间域中的数据点可以被视为几何点,并且我们知道任何两点都定义一条唯一的直线。然后,我们可以使用代数方程来求解直线的斜率 m
现在,在离散时间域中,f(t) 被采样并替换为 F[n]。我们还知道,在离散时间中,任何两个点之间的时间差恰好为 1 个时间单位!考虑到这一点,我们可以将这些值代入上面的公式
或者简化为
然后我们可以将整个公式向左移动一个点,这样我们的公式就不需要任何未来值了
导数可以通过从自身中减去时间移动(延迟)版本的函数来找到。
差分演算方程
[edit | edit source]差分演算方程是算术方程,有几个关键组成部分。让我们举个例子
我们可以看到,在这个公式中,X[n-1] 的系数为 2,X[n-2] 的系数为 5。在差分演算中,系数被称为“抽头权重”。我们将在后面的关于数字滤波器的章节中了解为什么它们被称为抽头权重。