असममित विंडोिंग के साथ एफएफटी?


17

सामान्य गैर-आयताकार खिड़की के कार्य सभी सममित प्रतीत होते हैं। क्या कभी ऐसा मामला होता है जब कोई एफएफटी से पहले एक गैर-सममित खिड़की फ़ंक्शन का उपयोग करना चाहेगा? (यह कहें कि एफएफटी एपर्चर के एक तरफ के डेटा को दूसरे पर डेटा की तुलना में थोड़ा अधिक महत्वपूर्ण माना जाता है, या कम शोर, आदि)

यदि ऐसा है, तो किस प्रकार की असममित खिड़की के कार्यों का अध्ययन किया गया है, और वे (अधिक हानिरहित?) सममित खिड़की की तुलना में आवृत्ति प्रतिक्रिया को कैसे प्रभावित करेंगे?


2
आम तौर पर विंडोज़ का उपयोग किया जाता है क्योंकि एफएफटी एक सिग्नल के छोटे हिस्से पर काम कर रहा है, यह एक स्थिर सिग्नल की तरह स्थानीय रूप से देखने की कोशिश कर रहा है। इसलिए पसंद करने के लिए कोई "पक्ष" नहीं है, संकेत को पूरे समान माना जाता है।
'21

4
एक ऑडियो विश्लेषण एल्गोरिथ्म जो लाइव डेटा पर काम कर रहा है और इसके बारे में चिंता करने के लिए थ्रूपुट देरी है, कभी-कभी एक असममित खिड़की को डिज़ाइन किया जा सकता है जिसमें समान लंबाई की सममित खिड़की की तुलना में कम प्रभावी देरी होती है। यदि इस असममित खिड़की (जो पहले से ज्ञात है) का व्यवहार इस ऑडियो विश्लेषण के आउटपुट मापदंडों को एक ज्ञात तरीके से प्रभावित करता है, तो उन मापदंडों की भरपाई की जा सकती है और आप कम देरी के लाभ को बरकरार रख सकते हैं।
रॉबर्ट ब्रिस्टो-जॉनसन

जवाबों:


9

मैं "विंडो फ़ंक्शन" के लिए शॉर्टहैंड विंडो का उपयोग करूंगा ।

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

परंपरागत रूप से उपयोग किए जाने वाले खिड़की के कार्य सममित थे, और उनकी चौड़ाई आवृत्ति चयनात्मकता (लंबी खिड़की) और समय-क्षेत्र विरूपण साक्ष्य परिहार (छोटी खिड़की) के बीच एक समझौता रही है। खिड़की जितनी चौड़ी होगी, प्रसंस्करण में उतनी ही अधिक समय तक सिग्नल फैल सकता है। एक और हालिया समाधान एक असममित खिड़की का उपयोग करना है। उपयोग की जाने वाली दो खिड़कियां एक दूसरे की दर्पण छवियां हो सकती हैं। विश्लेषण खिड़की शिखर से शून्य तक तेजी से गिरती है ताकि आवेगों को पहले से "अधिक" पता न चले, और सिंथेसिस खिड़की शून्य से शिखर तक तेजी से बढ़ जाती है, ताकि किसी भी प्रसंस्करण का प्रभाव समय में बहुत पीछे न फैले। इसका एक अन्य लाभ कम विलंबता है। विषम खिड़कियों में अच्छी आवृत्ति-चयनात्मकता हो सकती है, और ऑडियो संपीड़न में चर-आकार की सममित खिड़कियों को बदल सकते हैं, एक तरह का इलाज-सभी की तरह। देखएम। श्नेल, एम। श्मिट, एम। जैंडर, टी। अल्बर्ट, आर। गीगर, वी। रूपोपिला, पी। एकस्ट्रैंड, एम। लुत्ज़की, बी। ग्रिल, "MPEG-4 एन्हांस्ड लो डिले एएसी - हाई के लिए एक नया मानक गुणवत्ता संचार ” , 125 वें एईएस कन्वेंशन, सैन फ्रांसिस्को, सीए, यूएसए, पहले से ही 7503, अक्टूबर 2008 और एक अन्य कॉन्फ्रेंस पेपर जहां वे अपनी खिड़की के फूरियर ट्रांसफॉर्म के परिमाण भी दिखाते हैं: शनेल, एम।, एट अल। 2007. एन्हांस्ड MPEG-4 कम विलंब AAC - कम बिटरेट उच्च गुणवत्ता संचार। 122 वें एईएस कन्वेंशन में

