비대칭 윈도우가있는 FFT?


17

직사각형이 아닌 일반적인 창 기능은 모두 대칭 인 것 같습니다. FFT 이전에 비대칭 창 기능을 사용하려는 경우가 있습니까? (FFT 조리개 한쪽의 데이터가 다른 쪽의 데이터보다 조금 더 중요하거나 덜 시끄러운 것으로 간주되는 경우)

그렇다면 어떤 종류의 비대칭 창 함수가 연구되었으며, (더 손실이 많은) 오프셋 대칭 창과 비교하여 주파수 응답에 어떤 영향을 미칩니 까?


2
FFT가 신호의 작은 덩어리에서 작동하여 고정 신호처럼 로컬로 보이도록하기 때문에 일반적으로 윈도우가 사용됩니다. 따라서 선호하는 "측면"은 없으며 신호는 전체적으로 균일 한 것으로 가정합니다.
endolith

4
라이브 데이터에서 작업하고 처리 지연이 걱정되는 오디오 분석 알고리즘에서, 때때로 같은 길이의 대칭 창보다 덜 효과적인 지연을 갖는 비대칭 창을 설계 할 수 있습니다. 이 비대칭 창의 동작 (미리 알려진)이이 오디오 분석의 출력 매개 변수에 알려진 방식으로 영향을 미치는 경우 해당 매개 변수를 보상 할 수 있으며 지연 감소의 이점을 유지할 수 있습니다.
robert bristow-johnson

답변:


9

"창 기능"에 대한 단축 을 사용하겠습니다 .

오디오를 사용하면 프리 링 또는 프리 에코와 비슷한 것을 만드는 모든 처리가 낮은 비트 전송률 mp3처럼 느슨하게 들립니다. 이것은 과도 현상 또는 임펄스의 국부 에너지가 예를 들어 랩핑 된 변형 된 이산 코사인 변환 (MDCT)과 같은 랩핑 된 변환에서 스펙트럼 데이터의 수정에 의해 시간적으로 뒤로 확산 될 때 발생한다. 이러한 프로세싱에서, 오디오는 중첩 분석 윈도우에 의해 윈도 잉되고 , 변환되고, 주파수 도메인에서 (더 작은 비트율로 데이터 압축 된 것과 같이) 프로세싱되고, 합성 윈도우로 다시 윈도 잉되고 다시 합산된다. 분석 및 합성 창의 곱은 겹치는 창이 합쳐 지도록해야합니다.

전통적으로 사용 된 윈도우 기능은 대칭 적이며 폭은 주파수 선택성 (긴 윈도우)과 시간 영역 아티팩트 회피 (짧은 윈도우) 사이에서 절충되었습니다. 윈도우가 넓을수록 처리 시간이 길어질수록 신호가 확산 될 수 있습니다. 보다 최근의 해결책은 비대칭 창을 사용하는 것입니다. 사용 된 두 개의 창은 서로의 미러 이미지 일 수 있습니다. 분석 창이 피크에서 제로로 빠르게 떨어 지므로 임펄스가 많이 "감지"되지 않고 신디사이저 창이 제로에서 피크로 빠르게 올라가므로 모든 처리의 효과가 시간에 따라 크게 뒤로 퍼지지 않습니다. 이것의 또 다른 장점은 낮은 대기 시간입니다. 비대칭 윈도우는 양호한 주파수 선택성을 가질 수 있고, 모든 종류의 치료와 같은 오디오 압축에서 가변 크기의 대칭 윈도우를 대체 할 수있다. 보다M. Schnell, M. Schmidt, M. Jander, T. Albert, R. Geiger, V. Ruoppila, P. Ekstrand, M. Lutzky, B. Grill, “MPEG-4 Enhanced Low Delay AAC-새로운 표준 양질의 커뮤니케이션” , 125 회 AES 컨벤션, 미국 캘리포니아, 샌프란시스코, 2008 년 10 월, Preprint 7503, 2008 년 10 월 및 다른 회의 논문에서 Schier, M., et al. 2007. 향상된 MPEG-4 저 지연 AAC – 낮은 비트 전송률 고품질 통신. 제 122 회 AES 협약 .

비대칭 창을 사용한 랩핑 분석 처리 합성 그림
그림 1. 랩 분석 분석 합성에서 비대칭 창 사용 그림. 분석 창 (파란색)과 합성 창 (노란색 주황색)의 곱 (검은 색 파선)은 이전 프레임의 창 (회색 파선)과 일치합니다. MDCT를 사용할 때 완벽한 재구성을 보장하기 위해서는 추가 제약이 필요합니다.

MDCT 대신 이산 푸리에 변환 (DFT, FFT)을 사용할 수 있지만 이러한 상황에서는 중복 스펙트럼 데이터가 제공됩니다. DFT와 비교하여 MDCT는 스펙트럼 데이터의 절반 만 제공하면서도 적절한 창이 선택되면 완벽한 재구성이 가능합니다.

여기에는 DFT를 사용하지만 완벽한 재구성을 제공하지 않는 MDCT가 아닌 랩핑 분석 처리 합성에 적합한 내 비대칭 창 디자인 (그림 2)이 있습니다. 이 윈도우는 잠재적으로 유용한 시간 영역 속성을 유지하면서 평균 제곱 시간 및 주파수 대역폭 ( 제한 가우시안 윈도우 와 유사)의 곱을 최소화하려고 시도 합니다. 윈도우는 서로의 미러 이미지, 함수 및 1 차 미분 연속성, 윈도우 함수의 제곱이 정규화되지 않은 확률 밀도 함수로 해석 될 때의 평균입니다. 이 창은 차등 진화를 사용하여 최적화되었습니다 .

