人の声がマイクに向かって話すときの平均周波数または範囲を把握しようとしています。リアルタイムである必要はありません。これまでの私のアプローチは、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データを返すと思う、印刷は次のようになります。しかし、これは正しいヘルツすることはできません
。それは私が話していたもので、男性の声は平均85〜180Hzです。私はここからどこに行くのか分かりません。
目標は、ユーザーがマイクを通して話すときの頻度平均または範囲を見つけることです。どんな助けでもありがとう!
2つの大きな問題点:(1)測定したい音量は、ボイスのピッチ*です。これは複雑なサウンドの基本周波数です(多かれ少なかれ、さまざまな周波数のコンポーネントを含んでいます)、そして(2)FFTは直接周波数測定値を与えません - あなたが実際に*パワースペクトルの推定値を生成している上のコード - もしプロットすれば、スペクトル(振幅対周波数)が見えます。 –
スペクトルの最大ピークの周波数を決定するための擬似コードについては、[この回答](http://stackoverflow.com/a/7675171/253056)を参照してください - これは必ずしもピッチではなく、しかしそれは出発点です... –
ありがとうございます@ポール!私はあなたのリンクされた答えにいくつかの時間を費やすでしょう。 – robinyapockets