विषम खिड़कियों का उपयोग करके विश्लेषण-प्रसंस्करण-संश्लेषण का चित्रण
चित्रा 1. छाया विश्लेषण-प्रसंस्करण-संश्लेषण में विषम खिड़कियों के उपयोग का चित्रण। विश्लेषण-विंडो (नीला) और संश्लेषण खिड़की (पीले नारंगी) का उत्पाद (काला धराशायी) पिछले फ्रेम (धराशायी) से खिड़की के साथ एकता के लिए बोता है। MDCT का उपयोग करते समय सही पुनर्निर्माण की गारंटी देने के लिए और बाधाओं की आवश्यकता होती है।

असतत फूरियर ट्रांसफॉर्म (DFT, FFT) का उपयोग MDCT के बजाय किया जा सकता है, लेकिन ऐसे संदर्भों में निरर्थक वर्णक्रमीय डेटा दिया जाएगा। DFT की तुलना में, MDCT वर्णक्रमीय डेटा का केवल आधा हिस्सा देता है, जबकि उपयुक्त विंडोज़ को चुने जाने पर भी पूर्ण पुनर्निर्माण को सक्षम करता है।

यहां डीएफटी का उपयोग करके मैप किए गए विश्लेषण-प्रसंस्करण-संश्लेषण के लिए उपयुक्त मेरी खुद की असममित खिड़की का डिज़ाइन (छवि 2) है, लेकिन एमडीसीटी नहीं है जिसके साथ यह सही पुनर्निर्माण नहीं देता है। विंडो कुछ संभावित उपयोगी समय-डोमेन गुणों को बनाए रखते हुए माध्य-वर्ग समय और फ़्रीक्वेंसी बैंडवाइड्स ( सीमित गॉसियन विंडो के समान ) के उत्पाद को कम करने की कोशिश करती है : "शून्य शून्य" पर शिखर जिसके साथ विश्लेषण और संश्लेषण होता है। विंडो एक दूसरे की दर्पण छवियां हैं, फ़ंक्शन और पहली व्युत्पन्न निरंतरता, शून्य-मतलब जब खिड़की फ़ंक्शन के वर्ग को एक असामान्य संभावना घनत्व फ़ंक्शन के रूप में व्याख्या की जाती है। विभेदक विकास का उपयोग करके खिड़की को अनुकूलित किया गया था ।

विषम और कोसाइन खिड़की
चित्रा 2. वाम: अपने समय उलट प्रतिपक्ष संश्लेषण खिड़की के साथ एक साथ अतिव्यापी विश्लेषण-प्रसंस्करण-पुनर्जन्म के लिए उपयुक्त एक विषम विश्लेषण खिड़की। दायां: कोसाइन विंडो, विषम खिड़की के समान विलंबता के साथ

खिड़कियों के फूरियर ट्रांसफॉर्मर
चित्रा 3. कोसाइन विंडो (ब्लू) और फिगर के असममित खिड़की (ऑरेंज) के फूरियर रूपांतरण के 2. विषमतापूर्ण खिड़की बेहतर आवृत्ति चयनात्मकता को दर्शाती है।

यहाँ भूखंडों के लिए और विषम खिड़की के लिए ऑक्टेव स्रोत कोड है। प्लॉटिंग कोड विकिमीडिया कॉमन्स से आता है । लिनक्स पर मैं इंस्टॉल करने की अनुशंसा gnuplot, epstool, pstoedit, transfigपहली और librsvg2-binके लिए का उपयोग करके देखने display

