【发布时间】: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表示虚数单位。