7

iPhone 용 Demetri의 Pitch Detector 프로젝트를 구현했으며 두 가지 문제를 해결했습니다. 1) 어떤 종류의 배경 소음이라도 바나나를 읽는 주파수를 보내고 2) 낮은 주파수의 소리는 올바르게 핏치 않고 있습니다. 나는 조정에 내 기타를 시도하고 높은 문자열 일 동안 - 튜너가 제대로iPhone에서 FFT를 사용하여 배경 잡음을 무시하고 낮은 피치를 찾습니다.

피치 감지 코드는 RIOInterface.mm에 위치하고 있으며, 이런 식입니다 낮은 E.을 ... 식별 할 수

// get the data 
AudioUnitRender(...); 

// convert int16 to float 
Convert(...); 

// divide the signal into even-odd configuration 
vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2); 

// apply the fft 
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD); 

// convert split real form to split vector 
vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2); 

라고 Demetri는 다음과 같이 '지배적 인'주파수를 결정하기 위해 계속 : 시작하기

float dominantFrequency = 0; 
int bin = -1; 
for (int i=0; i<n; i+=2) { 
    float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]); 
    if (curFreq > dominantFrequency) { 
     dominantFrequency = curFreq; 
     bin = (i+1)/2; 
    } 
} 
memset(outputBuffer, 0, n*sizeof(SInt16)); 

// Update the UI with our newly acquired frequency value. 
[THIS->listener frequencyChangedWithValue:bin*(THIS->sampleRate/bufferCapacity)]; 

, 나는 내가 저역 통과 필터를 적용 할 필요가 믿고 ...하지만 나는 FFT 전문가 아니에요하지 vDSP 함수에서 반환 된 데이터에 대해 정확히 어디서 어떻게 처리해야하는지 에스. 낮은 주파수에서 코드의 정확도를 높이는 방법을 모르겠습니다. 지배적 인 주파수를 결정하는 다른 알고리즘이있는 것처럼 보이지만, Apple Accelerate 프레임 워크가 반환 한 데이터를 사용할 때 올바른 방향으로 걷어차기를 찾으십시오.

UPDATE :

프레임 워크가 실제로 어떤 윈도우 기능이 가속화 할 수 있습니다. I 설정 I는 다음 vDSP_ctoz 기능 전에

vDSP_vmul(outputBuffer, 1, window, 1, transferBuffer, 1, windowSize); 

를 삽입하여 적용이

windowSize = maxFrames; 
transferBuffer = (float*)malloc(sizeof(float)*windowSize); 
window = (float*)malloc(sizeof(float)*windowSize); 
memset(window, 0, sizeof(float)*windowSize); 
vDSP_hann_window(window, windowSize, vDSP_HANN_NORM); 

같은 기본 창. 그런 다음 나머지 코드를 outputBuffer 대신 'transferBuffer'를 사용하도록 변경합니다. 그러나 지금까지 최종 피치 추측에는 큰 변화가 없었습니다.

+0

내가 몇 년 전이 물건을 가지고 노는 것을 기억하는 두 가지 사실 : 미리 결정된 양에서 원시 입력 데이터를 빼는 것만으로 배경 음향에 대한 스켈치 레벨을 설정할 수 있습니다 (그림에서 확인할 때까지는 추측 할 수 있음). 좋은 알고리즘을 벗어남), 0보다 낮은 값을 0으로 설정하고 주파수를 낮추면 어떤 이유로 기억이 안나고 소리가 큰만큼 등록하지 않으므로 비교하기 전에 저주파수 볼륨을 기하 급수적으로 확장해야합니다 더 높은 우세 주파수. –

+0

FFT를하기 전에 적절한 창 기능을 적용하지 않는 것 같습니다. 따라서 파워 스펙트럼에 인공물이 많아서 피치 감지에서 어떤 종류의 시도도 엉망이 될 것입니다. –

+2

다음은 비슷한 대답으로 거의 중복되는 질문입니다 : http://stackoverflow.com/questions/4227420/matlab-missing-fundamental-from-an-fft – hotpaw2

답변

7

피치가 최대 크기 빈도 (가속도 프레임 워크의 FFT가 사용자에게 직접 줄 수있는 것)와 동일하지 않습니다. 따라서 모든 피크 주파수 검출기는 피치 추정에 신뢰할 수 없습니다. 로우 패스 필터는 음이 빠지거나 매우 약한 기본 음향 (일부 음색, 피아노 및 기타 사운드에서 공통) 및/또는 스펙트럼에서 강력한 오버톤이 많은 경우 도움이되지 않습니다.

음악 사운드의 와이드 밴드 스펙트럼 또는 스펙트로 그래프를보고 문제가 표시됩니다.

일반적으로 음악 피치를 더 안정적으로 추정하려면 다른 방법이 필요합니다. 이들 중 일부는 자기 상관법 (AMDF, ASDF), Cepstrum/Cepstral 분석, 고조파 곱 스펙트럼, 위상 보코더 및/또는 RAPT (Pitch Tracking을위한 강력한 알고리즘) 및 YAAPT와 같은 복합 알고리즘을 포함합니다. FFT는 위의 방법 중 일부의 하위 부분으로 만 유용합니다.

+0

