Swift3 通过麦克风(AVAudioPCMBuffer和FFT)查找平均语音频率/范围

Swift3 通过麦克风(AVAudioPCMBuffer和FFT)查找平均语音频率/范围,swift3,fft,frequency-analysis,avaudioengine,avaudiopcmbuffer,Swift3,Fft,Frequency Analysis,Avaudioengine,Avaudiopcmbuffer,我试图找出一个人对着麦克风说话时声音的平均频率或范围。它不必是实时的。到目前为止,我的方法是使用AVAudioEngine和AVAudioPCMBuffer,获取缓冲区数据并将其转换为FFT inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in self.recognitionR

我试图找出一个人对着麦克风说话时声音的平均频率或范围。它不必是实时的。到目前为止,我的方法是使用AVAudioEngine和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数据,打印结果如下:

然而,这不可能是正确的赫兹。是我说的,平均男声的频率范围是85到180赫兹。我只是不知道接下来该怎么办


目标是当用户通过麦克风讲话时,找到音频的平均频率或范围。非常感谢你的帮助

FFT幅度是一种频谱频率估计器(对许多语音基音不起作用),而不是基音检测/估计算法。尝试使用基音估计算法,即使人声谐波/泛音序列具有更高的频谱功率,该算法也能更好地检测基音基音。

两个主要问题:(1)要测量的量是语音的基音基音-这是(或多或少)复杂声音的基音频率(复杂的是,它包含许多不同频率的分量)和(2)FFT不会直接给出频率测量值-上面的int eh代码实际上是在生成功率谱的估计值-如果绘制此图,您应该会看到一个频谱(幅度与频率)。请参阅用于确定频谱中最大峰值频率的伪代码-请注意,这不一定是基音,甚至不是基音,但这是一个起点…非常感谢@PaulR!!我将花一些时间研究您的链接答案。感谢@hotpaw2!!我将花更多时间阅读基音估计算法。