비대칭 및 코사인 창
그림 2. 왼쪽 : 시간 역전 된 대응 물 합성 창과 함께 중첩 된 분석 처리 재 합성에 적합한 비대칭 분석 창. 오른쪽 : 비대칭 창과 대기 시간이 같은 코사인 창

창문의 푸리에 변형
그림 3. 그림 2의 코사인 창 (파란색)과 비대칭 창 (주황색)의 푸리에 변환의 크기.

다음은 플롯과 비대칭 창에 대한 옥타브 소스 코드입니다. 플로팅 코드는 Wikimedia Commons 에서 제공 합니다. 내가 설치하는 것이 좋습니다 리눅스 gnuplot, epstool, pstoedit, transfiglibrsvg2-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");

0에서 시작하고 끝나기 때문에 매 초마다 샘플을 사용할 수 있습니다. 다음 C ++ 코드는이를 수행하므로 모든 곳에서 0 인 창을 제외하고 샘플을 전혀 얻지 못합니다. 분석 윈도우의 경우 이것은 1 분기이며 합성 윈도우의 경우는 마지막 분기입니다. 분석 윈도우의 후반부는 제품 계산을 위해 합성 윈도우의 전반과 정렬되어야합니다. 이 코드는 또한 창의 평균 (확률 밀도 함수)을 테스트하고 겹친 재구성의 평탄도를 보여줍니다.

#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

창의 컨텍스트에 따라 다릅니다. 윈도 잉은 전통적으로 개발되었으므로 전력 스펙트럼 밀도 추정의 Blackman-Tukey 방법을 위해 고안되었습니다. 이것은 상호 연관 법의 일반적인 형태로, 이산 시간 위너-킨친 정리가 이용된다. 이것은 이산 시간 푸리에 변환을 통해 자기 상관 시퀀스를 전력 스펙트럼 밀도와 관련시킵니다.

따라서 여러 기준을 염두에두고 창을 설계했습니다. 첫째, 그들은 기원에서 통일 된 이익을 가져야했다. 이것은 rxx [0]이 샘플 전력으로 생각 될 수 있기 때문에 신호의 자기 상관 시퀀스에서 전력을 보존하기위한 것입니다. 다음으로, 창은 원점에서 점점 가늘어 져야합니다. 여러 가지 이유가 있습니다. 먼저, 유효한 자기 상관 시퀀스가 ​​되려면 다른 모든 지연이 원점보다 작거나 같아야합니다. 둘째, 이는 대부분의 샘플을 사용하여 큰 신뢰도로 계산 된 하위 지연의 가중치를 높이고, 상위 지연의 가중치를 작거나 0으로 설정하여 데이터 지연 시간이 길어짐에 따라 분산이 증가합니다. 계산. 결과적으로 PSD 추정에서 메인 로브가 더 넓어지고 해상도가 감소합니다.

마지막으로, 창에 음이 아닌 스펙트럼이 있으면 매우 바람직합니다. Blackman-Tukey 방법을 사용하면 최종 추정치의 바이어스를 윈도우 스펙트럼과 관련된 실제 전력 스펙트럼 밀도로 생각할 수 있기 때문입니다. 이 윈도우 스펙트럼에 음의 영역이 있으면 전력 스펙트럼 밀도 추정에 음의 영역이있을 수 있습니다. 이 문맥에서 물리적 의미가 거의 없기 때문에 이것은 바람직하지 않습니다. 또한 Blackman-Tukey 방법에는 크기 제곱 연산이 없습니다. 실제 및 자기 상관 시퀀스에 실제 및 짝수 윈도우를 곱하면 이산 푸리에 변환도 실제적이고 균일하기 때문입니다. 실제로는 일반적으로 양자화되는 매우 작은 음의 성분이 있습니다.

이러한 이유로, 모든 유효한 자기 상관 시퀀스도 함께 있기 때문에 윈도우의 길이도 홀수입니다. 이제, 여전히 할 수있는 (그리고 행해지는) 주기도 방법의 맥락에서 윈도 잉입니다. 즉, 데이터를 윈도우 화 한 다음 윈도우 화 된 데이터의 크기 제곱을 취합니다. 이것은 Blackman-Tukey 방법과 동일하지 않습니다. 일부 통계적 도출을 통해 평균적으로 유사하게 작동 하지만 일반적으로 그렇지는 않음을 알 수 있습니다. 예를 들어, Welch 또는 Bartlett의 방법에서 각 세그먼트에 대해 윈도 잉을 사용하여 추정의 분산을 줄이는 것이 일반적입니다. 본질적으로 이러한 방법으로 동기 부여는 부분적으로 동일하지만 다릅니다. 이들 방법에서 전력은 창 지연의 신중한 가중치 대신에 창 에너지를 분할함으로써 정규화된다.

희망적으로 이것은 창과 그 기원을 문맥 화하고 왜 대칭인지를 희망합니다. 비대칭 창을 선택한 이유에 대해 궁금한 경우 푸리에 변환의 이중성 속성의 영향과 전력 스펙트럼 밀도 추정이 어떻게 적용되는지를 고려하십시오. 건배.


1

윈도 잉의 원래 지점은 (DFT에 의해 주기적으로 가정되는) 신호가 처음과 비교할 때 날카로운 과도 전류가 없는지 확인하는 것입니다. 비용은 (대칭) 창의 중심을 향한 주파수가 더 가중되어 후속 DFT에 표시됩니다.

모든 것을 배경으로, DFT를 통해 분석되는 신호의 로컬 시간적 특징 을 강조하기 위해 비대칭 창을 사용하고 싶다고 상상할 수 있습니다 . 그러나 신호 종료 지점이 윈도 잉 후 거의 동일한 진폭이 아닌 경우 DFT 도중 로브 폭이 넓어 질 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.