pkg load signal

graphics_toolkit gnuplot
set (0, "defaultaxesfontname", "sans-serif")
set (0, "defaultaxesfontsize", 12) 
set (0, "defaultaxeslinewidth", 1)

function plotWindow (w, wname, wfilename = "", wspecifier = "", wfilespecifier = "")

  M = 32; % Fourier transform size as multiple of window length
  Q = 512; % Number of samples in time domain plot
  P = 40; % Maximum bin index drawn
  dr = 130; % Maximum attenuation (dB) drawn in frequency domain plot

  N = length(w);
  B = N*sum(w.^2)/sum(w)^2 % noise bandwidth (bins)

  k = [0 : 1/Q : 1];
  w2 = interp1 ([0 : 1/(N-1) : 1], w, k);

  if (M/N < Q)
    Q = M/N;
  endif

  figure('position', [1 1 1200 600])
  subplot(1,2,1)
  area(k,w2,'FaceColor', [0 0.4 0.6], 'edgecolor', [0 0 0], 'linewidth', 1)
  if (min(w) >= -0.01)
    ylim([0 1.05])
    set(gca,'YTick', [0 : 0.1 : 1])
  else
    ylim([-1 5])
    set(gca,'YTick', [-1 : 1 : 5])
  endif
  ylabel('amplitude')
  set(gca,'XTick', [0 : 1/8 : 1])
  set(gca,'XTickLabel',[' 0'; ' '; ' '; ' '; ' '; ' '; ' '; ' '; 'N-1'])
  grid('on')
  set(gca,'gridlinestyle','-')
  xlabel('samples')
  if (strcmp (wspecifier, ""))
    title(cstrcat(wname,' window'), 'interpreter', 'none')
  else
    title(cstrcat(wname,' window (', wspecifier, ')'), 'interpreter', 'none')
  endif
  set(gca,'Position',[0.094 0.17 0.38 0.71])

  H = abs(fft([w zeros(1,(M-1)*N)]));
  H = fftshift(H);
  H = H/max(H);
  H = 20*log10(H);
  H = max(-dr,H);
  k = ([1:M*N]-1-M*N/2)/M;
  k2 = [-P : 1/M : P];
  H2 = interp1 (k, H, k2);

  subplot(1,2,2)
  set(gca,'FontSize',28)
  h = stem(k2,H2,'-');
  set(h,'BaseValue',-dr)
  xlim([-P P])
  ylim([-dr 6])
  set(gca,'YTick', [0 : -10 : -dr])
  set(findobj('Type','line'),'Marker','none','Color',[0.8710 0.49 0])
  grid('on')
  set(findobj('Type','gridline'),'Color',[.871 .49 0])
  set(gca,'gridlinestyle','-')
  ylabel('decibels')
  xlabel('bins')
  title('Fourier transform')
  set(gca,'Position',[0.595 0.17 0.385 0.71])

  if (strcmp (wfilename, ""))
    wfilename = wname;
  endif
  if (strcmp (wfilespecifier, ""))
    wfilespecifier = wspecifier;
  endif
  if (strcmp (wfilespecifier, ""))
    savetoname = cstrcat('Window function and frequency response - ', wfilename, '.svg');
  else
    savetoname = cstrcat('Window function and frequency response - ', wfilename, ' (', wfilespecifier, ').svg');
  endif
  print(savetoname, '-dsvg', '-S1200,600')
  close

endfunction

N=2^17; % Window length, B is equal for Triangular and Bartlett from 2^17
k=0:N-1;

w = -cos(2*pi*k/(N-1));
w .*= w > 0;
plotWindow(w, "Cosine")

