我使用此代码(基于Apple的audioRouch示例):
void FFTHelper::ComputeFFT(Float32* inAudioData, Float32* outFFTData)
{
if (inAudioData == NULL || outFFTData == NULL) return;
// Generate a split complex vector from the real data
vDSP_ctoz((COMPLEX *)inAudioData, 2, &mDspSplitComplex, 1, mFFTLength);
// Take the fft and scale appropriately
vDSP_fft_zrip(mSpectrumAnalysis, &mDspSplitComplex, 1, mLog2N, kFFTDirection_Forward);
vDSP_vsmul(mDspSplitComplex.realp, 1, &mFFTNormFactor, mDspSplitComplex.realp, 1, mFFTLength);
vDSP_vsmul(mDspSplitComplex.imagp, 1, &mFFTNormFactor, mDspSplitComplex.imagp, 1, mFFTLength);
// Zero out the nyquist value
mDspSplitComplex.imagp[0] = 0.0;
// Complex vector magnitudes squared; single precision.
// Calculates the squared magnitudes of complex vector A.
vDSP_zvmags(&mDspSplitComplex, 1, outFFTData, 1, mFFTLength);
}
计算最简单的FFT - 1Hz正弦波(向上移动1个单位):
Float32 waveFreq = 1.0;
int samplesCount = 1024;
Float32 samplesPerSecond = 1000; //sample rate
Float32 dt = 1 / samplesPerSecond;
Float32 sd = M_PI * 2.0 * waveFreq;
FFTHelper *mFFTHelper = new FFTHelper(samplesCount);
Float32 NyquistMaxFreq = samplesPerSecond/2.0;
Float32 fftDataSize = samplesCount/2.0;
Float32 *sinusoidOriginal = (Float32 *)malloc(sizeof(Float32) * samplesCount);
Float32 *outFFTData = (Float32 *)malloc(sizeof(Float32) * fftDataSize);
// 2. Generate sin samples:
for (int i = 0; i < samplesCount; i++) {
Float32 x = dt * i;
sinusoidOriginal[i] = sin(sd * x) + 1;
[originalPlot addVector2D:GLVector2DMake(x, sinusoidOriginal[i])];
}
mFFTHelper->ComputeFFT(sinusoidOriginal, outFFTData);
for (int i = 0; i < fftDataSize; i++) {
Float32 hz = ((Float32)i / (Float32)fftDataSize) * NyquistMaxFreq;
GLfloat mag = outFFTData[i];
[fftPlot addVector2D:GLVector2DMake(hz, 0)];
[fftPlot addVector2D:GLVector2DMake(hz, mag)];
}
我得到的结果是:
黑线是FTT的绘图仪结果,水平放置在它们的频率上。 DC值(左起第1条黑线)看起来没问题,正确表示y = sin(x)+ 1垂直偏移。
但是为什么第二条黑线代表了正弦方程中唯一存在的频率没有幅度= 1并且不完全保持在1Hz?
有人能指点我使用vDSP函数将FFT结果从输入信号转换为幅度单位吗?
答案 0 :(得分:2)
简答:
您似乎正在使用我在这个地方的答案中的代码:https://stackoverflow.com/a/19966776/468812 它很棒,但是:
您无法避免信号中的这些额外频率。
您生成的信号(正弦波)是无限信号。 如果你&#34;裁剪它&#34;和&#34;只使用一段信号&#34;它介绍了&#34;削波噪声&#34;在两端。
但是你可以通过在FFT之前采用更大的输入块和using windowing来最小化噪声。 Accelerate Framework提供了一些简单的窗口函数。 (例如Hann Function,vDSP_hann_window) 另外 - 使用更大的输入块。输入越大,频率检测越精确。
请参阅this article,google:光谱泄漏,窗口功能。