Найти среднюю частоту голоса / диапазон через микрофон (AVAudioPCMBuffer и FFT)
Я пытаюсь определить среднюю частоту или диапазон голоса человека, когда он говорит в микрофон. Это не должно быть в режиме реального времени. До сих пор мой подход состоял в том, чтобы использовать 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 Гц. Я просто не уверен, куда идти отсюда.
Цель состоит в том, чтобы найти среднее значение частоты или диапазон, когда пользователь говорит через микрофон. Большое спасибо за любую помощь!!!
1 ответ
Величина БПФ является оценщиком спектральной частоты (которая не работает для многих тембров голоса), а не алгоритмом обнаружения / оценки основного тона. Вместо этого попробуйте алгоритм оценки высоты тона, который может лучше определять основной тональный сигнал, даже если ряд вокальных гармоник / обертонов обладает большей спектральной мощностью.