freqData = [0.66697133904805994131, -0.20556692772918355727, 0.49267389481655493588, -0.25062332863369246594, -0.42388422228212319087, 0.42317609537724842905, -0.03930334287740060856, -0.11936153294075849129, 0.30201210285940127687, -0.15541616804857899536, -0.16208119255594669039, 0.12843871362286504723, -0.04470810646117385351, -0.00521885027256757845, 0.07185811583185619522, -0.02835116723496184862, -0.01393644785822748498, 0.00780746224568363342, -0.00748496824751256583, 0.00119325723511989282, 0.00194602547595042175];
freqData(1) /= 2;
scale = freqData(1) + sum(freqData.*not(mod(1:length(freqData), 2)));
freqData /= scale;
w = freqData(1)*ones(1, N);
for bin = 1:(length(freqData)/2)
  w += freqData(bin*2)*cos(2*pi*bin*((1:N)-1)/N);
  w += freqData(bin*2+1)*sin(2*pi*bin*((1:N)-1)/N);
endfor
w(N/4+1:N/2+1) = 0;
w(N/8+2:N/4) = (1 - w(N/8:-1:2).*w(7*N/8+2:N))./w(7*N/8:-1:6*N/8+2);
w = shift(w, -N/2);
plotWindow(w, "Asymmetrical");

आप विंडो के केवल हर दूसरे नमूने का उपयोग करना चाह सकते हैं क्योंकि यह शुरू होता है और शून्य पर समाप्त होता है। निम्नलिखित C ++ कोड आपके लिए ऐसा करता है जिससे आपको विंडो के एक चौथाई हिस्से को छोड़कर कोई भी शून्य नमूना नहीं मिलता है जो हर जगह शून्य है। विश्लेषण विंडो के लिए यह पहली तिमाही है और संश्लेषण खिड़की के लिए यह अंतिम तिमाही है। विश्लेषण विंडो की दूसरी छमाही को उनके उत्पाद की गणना के लिए संश्लेषण खिड़की के पहले छमाही के साथ गठबंधन किया जाना चाहिए। कोड भी विंडो के माध्य (संभाव्यता घनत्व फ़ंक्शन के रूप में) का परीक्षण करता है, और ओवरलैप किए गए पुनर्निर्माण का सपाटता दिखाता है।

#include <stdio.h>
#include <math.h>

int main() {
  const int windowSize = 400;
  double *analysisWindow = new double[windowSize];
  double *synthesisWindow = new double[windowSize];
  for (int k = 0; k < windowSize/4; k++) {
    analysisWindow[k] = 0;
  }
  for (int k = windowSize/4; k < windowSize*7/8; k++) {
    double x = 2 * M_PI * ((k+0.5)/windowSize - 1.75);
    analysisWindow[k] = 2.57392230162633461887-1.58661480271141974718*cos(x)+3.80257516644523141380*sin(x)
      -1.93437090055110760822*cos(2*x)-3.27163999159752183488*sin(2*x)+3.26617449847621266201*cos(3*x)
      -0.30335261753524439543*sin(3*x)-0.92126091064427817479*cos(4*x)+2.33100177294084742741*sin(4*x)
      -1.19953922321306438725*cos(5*x)-1.25098147932225423062*sin(5*x)+0.99132076607048635886*cos(6*x)
      -0.34506787787355830410*sin(6*x)-0.04028033685700077582*cos(7*x)+0.55461815542612269425*sin(7*x)
      -0.21882110175036428856*cos(8*x)-0.10756484378756643594*sin(8*x)+0.06025986430527170007*cos(9*x)
      -0.05777077835678736534*sin(9*x)+0.00920984524892982936*cos(10*x)+0.01501989089735343216*sin(10*x);
  }
  for (int k = 0; k < windowSize/8; k++) {
    analysisWindow[windowSize-1-k] = (1 - analysisWindow[windowSize*3/4-1-k]*analysisWindow[windowSize*3/4+k])/analysisWindow[windowSize/2+k];
  }
  printf("Analysis window:\n");
  for (int k = 0; k < windowSize; k++) {
    printf("%d\t%.10f\n", k, analysisWindow[k]);
  }
  double accu, accu2;
  for (int k = 0; k < windowSize; k++) {
    accu += k*analysisWindow[k]*analysisWindow[k];
    accu2 += analysisWindow[k]*analysisWindow[k];
  }
  for (int k = 0; k < windowSize; k++) {
    synthesisWindow[k] = analysisWindow[windowSize-1-k];
  }
  printf("\nSynthesis window:\n");
  for (int k = 0; k < windowSize; k++) {
    printf("%d\t%.10f\n", k, synthesisWindow[k]);
  }
  printf("Mean of square of analysis window as probability density function:\n%f", accu/accu2);
  printf("\nProduct of analysis and synthesis windows:\n");
  for (int k = 0; k < windowSize/2; k++) {
    printf("%d\t%.10f\n", k, analysisWindow[windowSize/2+k]*synthesisWindow[k]);
  }
  printf("\nSum of overlapping products of windows:\n");
  for (int k = 0; k < windowSize/4; k++) {
    printf("%d\t%.10f\n", k, analysisWindow[windowSize/2+k]*synthesisWindow[k]+analysisWindow[windowSize/2+k+windowSize/4]*synthesisWindow[k+windowSize/4]);
  }
  delete[] analysisWindow;
  delete[] synthesisWindow;
}

