我正在尝试在STM32F411RE Nucleo开发板上实现具有相关复数幅度功能的快速傅立叶变换。我的目标是将具有多个正弦波元素的组合信号分离为具有正确幅度的单独频率分量。
我的问题是我无法正确地将复数幅值函数的频点结果与频率对齐。我也开始质疑这些结果的有效性。
我尝试将人们发布的许多不同实现用于幅度固定的FFT算法,最著名的是StackoverFlow by SleuthEye和Blog by LB9MG上列出的示例。
AFAIK我有一个类似的方法,但是不知何故,他们的方法产生了预期的结果,而我的却没有。下面是我更改的代码,以通过SleuthEye创建的实现工作。
int main(void)
{
fftLen = 32; // can be 32, 64, 128, 256, 512, 1024, 2048, 4096
half_fftLen = fftLen/2;
volatile float32_t sampleFreq = 50 * fftLen; // Fs = binsize * fft length, desired binsize = 50 hz
arm_rfft_fast_instance_f32 inst;
arm_status status;
status = arm_rfft_fast_init_f32(&inst, fftLen);
float32_t signalCombined[fftLen] = {0};
float32_t fftCombined[fftLen] = {0};
float32_t fftMagnitude[fftLen] = {0};
volatile float32_t fftFreq[fftLen] = {0};
float32_t maxAmp;
uint32_t maxAmpInd;
while (1)
{
for (int i = 0; i< fftLen; i++)
{
signalCombined[i] = 40 * arm_sin_f32(450 * i); // 450 frequency at 40 amplitude
}
arm_rfft_fast_f32(&inst, signalCombined, fftCombined, 0); // perhaps switch to complex transform to allow for negative frequencies?
arm_cmplx_mag_f32(fftCombined, fftMagnitude, half_fftLen);
fftMagnitude[0] = fftCombined[0];
fftMagnitude[half_fftLen] = fftCombined[1];
arm_max_f32(fftMagnitude, half_fftLen, &maxAmp, &maxAmpInd); // We need the 3 max values
for (int k = 0; k < fftLen ; k++)
{
fftFreq[k] = ((k*sampleFreq)/fftLen);
}
}
下面显示的是我从上面列出的代码中得到的结果:虽然我从算法中得到了一个幅度(在正确的索引12处),但它不对应于输入数组的频率或幅度signalCombined[]
。
有人知道为什么会这样吗?像我的许多错误一样,这可能是一件微不足道且愚蠢的事情,但我无法弄清为什么会这样。
答案 0 :(得分:2)
您的音调产生没有考虑到1600Hz的采样频率,因此您可以有效地产生450*1600/(2*PI) ~ 114591Hz
频率的音调,该频率别名为〜608Hz。当使用FFT大小为32时,该608Hz频率大致对应于12附近的频率索引。
以1600Hz采样频率产生450Hz音调应如下:
for (int i = 0; i< fftLen; i++)
{
signalCombined[i] = 40 * arm_sin_f32(2 * PI * 450 * i / sampleFreq);
}
只要与振幅匹配,请注意在时域和频域之间存在大约0.5*fftLen
的比例因子(请参阅this other post of mine)。