अगर यह दो बिन केंद्रों के बीच स्थित है, तो सिग्नल के शिखर मूल्य को प्राप्त करें


12

कृपया निम्नलिखित मान लें:

  • एफएफटी और कुछ आवृत्ति अनुमान विधियों का उपयोग करके सिग्नल के मूलभूत की आवृत्ति का अनुमान लगाया गया है और दो बिन केंद्रों के बीच स्थित है
  • नमूने की आवृत्ति निश्चित है
  • कम्प्यूटेशनल प्रयास एक मुद्दा नहीं है

आवृत्ति को जानने के बाद, संकेतों के संगत शिखर मूल्य का अनुमान लगाने का सबसे सटीक तरीका क्या है?

एक तरीका एफएफटी रिज़ॉल्यूशन को बढ़ाने के लिए समय संकेत को शून्य-पैड करने के लिए हो सकता है जैसे कि बिन केंद्र अनुमानित आवृत्ति के करीब होगा। इस परिदृश्य में, एक बिंदु पर मुझे यकीन नहीं है कि क्या मैं शून्य-पैड कर सकता हूं जितना मैं चाहता हूं या यदि ऐसा करने में कुछ कमियां हैं। एक और जो बिन केंद्र मैं शून्य गद्दी के बाद का चयन करना चाहिए क्योंकि मैं शिखर मूल्य प्राप्त कर रहा हूं (क्योंकि कोई शून्य की पैडिंग के बाद भी ब्याज की आवृत्ति को ठीक से हिट नहीं कर सकता है)।

हालांकि, मैं यह भी सोच रहा हूं कि क्या कोई और तरीका है जो बेहतर परिणाम दे सकता है, एक अनुमानकर्ता जो कि आसपास के दो बिन केंद्रों के चरम मूल्यों का उपयोग करता है, ब्याज की आवृत्ति पर शिखर मूल्य का अनुमान लगाने के लिए।


2
एफएफटी से पहले शून्य पैडिंग एक तरीका है। एक और एक विंडो फ़ंक्शन लागू करना है जो आपके neads के लिए अनुकूल है। फ्लैट टॉप विंडो बिल्कुल इसी उद्देश्य के लिए डिजाइन की गई थी। बेशक, अगर आप पहले से ही आवृत्ति को ठीक से जानते हैं और आप केवल एक ही एम्प्यूटाइड में रुचि रखते हैं, तो शायद एफएफटी की तुलना में इसे करने के लिए सस्ते तरीके हैं।
sellibitze

1
कोई शून्य पैडिंग की आवश्यकता नहीं है: सरल परवलयिक प्रक्षेप (3 बिंदुओं के साथ: इमैक्स -1, इमैक्स, इमैक्स + 1, जहां imaxएफएफटी शिखर है) आपको सटीक परिणाम देगा
बसज

सुनिश्चित करें कि प्रक्षेप फ़ंक्शन विंडो फ़ंक्शन से मेल खाता है। फ़्लैट-टॉप तुच्छ है, अन्यथा आप एक मिलान जोड़ी चाहते हैं (जैसे आयताकार खिड़की + sinc प्रक्षेप, गाऊसी खिड़की + गाऊसी प्रक्षेप) आदि
finnw

@CedronDawg यह प्रश्न और इसके उत्तर आपके सटीक आवृत्ति सूत्र के साथ संबंधित (लेकिन समान नहीं हैं)। हो सकता है कि आपको यह दिलचस्प लगे।
Fat32

जवाबों:


5

पहला एल्गोरिथ्म जो मन को स्प्रिंग्स करता है वह है गोएर्टज़ेल एल्गोरिथम । वह एल्गोरिथ्म आमतौर पर मानता है कि ब्याज की आवृत्ति मौलिक आवृत्ति का एक पूर्णांक है। हालांकि, यह पेपर उस मामले पर सामान्यीकृत (सामान्यीकृत) एल्गोरिथ्म लागू करता है जिसमें आप रुचि रखते हैं।