और अनुकूलन लागत समारोह के लिए स्रोत कोड के साथ प्रयोग की जाने वाली चुंबन FFT और एक अनुकूलन पुस्तकालय :

class WinProblem : public Opti::Problem {
private:
  int numParams;
  double *min;
  double *max;
  kiss_fft_scalar *timeData;
  kiss_fft_cpx *freqData;
  int smallSize;
  int bigSize;
  kiss_fftr_cfg smallFFTR;
  kiss_fftr_cfg smallIFFTR;
  kiss_fftr_cfg bigFFTR;
  kiss_fftr_cfg bigIFFTR;

public:
  // numParams must be odd
  WinProblem(int numParams, int smallSize, int bigSize, double* candidate = NULL) : numParams(numParams), smallSize(smallSize), bigSize(bigSize) {
    min = new double[numParams];
    max = new double[numParams];
    if (candidate != NULL) {
      for (int i = 0; i < numParams; i++) {
        min[i] = candidate[i]-fabs(candidate[i])*(1.0/65536);
        max[i] = candidate[i]+fabs(candidate[i])*(1.0/65536);
      }
    } else {
      for (int i = 0; i < numParams; i++) {
        min[i] = -1;
        max[i] = 1;
      }
    }
    timeData = new kiss_fft_scalar[bigSize];
    freqData = new kiss_fft_cpx[bigSize/2+1];
    smallFFTR = kiss_fftr_alloc(smallSize, 0, NULL, NULL);
    smallIFFTR = kiss_fftr_alloc(smallSize, 1, NULL, NULL);
    bigFFTR = kiss_fftr_alloc(bigSize, 0, NULL, NULL);
    bigIFFTR = kiss_fftr_alloc(bigSize, 1, NULL, NULL);
  }

  double *getMin() {
    return min;
  }

  double *getMax() {
    return max;
  }

// ___                                                            __ 1     
// |  \    |       |       |       |       |       |       |     / |       
// |   \   |       |       |       |       |       |       |    /  |       
// |    \_ |       |       |       |       |       |       |   /   |
// |      \|__     |       |       |       |       |       |  /|   |       
// |       |  -----|_______|___    |       |       |       | / |   |       
// |       |       |       |   ----|       |       |       |/  |   |       
// --------------------------------x-----------------------x---|---- 0
// 0      1/8     2/8     3/8     4/8     5/8     6/8     7/8 15/16 
// |-------------------------------|                       |-------|
//            zeroStarts                                   winStarts
//
// f(x) = 0 if 4/8 < x < 7/8
// f(-x)f(x) + f(-x+1/8)f(x-1/8) = 1 if 0 < x < 1/8

