AudioRecord (続
ええと、直前エントリにコメント頂いてる件についてフォローなエントリです。
以下な実装にしてみました、と書いた所
int bufferSize = AudioRecord.getMinBufferSize(this.getFrequency(), this.getChannelConfiguration(), this.getAudioEncoding()); AudioRecord recordInstance = new AudioRecord( MediaRecorder.AudioSource.MIC, this.getFrequency(), this.getChannelConfiguration(), this.getAudioEncoding(), 4 * bufferSize); short[] tempBuffer = new short[bufferSize];
以下なフォローを id:t-doi さんから頂きました。
- バッファサイズを 2 倍するのではなく tempBuffer のサイズをもっと小さく (1/4 とかそれ以下) した方が良い
- おそらくは AudioRecord も別 thread で動作しててバッファサイズが同一だと問題があるのではないか
- ActiveRecord が一杯になるのと tempBuffer への読み込みが同じになる
整理してみる
ええと、上記のコードが書いてある部分も一つの thread として動いてます。AudioRecord の read というメソドを使って、上記 tempBuffer な領域に音声なデータ列を読み込んで変換処理を、という形。読み込み処理の呼び出し部分では mutex な同期とかはしてません。
てか、こんな期待しちゃダメでしょ、ってツッコミ入りそうですが、AudioRecord の中で
- read メソド呼び出し時
- 音声データを内部バッファに投入する時
には同期をとって処理してるんだろう、と。(を
で、基本的に read 呼び出し時には
- mutex 取って
- 4 * bufferSize な (おそらくはリングバッファ) 領域から指定されたサイズをメソドに渡された配列にコピーしてコピー元のバッファの後始末
- mutex 手放す
ってコトをしてるのではと類推。音声データを取り込む時にも mutex を取って内部バッファに追加してるのだと見てます。
あと、AudioRecord の使い方については_このスレッド_を参考にしてるんですが、この例では AudioRecord のコンストラクタに渡すバッファサイズ (おそらくは AudioRecord が持つ内部バッファのサイズと類推) と read に渡すバッファサイズが同一になってます。
読み込んだ後の処理マターかと思うんですが、こうした形を取ってると buffer overflow なログが出力される頻度が増えまず。AudioRecord が持ってる内部バッファが溢れてるのだろう、と見ています。
あ、あと上記の処理を書いてる thread ですが、基本的に一つしか thread は kick されません。ので排他制御はしてないです。
N1 不具合
今日、N1 と HT-03A のサンプリングレートが異なる事を確認してます。変換エンジンでサンプリングレートの指定があるので、これが原因なのかも、と。
- NTT DoCoMo PRO series HT-03A (HTC Sapphire) Detailed Specs
- Google Nexus One US (HTC Dragon) Detailed Specs
上記のよれば HT-03A は 44.1kHz で N1 は 48kHz との事。サンプリングレートの変換に挑む方向だったりなんかして。
最後に
色々とフォローありがとうございます。> t-doi さん
正直申し上げて java は門外漢なのでいつも参考になります。