एक और समस्या यह है कि सिग्नल मॉडल गलत है। इसका उपयोग करता है 2*%pi*(1:siglen)*(Fc/siglen)। इसे 2*%pi*(0:siglen-1)*(Fc/siglen)चरण के लिए सही ढंग से बाहर आने के लिए उपयोग करना चाहिए ।

मुझे भी लगता है कि आवृत्ति Fc=21.3कम होने की समस्या है । निम्न-आवृत्ति वाले वास्तविक-मूल्यवान सिग्नल चरण / आवृत्ति अनुमान समस्याओं के बारे में पूर्वाग्रह प्रदर्शित करते हैं।

मैंने चरण अनुमान के लिए एक मोटे ग्रिड खोज की भी कोशिश की, और यह Goertzel एल्गोरिथ्म के समान उत्तर देता है।

नीचे एक प्लॉट है जो दोनों अनुमानों में पूर्वाग्रह दिखाता है (Goertzel: blue, Coarse: red) दो अलग-अलग आवृत्तियों के लिए: Fc=21.3(ठोस) और Fc=210.3(धराशायी)। जैसा कि आप देख सकते हैं उच्च आवृत्ति के लिए पूर्वाग्रह बहुत कम है।

प्लॉट -axis 0 से बदलने वाला प्रारंभिक चरण है ।2 πx2π

यहाँ छवि विवरण दर्ज करें


बस कागज के आधार पर Goerzel एल्गोरिथ्म के लिए कोड का परीक्षण किया। आउटपुट DTFT मूल्य का उपयोग करते हुए, शिखर को बहुत सटीक रूप से प्राप्त किया जा सकता है। हालाँकि, इसमें 1000 का स्केलिंग फैक्टर है। इसलिए, अगर गोएरज़ेल के बाद मूल शिखर 1,234 है, तो यह 1234 होगा। क्या किसी को पता है कि यह कहाँ से आ सकता है?
lR8n6i

इस बीच कुछ शोध किया। संभवतः इसे आयाम स्केलिंग के साथ करना है: स्केलिंग टाइम डोमेन आयाम = आवृत्ति डोमेन गुणांक * 2 / एन, जहां एन सिग्नल की लंबाई है। क्या यह धारणा सही है?
lR8n6i


नमस्ते! मुझे अभी पता चला है कि गोएर्टज़ल एल्गोरिथ्म का उपयोग करने के परिणामस्वरूप, परिणामी जटिल गुणांक में आयाम बहुत सटीक है, लेकिन चरण पूरी तरह से गलत है। क्या किसी को अंदाजा है कि यह कहां से आ सकता है? "चरण" से मेरा मतलब है कि मूल संकेत के मूल में निर्दिष्ट चरण अंतराल।
lR8n6i

1
@ Rickson1982 चरण सही है। आप इसे सही ढंग से व्याख्या नहीं कर रहे हैं। :-) याद रखें: यानी जो आप छोड़ रहे हैं उससे (90 डिग्री) बाहर है । π/2sin(ω0t+ϕ)j2[ejϕδ~(ω+ω0+2πk)e+jϕδ~(ωω0+2πk)]π/2
पीटर के.एच.

4

यदि आप केवल 2 ही नहीं, बल्कि कई पड़ोसी एफएफटी डिब्बे का उपयोग करने के लिए तैयार हैं, तो जटिल बिन परिणामों के बीच विंडो सिनक प्रक्षेप खिड़की की चौड़ाई के आधार पर बहुत सटीक अनुमान लगा सकता है।

विंडो सिनक इंटरपोलेशन आम तौर पर उच्च गुणवत्ता वाले ऑडियो अपस् लेमर्स में पाया जाता है, इसलिए उस विषय पर कागजात में त्रुटि विश्लेषण के साथ उपयुक्त प्रक्षेप सूत्र होंगे।


