質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

4445閲覧

[swift]録音データからの時系列での周波数の算出ができない

makoto-

総合スコア9

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2016/09/01 01:13

編集2016/09/01 02:04

###前提・実現したいこと
録音したPCMデータから単位時間ごとに周波数算出したいと考えております。

###発生している問題・エラーメッセージ
以下のようになコードを作成しまして1buffer単位の最大周波数を算出したいと考えておりますが
想定しているデータを違う結果が出力されてしまいます。

イメージ説明

###該当のソースコード

swift

1 //オーディオデータの取得 2 let audioFile = try AVAudioFile(forReading: url) 3 // オーディオのサンプルレートの取得 4 let sampleRate = audioFile.fileFormat.sampleRate 5 6 let fft = EZAudioFFTRolling.fftWithWindowSize(fftWindowSize, historyBufferSize: fftWindowSize , sampleRate: Float(sampleRate)) 7 8 //オーディオファイルから、PCMBufferにオーディオデータを取得して、フーリエ変換した周波数配列を求める 9 let perCount: Int = 2 10 let totalSampleFrames = Int(audioFile.length) 11 // 取得したい周波数の配列 12 var frequencies = [Float]() 13 14 15 for _ in 0 ..< totalSampleFrames { 16 17 // バッファーの取得 18 let buffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat, frameCapacity: AVAudioFrameCount(totalSampleFrames)) 19 20 // 一部取得 21 try audioFile.readIntoBuffer(buffer, frameCount: AVAudioFrameCount(perCount)) 22 let bufferSize = UInt32(buffer.frameLength) 23 // FFT 24 fft.computeFFTWithBuffer(buffer.floatChannelData[0], withBufferSize: bufferSize) 25 26 frequencies.append(fft.maxFrequency) 27 } 28 // 結果の出力 29 for _ in 0 < frequencies.count { 30 print("周波数:\(fft.maxFrequency)") 31 } 32 ....

上記FFTの結果をグラフ出力
fft.maxFrequency // → 緑のライン
buffer.floatChannelData[0].memory // → 赤いライン

###補足情報(言語/FW/ツール等のバージョンなど)
Swift 2.1
XCode 7
EXAudioを使用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

issei.

2016/09/01 01:53

グラフ出力はどのタイミングでやっていますか?都度出力です?それとも、ファイルに書き出して後で出力していますか?
makoto-

2016/09/01 02:04

issei様 閲覧いただきありがとうございます。 グラフですが実際には動作を確認するためにExcelで結果をcsvにしてそれをグラフにしておりますのでプログラムでは出力しておりません。。 ですのでプログラム上で必要なのはmaxFrequencyの時系列データのみとなります。 ※わかりにくかったのでコードを追加させていただきました。 よろしくお願いいたします。
issei.

2016/09/01 02:12

ありがとうございます。それなら、出力の時間スケールがずれていることはなさそうです。むしろ、FFT取っている範囲の幅がバッファーサイズで200前後だから、高周波の範囲の後ろ側200個分は最大値が大きくなるだけでは?
makoto-

2016/09/01 02:39

こちらこそありがとうございます。現状 fft.computeFFTWithBuffer(buffer.floatChannelData[0], withBufferSize: bufferSize) の関数でまとめて処理をしているのですが後ろ200個分....のくだりがよく理解できておりません。申し訳ございませんがご教授いただけますでしょうか?
issei.

2016/09/01 02:53

buffer.floatChannelData[0]を先頭に、bufferSize個のデータでFFTをやっていると思います。まず、bufferSize個は200個前後なのでは?
makoto-

2016/09/01 03:29

現在のbufferSizeが1が入っておりまして,256に設定させていただき動作確認しました。ですが最大周波数は0で全域で算出されませんでした。
makoto-

2016/09/01 04:39

ちなみにBuffersizeですが1,2,100,200,256,512,1024を入れても同様に周波数が算出されませんでした。
issei.

2016/09/01 05:06

なるほど。すみません誤解しておりました。buffer1つに対して時系列データがあるという認識で正しいでしょうか?
makoto-

2016/09/01 05:35

bufferにデータがある認識です。issei様のご指摘通りですとmaxfrepuencyは使えず、自作で計算しないといけないということでしょうか?
issei.

2016/09/01 06:13

はい。frequenciesの配列から最大値を計算するメソッドないしロジックが必要です。。
guest

回答1

0

ベストアンサー

現状ですと、fft.maxFrequencyの画面出力値を元に描画されています。
このままですと、totalSampleFramesごとに最新のFFTの最大周波数をひたすら出力してしまいます。
参考: http://cocoadocs.org/docsets/EZAudio/1.1.2/Classes/EZAudioFFT.html#//api/name/maxFrequency

画面出力する箇所を見直してみて下さい。
swiftの書き方を把握できていないので方針しか書けず申し訳ないのですが、こう直せば良いと思います。

swift

1 // 結果の出力 2 for _ in 0 < frequencies.count { 3 print("周波数:\(<frequenciesの値を1つずつ出力する>)") 4 }

投稿2016/09/01 05:33

編集2016/09/02 00:02
issei.

総合スコア326

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

makoto-

2016/09/01 06:17

サンプルありがとうございます。 いただきました記載ですと frequencies.append(fft.maxFrequency) で登録した内容になってしまいますがよろしかったでしょうか? 推測なのですがbufferには音楽データの配列が入っている気がします。 最終的に処理としましては 1ms → 17Khz 2ms → 19Khz 3ms → 0Khz というのを想定していたのですが現状は 1ms → 17Khz 2ms → 19Khz 3ms → 19Khz といった形になっていると思っております。
issei.

2016/09/01 06:22

「frequencies.append(fft.maxFrequency) で登録した内容」で、認識あっています。値を突っ込み終わった配列から最大値を選ぶだけです。
makoto-

2016/09/01 21:16

返信ありがとうございます。 そうしますと全録音時間の最大周波数になってしまいませんでしょうか? 取得したい内容としましては時間単位での最大周波数の時系列データなので、、、
issei.

2016/09/02 00:00

確かに。言われてみれば単位時間あたりの最大値が既に入っているので、愚直に出力すれば良いだけです
makoto-

2016/09/04 11:25

issei様。ご回答ありがとうございます。すごく勉強になりました。この方式ではわたしのやりたいことが検出出来なさそうなので別の方式を検討させていただきます。 いろいろとご助言ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問