在 Matlab 中以精确的奈奎斯特速率采样

Sampling at exactly Nyquist rate in Matlab

今天我在 matlab 中偶然发现了一个奇怪的结果。假设我有一个正弦波

f = 1;
Fs = 2*f;
t = linspace(0,1,Fs);    
x = sin(2*pi*f*t);
plot(x)

结果如图

当我设置时,

f = 100

结果如下图,

具体原因是什么?这是奈奎斯特采样定理,因此它应该正确地生成正弦。当然,当我使用 Fs >> f 时,我会得到更好的结果和非常好的正弦形状。我对自己的解释是 Matlab 在处理浮点数时遇到了困难,但我不太确定这是否属实。有人有什么建议吗?

在第一种情况下你只生成了 2 个样本(linspace 的第三个输入是样本数),所以很难看到任何东西。

在第二种情况下,您从时间 0 到 1(包括这两个值)生成了 200 个样本。所以采样周期为1/199,采样频率为199,略低于奈奎斯特速率。所以 存在混叠 :您会看到频率为 100 的原始信号及其在频率 99 处的混叠。

换句话说:下面的代码重现了你的第二个数字:

t = linspace(0,1,200);
x = .5*sin(2*pi*99*t) -.5*sin(2*pi*100*t);
plot(x)

上面的.5-.5源于一个正弦波可以分解为正负频率的两个频谱delta之和,并且这两个delta的系数相反迹象。

这两个正弦波的总和相当于调幅,即由频率为 1/2 的正弦波调制的频率为 99.5 的正弦波。由于时间跨度从 0 到 1,调制器信号(其频率为 1/2)仅完成半个周期。这就是你在第二个图中看到的。


为避免混叠,您需要将采样率提高到高于奈奎斯特率。然后,要从样本中恢复原始信号,您可以使用截止频率为 Fs/2 的理想低通滤波器。但是,在您的情况下,由于您采样 低于 奈奎斯特速率,因此您 不会 恢复频率为 100 的信号,而是它的别名频率 99.

如果您在奈奎斯特速率 以上 上采样,例如 Fs = 201,则可以从样本中理想地恢复原始信号 但这需要一个近乎理想的低通滤波器,在通带和阻带之间具有 非常尖锐的 过渡。即,混叠现在的频率为 101,应该被拒绝,而所需信号的频率为 100,应该通过。

放宽滤波器要求,您需要可以在奈奎斯特速率以上进行采样。这样,别名与信号的距离更远,并且过滤器可以更轻松地将信号与别名分开。


这并不意味着图表 看起来 像您的原始信号(参见 );这仅意味着经过理想的低通滤波后它会。

您的问题与奈奎斯特定理和混叠无关。这是一个简单的图形表示问题。您可以更改您的代码,使正弦频率低于奈奎斯特极限,但图形会像以前一样奇怪:

t = linspace(0,1,Fs+2);
plot(sin(2*pi*f*t));

结果:

为了说明问题我修改了你的代码:

Fs=100;
f=12;  %f << Fs
t=0:1/Fs:0.5; % step =1/Fs
t1=0:1/(10*Fs):0.5;   % step=1/(10*Fs) for precise graphic representation
subplot (2, 1, 1);
plot(t,sin(2*pi*f*t),"-b",t,sin(2*pi*f*t),"*r");
subplot (2, 1, 2);
plot(t1,sin(2*pi*f*t1),"g",t,sin(2*pi*f*t),"r*");

查看结果:

  • 红星 - sin(2*pi*f) 的值,采样率为 Fs
  • 蓝线 - 连接红星的线。它是函数 plot() 的常用数据表示 - 数据点之间的线插值
  • 绿色曲线 - sin(2*pi*f)

你的眼睛和大脑可以很容易地理解这些图形代表正弦

将频率改为更高:

f=48;   % 2*f < Fs !!!

查看蓝线和红星。现在您的眼睛和大脑不明白这些图形表示相同的正弦。但是你的 "red stars" 实际上是正弦的有效值。请参见底部图表。

最后还有频率为f=50(2*f = Fs)的正弦同图:

P.S.

Nyquist-Shannon 采样定理针对您的情况说明如果:

  1. f < 2*Fs
  2. 您有 无限 个样本(我们的地块上有红色星星)

然后您可以随时重现函数值(我们图中的绿色曲线)。您必须使用 sinc 插值 来完成。

从 Matlab 帮助中复制:

林空间

生成线性间隔的向量 语法

y = linspace(a,b)
y = linspace(a,b,n)

描述

linspace 函数生成线性间隔的向量。它类似于冒号运算符“:”,但可以直接控制点数。

y = linspace(a,b) 生成一个包含 100 个点的行向量 y,这些点在 a 和 b 之间线性间隔(包括 a 和 b)。

y = linspace(a,b,n) 生成一个包含 n 个点的行向量 y,这些点在 a 和 b 之间线性间隔,包括 a 和 b。对于 n < 2,linspace returns b。 例子

创建一个由 100 个从 1 到 500 的线性间隔数字组成的向量:

A = linspace(1,500);

创建一个由 1 到 36 之间的 12 个线性间隔数字组成的向量:

A = linspace(1,36,12);

linspace对于奈奎斯特区间来说并不明显,所以你可以使用常见的形式:

t = 0:Ts:1;

t = 0:1/Fs:1;

并更改 Fs 值。

第一个图是由于'0'的近似:sin(0)和sin(2*pi)。我们可以注意到范围在 10^(-16) 级别。

我编写了函数 reconstruct_FFT,如果样本的输入序列是周期性的,即使对于较短的观察间隔,它也可以恢复临界采样数据。它在频域中执行低通滤波。