टिप्पणी के लिए धन्यवाद। मैं इस दृष्टिकोण को भी आजमाऊंगा।
lR8n6i

4

यदि आप Flanagan [1] का उपयोग करते हैं, तो इसे क्रमिक चरण स्पेक्ट्रा difference (तात्कालिक आवृत्ति) के चरण अंतर से गणना की जाती है और यदि आप एक सही कारक (तात्कालिक चुंबकत्व) का उपयोग करके परिमाण को फिर से संगठित करते हैं [2] एक सामान्यीकृत शंकु फ़ंक्शन का उपयोग करें: और अंत में चोटी के परिमाण के आसपास परवलयिक प्रक्षेप का उपयोग करके आप आश्चर्यजनक परिणाम प्राप्त कर सकते हैं, आज मैं समझता हूं कि यह सबसे अच्छा तरीका है, मुझे इसका उपयोग किया गया है और परिणाम हमेशा होते हैं बहुत ठोस :-)

sin(πx)(πx)

[१] जेएल फ्लैनागन और आरएम गोल्डन, "फेज वोकडर," बेल सिस्टम्स टेक्निकल जर्नल, वॉल्यूम। 45, पीपी। 1493–1509, 1966।

[२] के। ड्रेसर, "एक बहु-रिज़ॉल्यूशन FFT के एक fi of cient कार्यान्वयन का उपयोग करके साइनसोइडल एक्सट्रैक्शन," प्रोक में। 9 वीं इंट। सम्मेलन। डिजिटल ऑडियो प्रभाव (DAFx-06), मॉन्ट्रियल, कनाडा, सितम्बर 2006, पीपी। 247-252 पर।


नमस्ते! आपकी सभी टिप्पणियों के लिए बहुत बहुत धन्यवाद। मैंने अपना कोड बढ़ाया (नीचे देखें) चरण प्राप्त करने के लिए पैराबोलिक चोटी के प्रक्षेप के साथ गोएर्टज़ेल फ़िल्टर को संयोजित करने के लिए। हालांकि, परिणाम अभी भी सटीक नहीं हैं (+ - 3-4 डिग्री)। क्या यह उतना ही निकट है जितना कि इसे समझने या कोडिंग में गलतियाँ हैं?
lR8n6i

3

एक तरीका यह है कि इसके बारे में एक परबोला को अधिकतम और फिट किया जाए, और फिर आवृत्ति और परिमाण अनुमान के रूप में परबोला का अधिकतम उपयोग करें। आप यहाँ पढ़ सकते हैं: https://ccrma.stanford.edu/~jos/sasp/Sinusoidal_Peak_Interpolation.html


3

मुझे कुछ साल पहले इस सटीक समस्या से बहुत कठिनाई थी।

मैंने यह प्रश्न पोस्ट किया है:

/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;
}

आप आवृत्ति को प्रक्षेपित कर रहे हैं, जबकि ओपी आवृत्ति जानता है और आयाम को प्रक्षेपित करना चाहता है।
finnw

2

यह पायथन कोड आपको एक बहुत ही सटीक परिणाम देगा (मैंने इसे बहुत सारे संगीत नोटों के लिए इस्तेमाल किया और अर्धवृत्त से कम 0,01% से अधिक त्रुटियां प्राप्त कीं) परवलयिक अवशिष्ट (मैक्युले क्वाटिएरी, सेरा, आदि) द्वारा हार्मोनिक + अवशिष्ट में प्रयुक्त विधि। जुदाई तकनीक)

import matplotlib.pyplot as plt
import numpy as np
from scipy.io.wavfile import read
from scipy.fftpack import fft, ifft
import math

(fs, x) = read('test.wav')
if (len(x.shape) == 2):    # if stereo we keep left channel only
 x = x[:,1]

