剪切FFT矩阵

时间:2009-05-31 23:15:35

标签: python audio signal-processing fft

音频处理对我来说很新鲜。目前正在使用Python Numpy处理wave文件。在计算FFT矩阵之后,我得到了不存在频率的噪声功率值。我对可视化数据和准确性感兴趣不是一个高优先级。有没有一种安全的方法可以计算削波值来删除这些值,还是应该使用每个样本集的所有FFT矩阵来得出平均数?

问候

编辑:

    from numpy import *
    import wave
    import pymedia.audio.sound as sound
    import time, struct
    from pylab import ion, plot, draw, show

    fp = wave.open("500-200f.wav", "rb")
    sample_rate = fp.getframerate()
    total_num_samps = fp.getnframes()
    fft_length = 2048.
    num_fft = (total_num_samps / fft_length ) - 2
    temp = zeros((num_fft,fft_length), float)

    for i in range(num_fft):
        tempb = fp.readframes(fft_length);
        data = struct.unpack("%dH"%(fft_length), tempb)
        temp[i,:] = array(data, short) 
    pts = fft_length/2+1
    data = (abs(fft.rfft(temp, fft_length)) / (pts))[:pts]

    x_axis = arange(pts)*sample_rate*.5/pts
    spec_range = pts
    plot(x_axis, data[0])
    show()

以下是非对数刻度的图,包含使用Goldwave创建的500hz(淡出)+ 200hz正弦波的合成波文件。

4 个答案:

答案 0 :(得分:3)

模拟波形不应该像您的图一样显示FFT,因此有些问题非常错误,可能不是FFT,而是输入波形。你的情节中的主要问题不是涟漪,而是1000 Hz左右的谐波和500 Hz时的次谐波。模拟波形不应显示任何此类(例如,请参见下面的图表)。

首先,您可能只想尝试绘制原始波形,这可能会指出一个明显的问题。另外,将波解包为无符号短路(即“H”)似乎很奇怪,特别是在此之后没有大的零频率分量。

通过对波形应用削波,我能够得到非常接近的FFT,如分谐波和高次谐波(和Trevor)所暗示的那样。您可以在模拟或解包中引入剪辑。无论哪种方式,我都是通过在numpy中创建波形开始绕过它。

这是正确的FFT应该是什么样的(即基本上完美,除了由于窗口引起的峰值变宽)

alt text

这是一个被剪切的波形(与你的FFT非常相似,从分谐波到1000 Hz左右的三个高次谐波的精确模式)

alt text 这是我用来生成这些

的代码
from numpy import *
from pylab import ion, plot, draw, show, xlabel, ylabel, figure

sample_rate = 20000.
times = arange(0, 10., 1./sample_rate)
wfm0 = sin(2*pi*200.*times)
wfm1 = sin(2*pi*500.*times) *(10.-times)/10.
wfm = wfm0+wfm1
#  int test
#wfm *= 2**8
#wfm = wfm.astype(int16)
#wfm = wfm.astype(float)
#  abs test
#wfm = abs(wfm)
#  clip test
#wfm = clip(wfm,  -1.2, 1.2)

fft_length = 5*2048.
total_num_samps = len(times)
num_fft = (total_num_samps / fft_length ) - 2
temp = zeros((num_fft,fft_length), float)

for i in range(num_fft):
    temp[i,:] = wfm[i*fft_length:(i+1)*fft_length] 
pts = fft_length/2+1
data = (abs(fft.rfft(temp, fft_length)) / (pts))[:pts]

x_axis = arange(pts)*sample_rate*.5/pts
spec_range = pts
plot(x_axis, data[2], linewidth=3)
xlabel("freq (Hz)")
ylabel('abs(FFT)')
show()

答案 1 :(得分:2)

FFT,因为它们是窗口化的,sampled导致aliasing并在频域中进行采样。时域中的过滤只是频域中的乘法,因此您可能只想应用一个过滤器,该过滤器只是将每个频率乘以您正在使用的过滤器的函数值。例如,在通带中乘以1,在其他情况下乘以零。意外值可能是由于较高频率向下折叠到您看到的频率的混叠引起的。 original signal needs to be band limited to half your sampling rate或者您将获得aliasing。更值得关注的是使感兴趣区域扭曲的混叠,因为对于这个频率频段,您想要知道频率来自预期频率。

要记住的另一件事是,当您从波形文件中获取一段数据时,您将通过数学方法将其乘以方波。这会导致sinx / x与频率响应进行卷积,以最大限度地减少这种情况,您可以将原始窗口信号与Hanning window相乘。

答案 2 :(得分:1)

对于1D FFT,值得一提的是第一个元素(索引[0])包含DC(零频率)项,元素[1:N/2]包含正频率和元素{{1}包含负频率。由于您没有提供有关FFT输出的代码示例或其他信息,因此我不能排除“不存在频率时的噪声功率值”不仅仅是频谱的负频率的可能性。


编辑Here是纯Python中实现的基数-2 FFT的示例,其中包含一个简单的测试例程,用于查找矩形脉冲的FFT [N/2+1:N-1]。您可以在codepad上运行该示例,并查看该序列的FFT是

[1.,1.,1.,1.,0.,0.,0.,0.]

请注意,代码按照频率上升的顺序打印出傅立叶系数,即从最高负频率到DC,然后再到最高正频率。

答案 3 :(得分:1)

我对你的问题不太了解实际回答任何具体内容。

但是根据我自己编写FFT的经验,可以尝试以下几点:

  • 确保遵守奈奎斯特规则
  • 如果您正在查看FFT的线性输出...您将无法看到自己的信号并认为一切都已损坏。确保您正在查看FFT幅度的dB。 (即“情节(10 * log10(abs(fft(x))))”)
  • 通过输入生成的数据(如纯音)为FFT()函数创建unitTest。然后将相同的生成数据提供给Matlab的FFT()。在两个输出数据系列之间进行绝对值差异,并确保最大绝对值差异类似于10 ^ -6(即唯一的差异是由小浮点错误引起的)
  • 确保您是windowing your data

如果这三件事都有效,那么你的fft很好。您的输入数据可能就是问题所在。

时间点剪辑以特定的规则间隔以较小的幅度显示为频域信号的镜像。