Thanks @ hotpaw2. 나는 당신이 여기서 열거 한 기술들을 파헤쳐 야 할 것입니다. 제안 해줘서 고마워. –

+0

다른 피치 추정 방법에 대한 설명은 내 블로그에 있습니다. http://www.nicholson.com/rhn/dsp.html#1 – hotpaw2

3

적어도 FFT를 계산하기 전에 window function을 시간 도메인 데이터에 적용해야합니다. 이 단계가 없으면 파워 스펙트럼에 피치 정보를 추출하려는 시도를 방해하는 인공물이 포함됩니다 (spectral leakage 참조).

간단한 Hann (aka Hanning) 창으로 충분할 것입니다.

+2

좋은 답변과 멋진 아바타 이미지 : D – jarryd

+0

정말 동의 할 수 없습니다. 이 코멘트. 아날로그 신호를 샘플링하기 전에 창 필터를 적용해야합니다. 일단 샘플링되면 (예 : 마이크 또는 WAV 형식으로 녹음 된 경우), 다른 효과를 찾고있는 경우를 제외하고는 아무것도 필터링 할 필요가 없습니다. –

+0

@ ZeJibe : 나는 당신이 [ 창 기능] (https://en.wikipedia.org/wiki/Window_function)을 사용하고 [앤티 앨리어싱 필터] (https://en.wikipedia.org/wiki/Anti-aliasing_filter)를 사용합니까? –

1

샘플 빈도 및 블록 크기는 어떻게됩니까? Low E는 약 80Hz이므로 캡처 블록이이 주파수에서 많은 사이클을 캡처 할만큼 충분히 길어야합니다. 이것은 푸리에 변환 (Fourier Transform)이 주파수 스펙트럼을 각 Hz 폭의 빈 (bin)으로 나누기 때문입니다. 44시에 표본 추출.예를 들어, 각 bin은 44100/1024 = 43.07Hz 와이드가 될 것입니다. 따라서 낮은 E는 두 번째 빈에 있습니다. 여러 가지 이유로 (스펙트럼 누출 및 유한 시간 블록의 특성과 관련하여) 실제로 FFT 결과의 처음 3 ~ 4 개 데이터를 극단적 인 의심으로 고려해야합니다.

샘플 속도를 8kHz로 떨어 뜨리면 동일한 블록 크기로 7.8125Hz의 빈을 제공합니다. 이제는 낮은 E가 10 번째 또는 11 번째 빈에있게됩니다. 훨씬 더 좋습니다. 더 긴 블록 크기를 사용할 수도 있습니다.

그리고 Paul R points out으로, 스펙트럼 누출을 줄이기 위해 반드시 창을 사용해야합니다.

+0

나는 22050과 44100을 모두 시도했다. 나는 또한 'blocksize'금액을 얻을 때까지 각 콜백의 데이터를 저장하는 일종의 순환 버퍼에서 1024, 2048 및 4096의 블록 크기를 시도했다. 나는 fixed blocksize가 주어지면 샘플링 속도를 낮추면 조금 더 넓은 bin을 줄 것이고 낮은 E를 듣기는 쉽다는 생각을 이해합니다.불행하게도, 내가 알아 차 렸던 것은 295Hz 부근으로 내려 가면 튜너는 883과 901과 같은 숫자를 읽기 시작한다는 것입니다. 실제 톤의 2와 3의 배수와 매우 비슷합니다. –

+0

나는 앉아있는 다른 iPhone에서 톤을 생성합니다. 나는 소리를 내며 소리가 나기 시작했다. 튜너는 정확한 값을 잃어 버리고 다른 주파수로 빠지기 시작한다. 반드시 2 ~ 3의 배수가 아니야. 내가 찾고있는 근본적인 어조. –

+0

더 긴 블록 크기는 모든 피치 추정을위한 좋은 시작이지만 FFT 진폭 피크는 기본 주파수가 없거나 약한 모든 사운드 (마이크 롤오프로도)에서 작동하지 않습니다. – hotpaw2

1

iPhone의 주파수 응답 기능이 100 - 200Hz 미만으로 떨어집니다 (예 : http://blog.faberacoustical.com/2009/ios/iphone/iphone-microphone-frequency-response-comparison/ 참조).

낮은 기타 문자열의 기본 모드를 감지하려는 경우 마이크가 필터 역할을하여 관심있는 주파수를 억제 할 수 있습니다. fft 데이터를 사용하려면 몇 가지 옵션이 있습니다 당신은 얻을 수 있습니다 - 당신은 당신이 볼 수있는 모든 것이 첫 번째 모드가 더 높은 모드보다 낮은 경우에도 (즉, 첫 번째 모드를 조정 토글을 가지고 감지하려고하는 메모 주위의 주파수 도메인에서 데이터 창을 수 있습니다 문자열을 입력하고이 모드로 두십시오).

또는 주파수 도메인에서 이미 주파수 도메인 데이터를 가지고 있기 때문에 시간 도메인에서 또는 더 쉽게이 작업을 수행 할 수 있습니다. 매우 간단한 시간 영역 저역 통과 필터는 시간 이동 평균 필터를 수행하는 것입니다. 매우 간단한 주파수 도메인 저역 통과 필터는 fft 크기에 저주파 범위의 1과 높은 주파수의 선형 (또는 단계) 램프가있는 벡터를 곱하는 것입니다.

관련 문제