मुझे कुछ साल पहले इस सटीक समस्या से बहुत कठिनाई थी।
मैंने यह प्रश्न पोस्ट किया है:
/programming/4633203/extracting-precise-frequencies-from-fft-bins-using-phase-change-between-frames
मैंने स्क्रैच से गणना करना समाप्त कर दिया, और अपने प्रश्न का उत्तर पोस्ट किया।
मुझे आश्चर्य है कि मुझे इंटरनेट पर किसी भी तरह का एक्सपोजर नहीं मिला।
मैं यहां फिर से जवाब पोस्ट करूंगा; ध्यान दें कि कोड एक परिदृश्य के लिए डिज़ाइन किया गया है जिसमें मैं अपनी FFT विंडो को 4x से ओवरलैप कर रहा हूं।
π
यह पहेली इसे अनलॉक करने के लिए दो कुंजी लेती है।
ग्राफ 3.3:
ग्राफ 3.4:
कोड:
for (int k = 0; k <= fftFrameSize/2; k++)
{
// compute magnitude and phase
bins[k].mag = 2.*sqrt(fftBins[k].real*fftBins[k].real + fftBins[k].imag*fftBins[k].imag);
bins[k].phase = atan2(fftBins[k].imag, fftBins[k].real);
// Compute phase difference Δϕ fo bin[k]
double deltaPhase;
{
double measuredPhaseDiff = bins[k].phase - gLastPhase[k];
gLastPhase[k] = bins[k].phase;
// Subtract expected phase difference <-- FIRST KEY
// Think of a single wave in a 1024 float frame, with osamp = 4
// if the first sample catches it at phase = 0, the next will
// catch it at pi/2 ie 1/4 * 2pi
double binPhaseExpectedDiscrepancy = M_TWOPI * (double)k / (double)osamp;
deltaPhase = measuredPhaseDiff - binPhaseExpectedDiscrepancy;
// Wrap delta phase into [-Pi, Pi) interval
deltaPhase -= M_TWOPI * floor(deltaPhase / M_TWOPI + .5);
}
// say sampleRate = 40K samps/sec, fftFrameSize = 1024 samps in FFT giving bin[0] thru bin[512]
// then bin[1] holds one whole wave in the frame, ie 44 waves in 1s ie 44Hz ie sampleRate / fftFrameSize
double bin1Freq = (double)sampleRate / (double)fftFrameSize;
bins[k].idealFreq = (double)k * bin1Freq;
// Consider Δϕ for bin[k] between hops.
// write as 2π / m.
// so after m hops, Δϕ = 2π, ie 1 extra cycle has occurred <-- SECOND KEY
double m = M_TWOPI / deltaPhase;
// so, m hops should have bin[k].idealFreq * t_mHops cycles. plus this extra 1.
//
// bin[k].idealFreq * t_mHops + 1 cycles in t_mHops seconds
// => bins[k].actualFreq = bin[k].idealFreq + 1 / t_mHops
double tFrame = fftFrameSize / sampleRate;
double tHop = tFrame / osamp;
double t_mHops = m * tHop;
bins[k].freq = bins[k].idealFreq + 1. / t_mHops;
}