কয়েক বছর আগে এই সঠিক সমস্যাটি নিয়ে আমার অনেক সমস্যা হয়েছিল।
আমি এই প্রশ্ন পোস্ট:
/programming/4633203/extracting-precise-frequencies-from-fft-bins-using-phase-change-between-frames
আমি স্ক্র্যাচ থেকে গণনাগুলি শেষ করেছি, এবং আমার নিজের প্রশ্নের উত্তর পোস্ট করেছি।
আমি অবাক হয়েছি যে আমি ইন্টারনেটে তেমন কোনও প্রদর্শন খুঁজে পাইনি।
আমি উত্তর এখানে আবার পোস্ট করব; নোট করুন যে কোডটি এমন একটি দৃশ্যের জন্য তৈরি করা হয়েছে যাতে আমি আমার এফএফটি উইন্ডোটি 4x দিয়ে ওভারল্যাপ করছি।
π
এই ধাঁধাটি আনলক করতে দুটি কী লাগবে।
গ্রাফ ৩.৩:
গ্রাফ ৩.৪:
কোড:
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;
}