AudioRecord の使用に問題があります。
splmeterプロジェクトから派生したコードの一部を使用した例:
private static final int FREQUENCY = 8000;
private static final int CHANNEL = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private static final int ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private int BUFFSIZE = 50;
private AudioRecord recordInstance = null;
...
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, CHANNEL, ENCODING, 8000);
recordInstance.startRecording();
short[] tempBuffer = new short[BUFFSIZE];
int retval = 0;
while (this.isRunning) {
for (int i = 0; i < BUFFSIZE - 1; i++) {
tempBuffer[i] = 0;
}
retval = recordInstance.read(tempBuffer, 0, BUFFSIZE);
... // process the data
}
これは、HTC Dream と HTC Magic ではログの警告やエラーなしで完全に機能しますが、エミュレーターと Nexus One デバイスでは問題が発生します。
Nexus では、有用なデータが返されることはありません。リモートの友人にテストを行ってもらっているため、他の有用な情報を提供することはできません。
エミュレーター (Android 1.5、2.1、および 2.2) では、AudioFlinger から奇妙なエラーが発生し、AudioRecordThread でバッファー オーバーフローが発生します。また、UI の応答性が大幅に低下します (記録は UI とは別のスレッドで行われますが)。
私が間違っていることは明らかですか?Nexus One ハードウェアについて何か特別なことをする必要はありますか?
編集
問題を部分的に解決しました... AudioRecordのドキュメントには次のように書かれています:
public static int getMinBufferSize (int sampleRateInHz, int channelConfig, int audioFormat)
AudioRecord オブジェクトを正常に作成するために必要な最小バッファ サイズを返します。このサイズは、負荷がかかった状態でのスムーズな録音を保証するものではないことに注意してください。AudioRecord インスタンスが新しいデータについてポーリングされると予想される頻度に従って、より高い値を選択する必要があります。
だから私はバッファの長さを
private static final int BUFFSIZE = AudioRecord.getMinBufferSize(FREQUENCY, CHANNEL, ENCODING);
そして今、エミュレーターはうまく動作します。
しかし
ハードウェアはそうではありません。エミュレーターはその呼び出しから 640 の値を返しますが (1 秒あたり 12.5 ポーリングを行う)、8khz に基づいて、HTC ハードウェアは 4096 を返します! つまり、1 秒あたり約 2 回のポーリングと、0.5 秒の音声遅延です。さらに、Nexus One で同じ呼び出しを行うと、8192 が返されます。つまり、完全な 1 秒の遅延です。
それで終わったらいいのですが、HTCデバイスとすべてのエミュレーターが動作するようになったにもかかわらず、nexus oneはまだオーディオを返しません(まだ自分自身を持っていないので、適切なデバッグ情報を取得できません)。 (一部が他よりも遅れている場合でも)。
ここで何かひどく間違ったことをしていますか?