n=x.size
freq = np.arange(n)*1.0/n*fs 
xfft = abs(fft(x))

imax=np.argmax(xfft)  
p=1.0/2*(xfft[imax-1]/xfft[imax]-xfft[imax+1]/xfft[imax])/(xfft[imax-1]/xfft[imax]-2+xfft[imax+1]/xfft[imax])   # parabolic interpolation 
print 'Frequence detectee avec interpolation parabolique :',(imax+p)*1.0/n*fs, 'Hz'

1
clear all
clc

for phase_orig = 0:pi/18:pi,

%% Specify and generate signal
Amp = 1;                     % Amplitude of signal
Fs = 8000;                   % samples per second
dt = 1/Fs;                   % seconds per sample
Fc = 21.3;                   % Hz
StopTime = 0.25;             % seconds
t = (0:dt:StopTime-dt)';     % seconds

siglen = length(t);
sig = Amp * 1.5 * sin(2*pi*(0:siglen-1)*(Fc/siglen) + phase_orig) + 1.5 * Amp * sin(2*pi*(0:siglen-1)*(Fc/siglen) * 3) ...
  + 1.5 * Amp * sin(2*pi*(0:siglen-1)*(Fc/siglen) * 5)+ 0.3 * Amp * sin(2*pi*(0:siglen-1)*(Fc/siglen) * 7) ...
  + 1.3 * Amp * sin(2*pi*(0:siglen-1)*(Fc/siglen) * 9)+ 1.4 * Amp * sin(2*pi*(0:siglen-1)*(Fc/siglen) * 11);

%% Estimate the peak value of the signals fundamental using Goertzel algorithm
peak = 0;
indvec = [Fc-1 Fc Fc+1];

% Check the input data
if ~isvector(sig) || isempty(sig)
  error('X must be a nonempty vector')
end

if ~isvector(indvec) || isempty(indvec)
  error('INDVEC must be a nonempty vector')
end
if ~isreal(indvec)
  error('INDVEC must contain real numbers')
end

% forcing x to be column
sig = reshape(sig,siglen,1);

% initialization
no_freq = length(indvec); %number of frequencies to compute
y = zeros(no_freq,1); %memory allocation for the output coefficients

% Computation via second-order system
% loop over the particular frequencies
for cnt_freq = 1:no_freq
  %for a single frequency:
  %a/ precompute the constants
  pik_term = 2*pi*(indvec(cnt_freq))/(siglen);
  cos_pik_term2 = cos(pik_term) * 2;
  cc = exp(-1i*pik_term); % complex constant
  %b/ state variables
  s0 = 0;
  s1 = 0;
  s2 = 0;
  %c/ 'main' loop
  for ind = 1:siglen-1 %number of iterations is (by one) less than the length of signal
    %new state
    s0 = sig(ind) + cos_pik_term2 * s1 - s2;  % (*)
    %shifting the state variables
    s2 = s1;
    s1 = s0;
  end
  %d/ final computations
  s0 = sig(siglen) + cos_pik_term2 * s1 - s2; %correspond to one extra performing of (*)
  y(cnt_freq) = s0 - s1*cc; %resultant complex coefficient

  %complex multiplication substituting the last iterationA
  %and correcting the phase for (potentially) non-integer valued
  %frequencies at the same time
  y(cnt_freq) = y(cnt_freq) * exp(-1i*pik_term*(siglen-1));
end

  % perfom amplitude scaling
  peak = abs(y(2)) * 2 / siglen

% perform parabolic interpolation to get the phase estimate
phase_orig=phase_orig*180/pi
ym1 = angle(unwrap(y(1)));
y0 = angle(unwrap(y(2)));
yp1 = angle(unwrap(y(3)));

p = (yp1 - ym1)/(2*(2*y0 - yp1 - ym1)); 
phase = y0 - 0.25*(ym1-yp1)*p;
phase_est = phase * 180/pi + 90;
phase_est = mod(phase_est+180,360)-180
end