  double costFunction(double *params, double compare, int print) {
    double penalty = 0;
    double accu = params[0]/2;
    for (int i = 1; i < numParams; i += 2) {
      accu += params[i];
    }
    if (print) {
      printf("%.20f", params[0]/2/accu);
      for (int i = 1; i < numParams; i += 2) {
        printf("+%.20fcos(%d pi x)", params[i]/accu, (i+1)/2);
        printf("+%.20fsin(%d pi x)", params[i+1]/accu, (i+1)/2);
      }
      printf("\n");
    }
    if (accu != 0) {
      for (int i = 0; i < numParams; i++) {
        params[i] /= accu;
      }
    }
    const int zeroStarts = 4; // Normally 4
    const int winStarts = 2; // Normally 1
    int i = 0;
    int j = 0;
    freqData[j].r = params[i++];
    freqData[j++].i = 0;
    for (; i < numParams;) {
      freqData[j].r = params[i++];
      freqData[j++].i = params[i++];
    }
    for (; j <= smallSize/2;) {
      freqData[j].r = 0;
      freqData[j++].i = 0;
    }
    kiss_fftri(smallIFFTR, freqData, timeData);
    double scale = 1.0/timeData[0];
    double tilt = 0;
    double tilt2 = 0;
    for (int i = 2; i < numParams; i += 2) {
      if ((i/2)%2) {
        tilt2 += (i/2)*params[i]*scale;
      } else {
        tilt2 -= (i/2)*params[i]*scale;
      }
      tilt += (i/2)*params[i]*scale;
    }
    penalty += fabs(tilt);
    penalty += fabs(tilt2);
    double accu2 = 0;
    for (int i = 0; i < smallSize; i++) {
      timeData[i] *= scale;
    }
    penalty += fabs(timeData[zeroStarts*smallSize/8]);
    penalty += fabs(timeData[winStarts*smallSize/16]*timeData[smallSize-winStarts*smallSize/16]-0.5);
    for (int i = 1; i < winStarts*smallSize/16; i++) {
      // Last 16th
      timeData[bigSize-winStarts*smallSize/16+i] = timeData[smallSize-winStarts*smallSize/16+i];
      accu2 += timeData[bigSize-winStarts*smallSize/16+i]*timeData[bigSize-winStarts*smallSize/16+i];
    }
    // f(-1/8+i)*f(1/8-i) + f(i)*f(-i) = 1
    // => f(-1/8+i) = (1 - f(i)*f(-i))/f(1/8-i)   
    // => f(-1/16) = (1 - f(1/16)*f(-1/16))/f(1/16)
    //             = 1/(2 f(1/16))
    for (int i = 1; i < winStarts*smallSize/16; i++) {
      // 2nd last 16th
      timeData[bigSize-winStarts*smallSize/8+i] = (1 - timeData[i]*timeData[bigSize-i])/timeData[winStarts*smallSize/8-i];
      accu2 += timeData[bigSize-winStarts*smallSize/8+i]*timeData[bigSize-winStarts*smallSize/8+i];
    }
    // Between 2nd last and last 16th
    timeData[bigSize-winStarts*smallSize/16] = 1/(2*timeData[winStarts*smallSize/16]);
    accu2 += timeData[bigSize-winStarts*smallSize/16]*timeData[bigSize-winStarts*smallSize/16];
    for (int i = zeroStarts*smallSize/8; i <= bigSize-winStarts*smallSize/8; i++) {
      timeData[i] = 0;
    }
    for (int i = 0; i < zeroStarts*smallSize/8; i++) {
      accu2 += timeData[i]*timeData[i];
    }
    if (print > 1) {
      printf("\n");
      for (int x = 0; x < bigSize; x++) {
        printf("%d,%f\n", x, timeData[x]);
      }
    }
    scale = 1/sqrt(accu2);
    if (print) {
      printf("sqrt(accu2) = %f\n", sqrt(accu2));
    }
    double tSpread = 0;
    timeData[0] *= scale;
    double tMean = 0;
    for (int i = 1; i <= zeroStarts*smallSize/8; i++) {
      timeData[i] *= scale;
      //      tSpread += ((double)i)*((double)i)*(timeData[i]*timeData[i]);
      double x_0 = timeData[i-1]*timeData[i-1];
      double x_1 = timeData[i]*timeData[i];
      tSpread += ((double)i)*((double)i)*(x_0 + x_1)*0.5 - ((double)i)*(2.0/3*x_0 + 1.0/3*x_1) + 0.25*x_0 + 1.0/12*x_1;
      double slope = timeData[i]-timeData[i-1];
      if (slope > 0) {
        penalty += slope+1;
      }
      tMean += x_1*i;
      if (timeData[i] < 0) {
        penalty -= timeData[i];
      }
    }
    double x_0 = timeData[0]*timeData[0];
    for (int i = 1; i <= winStarts*smallSize/8; i++) {
      timeData[bigSize-i] *= scale;
      double x_1 = timeData[bigSize-i]*timeData[bigSize-i];
      tSpread += ((double)i)*((double)i)*(x_0 + x_1)*0.5 - ((double)i)*(2.0/3*x_0 + 1.0/3*x_1) + 0.25*x_0 + 1.0/12*x_1;
      x_0 = x_1;        
      tMean += x_1*(-i);
    }
    tMean /= smallSize;
    penalty += fabs(tMean);
    if (tMean > 0) {
      penalty += 1;
    }
    tSpread /= ((double)smallSize)*((double)smallSize); 
    if (print) {
      printf("tSpread = %f\n", tSpread);
    }
    kiss_fftr(bigFFTR, timeData, freqData);
    double fSpread = 0;
    x_0 = freqData[0].r*freqData[0].r;
    for (int i = 1; i <= bigSize/2; i++) {
      double x_1 = freqData[i].r*freqData[i].r+freqData[i].i*freqData[i].i;
      fSpread += ((double)i)*((double)i)*(x_0 + x_1)*0.5 - ((double)i)*(2.0/3*x_0 + 1.0/3*x_1) + 0.25*x_0 + 1.0/12*x_1;
      x_0 = x_1;
    }
    if (print > 1) {
      for (int i = 0; i <= bigSize/2; i++) {
        printf("%d,%f,%f\n", i, freqData[i].r, freqData[i].i);
      }
    }
    fSpread /= bigSize; // Includes kiss_fft scaling
    if (print) {
      printf("fSpread = %f\n", fSpread);
      printf("%f,%f,%f\n", tSpread, fSpread, tSpread*fSpread);
    }
    return tSpread*fSpread + penalty;
  }

