【问题标题】:Find Average Voice Frequency/Range through Microphone (AVAudioPCMBuffer and FFT)通过麦克风查找平均语音频率/范围(AVAudioPCMBuffer 和 FFT)
【发布时间】:2017-03-13 11:27:12
【问题描述】:

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

但是,这不可能是正确的 Hz。是我说话,平均男性声音的范围是 85 到 180 Hz。我只是不确定从这里去哪里。

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

【问题讨论】:

  • 两个主要问题:(1)您要测量的量是声音的音高 - 这是(或多或少)复杂声音的基本频率(复杂,因为它包含许多不同频率的分量),以及 (2) FFT 不会直接为您提供频率测量值 - 上面的 int eh 代码实际上是在生成 功率谱 的估计值 - 如果你绘制这个你应该看到一个频谱(幅度与频率)。
  • 请参阅this answer 获取用于确定频谱中最大峰值频率的伪代码 - 请注意,这不一定是音高,甚至不一定是基频,但它是一个起点...
  • 非常感谢@PaulR!我会花一些时间在您的链接答案上。

标签: swift3 fft frequency-analysis avaudioengine avaudiopcmbuffer


【解决方案1】:

FFT 幅度是一种频谱频率估计器(不适用于许多音高),而不是音高检测/估计算法。尝试使用音高估计算法,即使人声谐波/泛音系列具有更大的频谱功率,它也可以更好地检测基本音高。

【讨论】:

  • 谢谢@hotpaw2 !!我会花更多时间阅读音高估计算法。
猜你喜欢
  • 2018-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
相关资源
最近更新 更多