आपके द्वारा व्यवहार की जा रही आवृत्तियों (8kHz पर 21.3Hz नमूना) बहुत कम हैं। क्योंकि ये वास्तविक मूल्यवान संकेत हैं, वे ** किसी भी ** आवृत्ति के लिए चरण अनुमान में पूर्वाग्रह प्रदर्शित करेंगे।

यह चित्र पूर्वाग्रह के phase_est - phase_origलिए Fc = 210.3;(लाल रंग में) बनाम पूर्वाग्रह की साजिश को दर्शाता है Fc = 21.3;। जैसा कि आप देख सकते हैं, ऑफसेट 21.3मामले के लिए बहुत अधिक महत्वपूर्ण है ।

एक अन्य विकल्प आपकी नमूना दर को कम करना है। हरे रंग की वक्र के Fs = 800बजाय पूर्वाग्रह दिखाता है 8000

यहाँ छवि विवरण दर्ज करें


1
अद्यतन के लिए धन्यवाद! मेरी साजिश देखें; मुझे अभी भी लगता है कि किसी भी चरण आकलनकर्ता के पास इस कम आवृत्ति के लिए पूर्वाग्रह होने वाला है। इसके चारों ओर आने का एक तरीका ज्ञात आवृत्ति (यदि यह ज्ञात है!) का उपयोग चरण-अनुमान पूर्वाग्रह को एक लुक-अप तालिका के माध्यम से ठीक करने के लिए है। लेकिन आपको सावधान रहने की आवश्यकता होगी: पूर्वाग्रह आवृत्ति के साथ बदल जाएगा। इसे करने का दूसरा तरीका यह होगा कि आप अपनी सैंपलिंग दर को कम करें।
पीटर के.एच.

1
आपको भी धन्यवाद! हालाँकि, यदि आप Fs = 8000 Hz और Fc = 210 का उपयोग कर रहे हैं तो 210.3 पूर्वाग्रह के बजाय और भी बदतर लग रहे हैं। किसी भी विचार यह कहाँ से आ सकता है?
lR8n6i

1
Erk! कोई जानकारी नहीं। FWIW, Geortzel अनुमानक समस्या नहीं है goertzel = atan(imag(y(2)),real(y(2)))*180/%pi + 90;:। :-) थोड़ा और खोदेंगे। इस जगह को देखो।
पीटर के.एच.

1
परवलयिक प्रक्षेप वह नहीं कर रहा है जो आपको लगता है कि यह कर रहा है। विशेष रूप से, अगर आप की अपनी गणना की जगह pके साथ p2 = (abs(y(3)) - abs(y(1)))/(2*(2*abs(y(2)) - abs(y(3)) - abs(y(1)))); phase2 = y0 - 0.25*(ym1-yp1)*p2;तो तुम बहुत बेहतर जवाब भी के लिए मिलता है --- Fc=210। मुझे बिल्कुल यकीन नहीं है कि वर्तमान संस्करण pआपको कुछ भी समझदार बना देगा। प्रक्षेप सूत्र एक परवलय के AMPLITUDE के प्रक्षेप के लिए है, लेकिन pउस चरण को प्रक्षेपित कर रहा है जो सिर्फ ... विषम है।
पीटर के.एच.

1
यह सब ठीक है, उदाहरण है कि p = (yp1 - ym1)/(2*(2*y0 - yp1 - ym1))यदि आप आयामों के बजाय PHASES का उपयोग कर रहे हैं तो पीक स्थान ( ) कुछ समय गलत होगा। ऐसा इसलिए है क्योंकि चरण +/- 180 डिग्री की सीमा के आसपास कूद सकते हैं । चरण के लिए इसे ठीक करने के लिए आवश्यक सभी को उस पंक्ति को मेरी p2गणना में बदलना होगा ।
पीटर के.एच.
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.