  double costFunction(double *params, double compare) {
    return costFunction(params, compare, false);
  }

  int getNumDimensions() {
    return numParams;
  }

  ~WinProblem() {
    delete[] min;
    delete[] max;
    delete[] timeData;
    delete[] freqData;
    KISS_FFT_FREE(smallFFTR);
    KISS_FFT_FREE(smallIFFTR);
    KISS_FFT_FREE(bigFFTR);
    KISS_FFT_FREE(bigIFFTR);
  }
};

3

यह विंडोिंग के संदर्भ पर निर्भर करता है। घुमावदार, जैसा कि यह पारंपरिक रूप से विकसित किया गया था, अनुमान के पावर वर्णक्रमीय घनत्व के ब्लैकमैन-तुकी पद्धति के लिए अभिप्रेत था। यह कोरलोग्राम विधियों का सामान्य रूप है, जिससे असतत समय वीनर-खिनचिन प्रमेय का शोषण होता है। यह याद करते हुए असतत समय फूरियर रूपांतरण के माध्यम से विद्युत वर्णक्रमीय घनत्व के लिए ऑटोक्रॉलेशन अनुक्रम से संबंधित है।

इसलिए, खिड़कियों को कई मानदंडों को ध्यान में रखते हुए डिजाइन किया गया था। सबसे पहले, उन्हें मूल स्थान पर एकता हासिल करनी थी। यह सिग्नल के ऑटोक्रॉलेशन अनुक्रम में शक्ति को संरक्षित करने के लिए था, क्योंकि rxx [0] को नमूना शक्ति के रूप में माना जा सकता है। अगला, विंडो को मूल से टेंपर करना चाहिए। यह कई कारणों से है। सबसे पहले, एक वैध ऑटोकैरेलेशन अनुक्रम होने के लिए, अन्य सभी लैग को मूल से कम या बराबर होना चाहिए। दूसरा, यह निचले लैग के उच्च भार के लिए अनुमति देता है, जो कि अधिकांश नमूनों का उपयोग करके बहुत आत्मविश्वास के साथ गणना की गई है, और उच्च लैग के छोटे या शून्य भार के कारण, जिनके लिए उपलब्ध डेटा नमूनों की घटती मात्रा के कारण विचरण बढ़ रहा है। गणना। यह अंततः एक विस्तृत मुख्य लोब में परिणाम देता है और बाद में PSD अनुमान में संकल्प में कमी आई है,

