简单卷积与numpy的意外结果

时间:2014-02-07 05:58:06

标签: python numpy scipy signal-processing

我有一段时间没有做过DSP,但是我没想到我对基础知识的掌握到目前为止。 我有一个脚本,我用一个复杂的指数卷积一个音调。结果我期望是一个转变的基调。我的结果非常出乎意料 - 我得到了3个音调,而且没有一个是我期望的频率。有人可以解释为什么我会得到这些结果吗?

这是脚本。

import sys
import numpy
import math
import scipy
from pylab import *

def gen_tone(f, fs, length):
    t = linspace(0, length, length * fs)
    return cos(2.0 * pi * f * t)

def gen_exp(f, fs, length):
    t = linspace(0, length, length * fs)
    return numpy.exp(1.0j * 2 * pi * f * t)

def plot_fft(f, fs):
    FFT = abs(scipy.fft(f, 1024)) / f.size
    figure()
    plot(FFT)

f100 = gen_tone(8000, 44100, 1)
f200j = gen_exp(1000, 44100, 1)

res = scipy.signal.fftconvolve(f100, f200j, 'full')

plot_fft(f100, 44100)
plot_fft(f200j, 44100)
plot_fft(res, 44100)

show()

2 个答案:

答案 0 :(得分:1)

您正在使用频移属性。 (请参阅,例如http://ocw.usu.edu/Electrical_and_Computer_Engineering/Signals_and_Systems/5_6node6.html;向下滚动一下标记为频移属性的部分。)也就是说,如果f(t)的傅里叶变换为F(w) ,那么f(t)*exp(j*w0*t)的傅立叶变换是F(w - w0)。表达式f(t)*exp(j*w0*t)f(t)exp(j*w0*t)不是卷积的逐点乘法。

要查看您期望的结果,请将其替换为:

res = scipy.signal.fftconvolve(f100, f200j, 'full')

res = f100 * f200j

如果修改绘图函数,结果会更容易看到:

def plot_fft(f, fs):
    FFT = abs(fft(f, 1024)) / f.size
    freq = fftfreq(1024, 1.0/fs)
    ndx = freq.argsort()
    figure()
    plot(freq[ndx], FFT[ndx])
    grid(True)

并添加

from scipy.fftpack import fft, fftfreq

位于脚本的顶部。

您会看到f100的FFT图中-8000和8000处的峰值在res的FFT图中移位到-7000和9000。

答案 1 :(得分:0)

你想要的是频域中的乘法(移位音),所以你必须这样做:

res = f100 * f200j

而不是

res = scipy.signal.fftconvolve(f100, f200j, 'full')

下面是input(黑色)和res(蓝色)信号的频谱图像(不是FFT)。移位信号显示9kHz的dirac(8000移位1000)。 enter image description here

以下是我的plotSpectrum函数

def plotSpectrum(y,Fs):
    """
    Plots a Single-Sided Amplitude Spectrum of y(t)
    """
    n = len(y) # length of the signal
    k = arange(n)
    T = n/Fs
    frq = k/T # two sides frequency range
    frq = frq[arange(int(n/2))] # one side frequency range

    Y = fft(y)/n # fft computing and normalization
    Y = Y[arange(int(n/2))]

    plot(frq,abs(Y),'r') # plotting the spectrum
    xlabel('Freq (Hz)')
    ylabel('|Y(freq)|')