FFT з асиметричним вікном?


17

Усі загальні не прямокутні віконні функції здаються симетричними. Чи коли-небудь траплявся випадок, коли хтось хотів би використовувати несиметричну функцію вікна перед FFT? (Скажіть, якщо дані з одного боку діафрагми FFT вважалися дещо важливішими, ніж дані з іншого, або менш галасливими тощо)

Якщо так, то які види асиметричних функцій вікна були вивчені та як вони впливатимуть на частотну характеристику порівняно з (більш втраченою?) Зміщенням симетричного вікна?


2
Зазвичай вікна використовуються тому, що FFT працює на невеликі шматки сигналу, намагаючись зробити його локальним схожим на стаціонарний сигнал. Тому немає переваги "стороні", сигнал вважається рівномірним на всьому протязі.
ендоліт

4
в алгоритмі аудіоаналізу, який працює над прямими даними та має затримку пропускної здатності для побоювання, іноді може бути спроектовано асиметричне вікно, яке має менш ефективну затримку, ніж симетричне вікно тієї ж довжини. якщо поведінка цього асиметричного вікна (яке відомо заздалегідь) впливає на вихідні параметри цього аудіоаналізу відомим чином, ці параметри можна компенсувати, і ви зберігаєте перевагу зменшеної затримки.
Роберт Брістоу-Джонсон

Відповіді:


9

Я використаю скорочене вікно для "функції вікна".

З аудіо будь-яка обробка, яка створює щось подібне до попереднього дзвінка або попереднього відлуння, буде звучати непогано, як mp3 з низькою швидкістю передачі. Це відбувається, коли локалізована енергія перехідного часу або імпульсу поширюється назад у часі, наприклад, шляхом модифікації спектральних даних у перетворених трансформаціях, таких як кодова модифікована дискретна косинусна трансформація (MDCT). При такій обробці аудіо віконце перекриваються вікнами аналізу , перетворюються, обробляються в частотній області (наприклад, стиснуті даними на менший бітрейт), знову відкриваються вікном синтезу і підсумовуються назад. Продукт вікна аналізу та синтезу повинен бути таким, що вікна, що перекриваються, дорівнюють одиниці.

Традиційно використовувані функції вікон були симетричними, і їх ширина була компромісом між селективністю частоти (довге вікно) та уникненням артефактів часової області (коротке вікно). Чим ширше вікно, тим більше з часом обробка може поширити сигнал. Більш свіжим рішенням є використання асиметричного вікна. Два використовуваних вікна можуть бути дзеркальними зображеннями один одного. Вікно аналізу падає з піку до нуля швидко, так що імпульси не «виявляються» заздалегідь, а вікно синтезу швидко піднімається від нуля до піку, так що наслідки будь-якої обробки не поширюються значно назад за часом. Ще одна перевага цього - низька затримка. Асиметричні вікна можуть мати хорошу селективність частоти і можуть замінювати симетричні вікна змінного розміру при стисненні звуку, як би своєрідне лікування. ПобачитиМ. Шнелл, М. Шмідт, М. Джандер, Т. Альберт, Р. Гейгер, В. Руоппіла, П. Екстранд, М. Луцький, Б. Гриль, “MPEG-4 Enhanced Low Delay AAC - новий стандарт для високих якісна комунікація » , 125-а Конвенція AES, Сан-Франциско, Каліфорнія, США, передрук 7503, жовтень 2008 р. та інший документ про конференцію, де вони також показують масштабність перетворення Фур'є у своєму вікні: Schnell, M., et al. 2007. Розширений MPEG-4 з низькою затримкою AAC - низька швидкість зв'язку високої якості. У 122-й Конвенції AES .

Ілюстрація провідної аналізу-обробки-синтезу з використанням асиметричних вікон
Рисунок 1. Ілюстрація використання асиметричних вікон у пробіжному аналізі-обробці-синтезі. Продукт (чорний пунктир) вікна аналізу (синій) та вікна синтезу (жовтувато-оранжевий) дорівнює єдності з вікном попереднього кадру (сірий пунктир). Необхідні додаткові обмеження для гарантування ідеальної реконструкції при використанні MDCT.

Дискретна трансформація Фур'є (DFT, FFT) може використовуватися замість MDCT, але в таких контекстах даватиме надлишкові спектральні дані. Порівняно з DFT, MDCT дає лише половину спектральних даних, все ще дозволяє ідеальну реконструкцію, якщо обрано відповідні вікна.

Ось моя власна асиметрична конструкція вікон (рис. 2), яка підходить для нанесеного аналізу-обробки-синтезу з використанням DFT, але не MDCT, з яким вона не дає ідеальної реконструкції. Вікно намагається мінімізувати добуток пропускної здатності середнього квадрату часу та частоти (подібно до обмеженого Гауссового вікна ), зберігаючи деякі потенційно корисні властивості часової області: негативні, одномодальні з піком у "нульовий час", навколо якого відбувається аналіз та синтез windows - це дзеркальні зображення один одного, функціональність і неперервна похідна похідна, нульове значення, коли квадрат віконної функції трактується як ненормалізована функція щільності ймовірностей. Вікно було оптимізоване за допомогою диференціальної еволюції .

Асиметричне та косинусне вікно
Малюнок 2. Зліва: вікно несиметричного аналізу, придатне для перекритого аналізу-обробки-ресинтезу, разом із вікном синтезу аналогічного аналогічного часу. Праворуч: косине вікно, з тією ж затримкою, що і асиметричне вікно

Фур'єрні вікна вікон
Рисунок 3. Величина перетворень Фур'є косинусного вікна (синє) та асиметричного вікна (оранжеве) на рис. 2. Асиметричне вікно демонструє кращу селективність частоти.

Ось вихідний код Octave для сюжетів та для асиметричного вікна. Код планування походить від Вікімедіа . У Linux я рекомендую встановити 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;
}

І вихідний код функції оптимізації витрат, що використовується з Kiss 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) не має різких перехідних на початку в порівнянні з кінцем. Вартість полягає в тому, що частоти до центру (симетричного) вікна будуть більш зваженими та представленими в наступних DFT.

Зважаючи на все це на задньому плані, я можу уявити, що можна було б використовувати асиметричне вікно для акцентування місцевих часових особливостей у сигналі, що аналізується через DFT. Однак це може статися ціною ширшої долі під час DFT, якщо кінцеві точки сигналу не будуть приблизно однаковою амплітудою після вікна.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.