0

사람의 음성이 마이크에 대고 말하는 동안 평균 주파수 또는 범위를 파악하려고합니다. 실시간 일 필요는 없습니다. 지금까지는 AVAudioEngine 및 AVAudioPCMBuffer를 사용하여 버퍼 데이터를 가져온 다음 FFT로 변환하는 방법을 사용했습니다.마이크를 통해 평균 음성 주파수/범위 찾기 (AVAudioPCMBuffer 및 FFT)

inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in 
      self.recognitionRequest?.append(buffer) 

     let data = buffer.floatChannelData?[0] 
     let arrayOfData = Array(UnsafeBufferPointer(start: data, count: Int(buffer.frameLength))) 
     let fftData = self.performFFT(arrayOfData) 
} 




func performFFT(_ input: [Float]) -> [Float] { 

    var real = [Float](input) 
    var imag = [Float](repeating: 0.0, count: input.count) 
    var splitComplex = DSPSplitComplex(realp: &real, imagp: &imag) 

    let length = vDSP_Length(floor(log2(Float(input.count)))) 
    let radix = FFTRadix(kFFTRadix2) 
    let weights = vDSP_create_fftsetup(length, radix) 
    vDSP_fft_zip(weights!, &splitComplex, 1, length, FFTDirection(FFT_FORWARD)) 


    var magnitudes = [Float](repeating: 0.0, count: input.count) 
    vDSP_zvmags(&splitComplex, 1, &magnitudes, 1, vDSP_Length(input.count)) 

    var normalizedMagnitudes = [Float](repeating: 0.0, count: input.count) 

    vDSP_vsmul(sqrt(magnitudes), 1, [2.0/Float(input.count)], &normalizedMagnitudes, 1, vDSP_Length(input.count)) 

    vDSP_destroy_fftsetup(weights)  
    return normalizedMagnitudes 
} 


public func sqrt(_ x: [Float]) -> [Float] { 
    var results = [Float](repeating: 0.0, count: x.count) 
    vvsqrtf(&results, x, [Int32(x.count)]) 
    return results 
} 

는 내가 적절한 FFT 데이터, 인쇄는 다음과 같습니다 돌아 오는 것 같아 :

enter image description here

그러나이 올바른 Hz에서 수 없습니다. 그것은 나에게 말하기, 그리고 평균 남성 목소리의 범위는 85-180 Hz입니다. 나는 여기서 어디로 가야할지 모르겠다.

목표는 사용자가 마이크를 통해 말한 횟수에 대한 빈도 평균 또는 범위를 찾는 것입니다. 어떤 도움을 주셔서 너무 고마워요!

+0

두 가지 큰 문제 : (1) 측정하려는 양은 음성의 피치 *입니다. 복잡한 사운드의 기본 주파수 (다소 다른 주파수의 구성 요소를 포함한다는 점에서 복잡합니다)), 그리고 (2) FFT가 직접 주파수 측정을 제공하지 않습니다. 실제로 위의 코드는 * 파워 스펙트럼의 추정치를 생성합니다. * 이것을 플롯하면 스펙트럼 (진폭 대 주파수)이 나타납니다. –

+0

스펙트럼에서 가장 큰 피크의 주파수를 결정하기위한 의사 코드는 [this answer] (http://stackoverflow.com/a/7675171/253056)을 참조하십시오. 이것은 반드시 피치, 하지만 그것은 출발점입니다 ... –

+0

고마워요 @ 폴! 나는 당신의 연결된 대답에 시간을 할애 할 것입니다. – robinyapockets

답변

1

FFT 크기는 피치 검출/추정 알고리즘이 아니라 분광 주파수 견적 기 (많은 음 성 피치에서는 작동하지 않음)입니다. 보컬 하모닉/오버 톤 시리즈가 더 많은 스펙트럼 파워를 가지고 있더라도 기본 피치를 더 잘 감지 할 수있는 피치 추정 알고리즘을 사용해보십시오.

+0

감사합니다. @ hotpaw2 !! 피치 추정 알고리즘에 대해 더 많은 시간을 보냅니다. – robinyapockets