我试图用python编写一个简单的程序,计算并显示1段的DFT输出。
我的信号是3秒长,我想计算每10毫秒长的段的DFT。采样率为44100。一段是441个样本。
由于我正处于测试阶段,而原始程序要大得多(语音识别),这里是一个孤立的部分,用于测试,不幸的是行为古怪。要么是这个,要么是我对这个问题缺乏了解。
我在某个地方读到DFT输入应该四舍五入为2的幂,所以我将数组排列为512而不是441。这是真的吗?
如果我以44100的频率采样,我最多能达到22050赫兹的频率,而长度512(~441)的采样至少能达到100赫兹?
如果是2。是的,那么我可以让所有频率在100hz到220hz之间的10ms段,但段的长度是512(441)个采样,fft的输出返回256(220)个值的数组,它们不能包含所有21950个频率,是吗?
我的第一个猜测是,fft的输出值应该乘以100,因为10ms是每秒的100。这是很好的推理吗?
以下两个给定频率1000和2000的程序在输出阵列中的位置24和48以及图上的位置2071和位置4156返回图上的两个峰值。因为数字的比率是可以的(2000:1000=48:24),我想我是否应该忽略fft输出的一些起始部分?

import matplotlib.pyplot as plt
import numpy as np

t = np.arange(0, 1, 1/512.0)  # We create 512 long array

# We calculate here two sinusoids together at 1000hz and 2000hz
y = np.sin(2*np.pi*1000*t) + np.sin(2*np.pi*2000*t)
n = len(y)
k = np.arange(n)

# Problematic part is around here, I am not quite sure what
# should be on the horizontal line
T = n/44100.0
frq = k/T
frq = frq[range(n/2)]


Y = fft(y)
Y = Y[range(n/2)]
# Convert from complex numbers to magnitudes
iY = []
for f in Y:
    iY.append(np.sqrt(f.imag * f.imag + f.real * f.real))


plt.plot(frq, iY,  'r')
plt.xlabel('freq (HZ)')
plt.show()

最佳答案

我在某个地方读到DFT输入应该四舍五入为2的幂,所以我将数组排列为512而不是441。这是真的吗?
DFT适用于所有尺寸。然而,DFT的实现,例如FFT,对于可以被分解成小素数的大小,通常更有效。有些库实现有限制,不支持2的幂以外的大小,但numpy的情况并非如此。
如果我以44100的频率采样,我最多能达到22050赫兹的频率,而长度512(~441)的采样至少能达到100赫兹?
如您所正确指出的,均匀尺寸DFT的最高频率为44100/2=22050赫兹。注意,对于奇数大小的DFT,最高频率箱将对应于略小于Nyquist频率的频率。至于最小频率,它总是0Hz。下一个非零频率将是44100.0/N,其中N是采样中的DFT长度(如果使用441个采样的DFT长度和~86Hz(DFT长度为512个采样的DFT长度),则为100Hz)。
如果2)是真的,那么我可以在那10毫秒的段中拥有100赫兹到220赫兹之间的所有频率,但是段的长度仅为512(441)个采样,fft的输出返回256(220)个值的数组,它们不能包含所有21950个频率,不是吗?
首先,在100Hz和220hz之间没有21950个频率,因为频率是连续的,不限于整数频率。也就是说,您正确地认识到DFT的输出将被限制在一组更小的频率上。更具体地说,DFT表示离散频率阶跃下的频谱:0,44100/N2*44100/N。。。
我的第一个猜测是FFT的输出值应该乘以100,因为10ms是每秒的100。这是很好的推理吗?
无需将FFT输出乘以100。但是如果你的意思是100Hz的倍数,DFT长度为441,采样率为44100Hz,那么你的猜测是正确的。
以下两个给定频率1000和2000的程序在输出阵列中的位置24和48以及图上的位置2071和位置4156返回图上的两个峰值。因为数字的比率是可以的(2000:1000=48:24),我想我是否应该忽略fft输出的一些起始部分?
这里的问题更为重要。当你声明数组时

t = np.arange(0, 1, 1/512.0)  # We create 512 long array

实际上,您所代表的是采样率为512Hz而不是44100Hz的信号。因此,您生成的音调严重失真(分别为24赫兹和48赫兹)。这进一步加剧了这样一个事实,那就是你使用一个采样频率为40100Hz的频率轴转换。这就是为什么峰值不会出现在预期的1000Hz和2000Hz频率。
为了表示以44100Hz的频率采样的512个信号样本,您应该使用
t = np.arange(0, 511.0/44100, 1/44100.0)

在这一点上,用于频率轴的公式将是正确的(因为它是基于相同的4100Hz采样率)。然后,您应该能够在预期的1000Hz和2000Hz附近看到峰值(峰值的最接近频率箱为~1033Hz和1981Hz)。

关于python - 如何在python中的段上实现/执行DFT?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34387639/

10-10 22:58