【问题标题】:Getting values for specific frequencies in a short time fourier transform在短时间傅立叶变换中获取特定频率的值
【发布时间】:2015-07-17 12:27:19
【问题描述】:

我正在尝试使用 C++ 重新创建 Matlab 使用的 spectrogram 函数。该函数使用Short Time Fourier Transform (STFT)。我发现了一些执行 STFT 的 C++ 代码here。该代码似乎适用于所有频率,但我只想要一些。我发现this 发布了一个类似问题的帖子,答案如下:

只需将数据的内积与复指数 感兴趣的频率。如果 g 是您的数据,则只需替换 f 您想要的频率值(例如,1、3、10、...)

没有数学背景,我不知道该怎么做。从Wikipedia page 来看,内积部分似乎很简单,但我完全不知道他的意思(关于 DFT 的公式)

感兴趣频率的复指数

有人可以解释一下我是如何做到这一点的吗?我在 STFT 之后的数据结构是一个充满复数的矩阵。我只是不知道如何提取我想要的频率。

相关函数,其中window 是汉明,而所需频率的向量还不是输入,因为我不知道如何处理它们:

Matrix<complex<double>> ShortTimeFourierTransform::Calculate(const vector<double> &signal,
    const vector<double> &window, int windowSize, int hopSize)
{
    int signalLength = signal.size();
    int nOverlap = hopSize;
    int cols = (signal.size() - nOverlap) / (windowSize - nOverlap);
    Matrix<complex<double>> results(window.size(), cols);

    int chunkPosition = 0;
    int readIndex;
    // Should we stop reading in chunks? 
    bool shouldStop = false;
    int numChunksCompleted = 0;
    int i;
    // Process each chunk of the signal
    while (chunkPosition < signalLength && !shouldStop)
    {
        // Copy the chunk into our buffer
        for (i = 0; i < windowSize; i++)
        {
            readIndex = chunkPosition + i;
            if (readIndex < signalLength)
            {
                // Note the windowing! 
                data[i][0] = signal[readIndex] * window[i];
                data[i][1] = 0.0;
            }
            else
            {
                // we have read beyond the signal, so zero-pad it!
                data[i][0] = 0.0;
                data[i][1] = 0.0;
                shouldStop = true;
            }
        }
        // Perform the FFT on our chunk
        fftw_execute(plan_forward);

        // Copy the first (windowSize/2 + 1) data points into your spectrogram.
        // We do this because the FFT output is mirrored about the nyquist 
        // frequency, so the second half of the data is redundant. This is how
        // Matlab's spectrogram routine works.
        for (i = 0; i < windowSize / 2 + 1; i++)
        {               
            double real = fft_result[i][0];
            double imaginary = fft_result[i][1];
            results(i, numChunksCompleted) = complex<double>(real, imaginary);
        }
        chunkPosition += hopSize;
        numChunksCompleted++;
    } // Excuse the formatting, the while ends here.
    return results;
}

【问题讨论】:

  • Wikipedia description 有什么不清楚的地方,为什么不能直接编码?
  • 如果我理解你的问题,我相信我已经编写了离散时间 STFT。我现在只是试图获取特定频率的值。
  • 您可以完全按照维基百科中的公式编写公式。只需循环频率并分别为每个频率应用公式。
  • 对不起。我不懂经典的数学符号。哪个符号是所需的频率?我必须应用公式的哪一部分才能获得所需的值?
  • X(m,omega) = sum_n x[n]w[n-m]exp(-j*omega*n)omega 表示频率,m 表示移位,x 表示信号,w 表示窗口,j 表示虚数单位。

标签: c++ matlab audio fft


【解决方案1】:

查找 Goertzel algorithmfilter 示例代码,该代码使用内积与复指数的计算等效值来测量信号中特定固定正弦频率的存在或幅度。性能或分辨率取决于滤波器的长度和您的信号。

【讨论】:

    猜你喜欢
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多