2013-06-05 2 views
1

은 내가 어떻게 kissFFT를 사용하여 피크를 계산할 수 있습니까?

N=8192 
    kiss_fft_cpx out[N/2 +1]; 

    int len = fft->N/2 + 1; 

    kiss_fft_scalar* samples = &samples2[0]; //inputs from the mic 

    kiss_fftr(fft->config, samples, out); 

    for (int i = 0; i < len; i++) { 

     float re = scale(out[i].r) * N; 
     float im = scale(out[i].i) * N; 

     if (i > 0) 
      spectrum[i] = sqrtf(re * re + im * im)/(N/2); 
     else 
      spectrum[i] = sqrtf(re * re + im * im)/N; 

    } 

지금 내가 코드를 사용하여 선택을 계산 .. 실제 오디오 장치에 FFT를 적용하고

여기 내 코드입니다 프론트 피크를 계산합니다. 하지만 everytimes는 0 여기

float peak = 0; 
float maxEnergy = 0; 
for (int i = 0; i < BUFFER_SIZE/2 + 1; i++) { 

    float binEnergy = spectrum.at(i); 

    if (binEnergy > maxEnergy) { 

     maxEnergy = binEnergy; 
     peak = i; 

    } 

} 

내가 항상 = 피크를 얻을 0

여기

는 처음 25 개 FFT 샘플 내 specturm 출력입니다 도와주세요 ..

06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[0]: 0.036530 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[1]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[2]: 0.012086 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[3]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[4]: 0.040397 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[5]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[6]: 0.012086 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[7]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[8]: 0.044121 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[9]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[10]: 0.012086 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[11]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[12]: 0.040396 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[13]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[14]: 0.012086 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[15]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[16]: 0.116464 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[17]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[18]: 0.012086 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[19]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[20]: 0.040397 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[21]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[22]: 0.012086 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[23]: 0.011568 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(257) > specturm[24]: 0.044121 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(267) > peak 2223.000000 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(270) > FREQUENCY 4342.773438 
06-05 17:28:34.512 : INFO/HelloWorld (3351 : 3351) : void GuitarTunerMainForm::calculateFrequency(Tizen::Base::ByteBuffer *)(281) > octave 8 
+3

FFT 피크를 사용하는 것은 기타 튜너를 만드는 끔찍한 방법입니다. 대신 피치 검출/추정 방법에 대한 연구를 수행하십시오. – hotpaw2

+0

저는 몇 달 전부터 이것을 시도 해왔고, 어떤 피치 감지 코드도 작동시키지 못했습니다. –

+1

알려진 주파수 사인파를 입력 버퍼에 넣고 각 단계를 확인하여 코드를 디버깅하십시오. – hotpaw2

답변

2

나는 당신이 의심 반환 (a) FFT 이전에 적절한 window function을 적용하지 못하거나 (b) 큰 DC 구성 요소가있는 경우. 이것은 0 Hz에서 큰 (아마도 spectral leakage에 의한) 피크가 생길 것입니다. 스펙트럼 배열을 인쇄/플로팅하여이를 확인할 수 있습니다.

는이 문제를 해결하려면 다음

  • 는 FFT 이전에 적절한 윈도우 함수 (예를 들어, Hann)를 적용

  • 변화하여 피크 찾기 루프는 빈 0, 예를 들어, 위의 어딘가에 시작되도록

    for (int i = PEAK_MIN; i < BUFFER_SIZE/2 + 1; i++) { ...

+0

나는이 모든 시도를 everytime 시도했다. –

2

autocorrelation 방법을 이용하여 음성의 피치가 검출 할 수있는 매우 간단하지만, 계산적으로 집약적 인 방법이있다

const int PEAK_MIN = BUFFER_SIZE/1024;

. 왜 기타에 적용되지 않을지 나는 볼 수 없다! 그러나 하나 이상의 기본 주파수가있을 때 그것은 어려움을 겪을 것입니다. 나는 그것을 처리하는 알고리즘을 알고 있지 않다.

적어도 3 피치주기를 충당하기에 충분한 샘플을 채취해야합니다. 그런 다음 신호를 자동 상관합니다 (Autocorrelation은 효율적으로 performed with an FFT 일 수 있습니다).

당신은 자신의 자기 상관 신호가 있습니다. 가장 큰 피크를 지연 0에서 찾을 수 있습니다. 두 번째로 높은 피크가 피치가되어야합니다.

자기 상관 전에 해밍 창과 같은 것을 사용하여 입력 신호를 윈도 우잉함으로써 더 나은 결과를 얻을 수 있습니다.

Praat의 Paul Boersma는 아직까지 more accurate method of pitch detection으로 나타났습니다.

기본적으로 그의 구성표를 사용합니다. 창 함수의 자동 상관을 취한 다음 나중에 사용하기 위해 저장합니다. 다음으로 입력 신호를 윈도우합니다. 신호를 자동 상관하십시오. 이제 창 함수의 자기 상관 함수로 나눕니다. 마지막으로 가장 높은 피크를 선택하고 지연 0에서의 오프셋은 피치 검출에 대한 샘플 수입니다.

최상의 결과를 얻으려면 자기 상관 피크를 보간해야한다는 점에 유의하십시오. 나는 개인적으로 파라볼 릭 보간법을 사용했고, 내가 얻은 정확도 향상은 엄청났다.포물선 보간은 매우 간단합니다 : KB 국민 은행이 식별 한 자기 상관 피크와 kA 미만 후 그와 KC 샘플 전에 자동 상관 샘플입니다

void ParabolicInterpolation(const float kA, const float kB, const float kC, float& p, float& m) 
{ 
    p = 0.5f * ((kA - kC)/(kA - (2.0f * kB) + kC)); 
    m = (0.25f * (kA - kC) * p); 
} 

합니다.

편집 : 위의 방법은 고조파 제품 스펙트럼 (Check the start of this presentation)라는 기본 주파수를 계산하는 또 다른 정말 간단한 방법이 제공 정밀도의 종류를 필요로하지 않는 경우. 기본적으로 FFT로 시작합니다. 크기 스펙트럼으로 변환합니다. 마지막으로 2x, 3x 및 4x를 다운 샘플링합니다. 그런 다음 샘플을 함께 곱합니다. 가장 큰 피크는 기본 빈도에 의해 결정됩니다. 그러나 이것은 귀하의 FFT 해상도에 의해 심각하게 제한됩니다.

희망 하시겠습니까?

관련 문제