Unityで音声解析を行うとき,躓いた問題点を記録しておきます.
私は割と致命的な欠陥だと思っています.
しかしUnityを使い始めて日が浅いため私の知識不足なだけかもしれません.
「指定秒分録音して処理」ができない?
「1秒録音して処理」を行うプログラムを作ってみます.
Androidのマイクを使って録音する場合,AudioSourceを追加し,Microphoneを使ってAudioSource.clipに記録します.
このときマイク名,録音をループさせるか,録音時間,サンプリングレートの4つを指定します.
その後,AudioSouce.clip.GetDataを使ってAudioSourceに記録されたデータを取り出します.
float[] data;
AudioSource rec;
void Start () {
data = new float[44100]; //音声データを格納する配列
rec = GetComponent<AudioSource> (); //AudioSourceを初期化
rec.clip = Microphone.Start ("マイク名", true, 1, 44100); //録音開始
//次の録音ができるようになるまで待つ
while (Microphone.GetPosition("マイク名") <= 0) {
}
}
void Update () {
rec.clip.GetData (data, 0); //AudioSouceに記録されたデータを配列へ格納する
}
これでマイクで録音した音声データを取り出すことができるのですが,このプログラムでは「指定秒分録音して処理」はできません.
その理由は,Update関数が毎フレーム呼び出されるため1秒録音し終わる前の段階でAudioSourceに記録されたデータが取り出されてしまうからです.
実際に実行してみると分かりますが,明らかに1秒経たずにデータが取り出されています.(当然ですが…)
「リアルタイムで波形データを表示する」みたいなアプリを作る場合はこれでいいのでしょうが,今回はこれではダメです.
そこで録音が終了したタイミングで実行される関数はないかと探しましたが,それらしいものは見つからず,最終的には「Unityに指定秒分録音して実行する関数はない」というのが私の結論になりました.
コルーチンを使って無理やり指定秒間待たせて実行する
「Unityに指定秒分録音して実行する関数はない」というのが私の結論になりました.と書きましたが,できないで済めば苦労はしません.
なんとか,ややごり押し気味ではありますが,指定秒分録音して処理することができるようにしました.
bool isRec = true;
float[] data;
AudioSource rec;
void Start () {
rec = GetComponent<AudioSource> (); //AudioSourceを初期化
StartCoroutine ("SecRecording"); //コルーチンを実行
}
IEnumerator SecRecording () {
float[] data = new float[44100]; //音声データを格納する配列
//録音を繰り返す
while (isRec) {
rec.clip = Microphone.Start ("マイク名", false, 1, 44100);
yield return new WaitForSeconds (1.0f);
rec.clip.GetData (data, 0);
}
}
変更点をまとめます.
- 録音をループをwhile文で行うようにした
- yield returnを使って1秒間(録音時間分)待たせ,その後で処理を実行するようにした
これで厳密ではありませんが,指定秒分録音して処理を行うことができるようになりました.
他に何か方法があれば教えてください.