अंत में, यह अत्यधिक वांछित है अगर खिड़कियों में एक गैर-स्पेक्ट्रम स्पेक्ट्रम होता है। इसका कारण यह है कि ब्लैकमैन-तुकी पद्धति के साथ, आप अंतिम अनुमान के पूर्वाग्रह के बारे में सोच सकते हैं क्योंकि विंडो स्पेक्ट्रम के साथ वास्तविक शक्ति वर्णक्रमीय घनत्व को दोषी ठहराया गया है। यदि इस विंडो स्पेक्ट्रम में नकारात्मक क्षेत्र हैं, तो आपके पावर स्पेक्ट्रल घनत्व के अनुमान में नकारात्मक क्षेत्र होना संभव है। यह स्पष्ट रूप से अवांछित है, क्योंकि इस संदर्भ में इसका भौतिक अर्थ कम है। इसके अलावा, आप ध्यान दें कि ब्लैकमैन-तुकी पद्धति में कोई परिमाण नहीं है। ऐसा इसलिए है, क्योंकि एक वास्तविक और यहां तक ​​कि ऑटोक्रॉलेशन अनुक्रम को एक वास्तविक और यहां तक ​​कि खिड़की से गुणा किया जाता है, असतत फूरियर रूपांतरण वास्तविक और यहां तक ​​कि होगा। व्यवहार में, आपको बहुत छोटे नकारात्मक घटक मिलेंगे, जिन्हें आमतौर पर बाहर रखा जाता है।

इन कारणों के लिए, खिड़कियां विषम लंबाई की भी हैं क्योंकि सभी मान्य ऑटोक्रॉलेशन अनुक्रम समान हैं। अब, जो अभी भी किया जा सकता है (और किया जाता है) पीरियोडोग्राम विधियों के संदर्भ में विंडोिंग है। यही है, डेटा को विंडो करें, और फिर विंडो किए गए डेटा के परिमाण को लें। यह ब्लैकमैन-तुकी पद्धति के बराबर नहीं है। आप कुछ सांख्यिकीय व्युत्पत्तियों के माध्यम से पा सकते हैं, कि वे औसतन समान व्यवहार करते हैं , लेकिन सामान्य रूप से नहीं। उदाहरण के लिए, अनुमानों के विचलन को कम करने के लिए वेल्च या बार्टलेट की विधि में प्रत्येक खंड के लिए विंडोिंग का उपयोग करना काफी सामान्य है। तो संक्षेप में, इन विधियों के साथ, प्रेरणा एक ही भाग में है, लेकिन अलग है। विंडो लैग्स की सावधानीपूर्वक वेटिंग के बजाय, उदाहरण के लिए विंडो ऊर्जा को विभाजित करके इन विधियों में पावर को सामान्य किया जाता है।

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


1

विंडोिंग का मूल बिंदु यह सुनिश्चित करना है कि (DFT द्वारा समय-समय पर ग्रहण किए गए) सिग्नल की शुरुआत की तुलना में अंत में कोई तेज ग्राहक नहीं है। लागत यह है कि (सममित) खिड़की के केंद्र की ओर आवृत्तियों को अधिक भारित किया जाएगा और बाद के डीएफटी में प्रतिनिधित्व किया जाएगा।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.