ฉันมีปัญหามากมายกับปัญหาตรงนี้เมื่อสองสามปีก่อน
ฉันโพสต์คำถามนี้:
/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;
}