9

AudioRecordクラスの使用に問題があります。記録したデータをバッファに保存したいのですが、それを実現するための適切な方法がわかりません。私は多くの例を経験しましたが、それらのほとんどは複雑で、多くの異なるアプローチを表しています。簡単な説明を探しています。

プロジェクトのオーディオ設定は次のとおりです。

int audioSource = AudioSource.MIC;
int sampleRateInHz = 8000;
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);

short[] buffer = new short[bufferSizeInBytes];

AudioRecord audioRecorder = new AudioRecord(audioSource,
                                            sampleRateInHz, 
                                            channelConfig, 
                                            audioFormat, 
                                            bufferSizeInBytes);

記録関数を作成しようとしています:

public void Recording() {
    audioRecorder.startRecording();
    ...
    audioRecorder.stop();
    audioRecorder.release();
}

.read(short [] audioData、int offsetInShorts、int sizeInShorts)関数を使用することになっていることを知っています。そして、ここから私の問題が始まります。audioDataバッファがどのように機能するかわかりません-関数が記録されたサンプルをaudioDataに入れると思います。データが完全にいっぱいになるとどうなりますか?一番早い位置から書き直し始めますか?もしそうなら、私は収集したすべてのサンプルを別の場所にコピーする必要があると思います。それは別の質問を提起します-.read(...)関数バッファがすでにいっぱいであるかどうかをどのように確認できますか?時間を測定してバッファの内容をコピーする必要がありますか、それともそれに到達する別の方法がありますか?また、記録操作全体のスレッドを作成する必要がありますか?

1つのトピックで非常に多くの質問をしてすみません:)

4

1 に答える 1

4

あなたの質問に答えます::

recorder.read(...) は、必ずしもデータをまったく読み取るとは限りません。read の呼び出しの間に短い時間 (たとえば 50ms) 一時停止するようにループを書き直す必要があります。また、バッファにデータが入るまでバッファをキューに入れるべきではありません。また、バッファーがいっぱいではない可能性があるため、おそらくバイト数のカウントを維持するデータ構造を使用する必要があります。ByteBuffer が良い候補として思い浮かびます。読み取りループでバイトを詰め込むことができ、十分にいっぱいになったら、送信のためにキューに入れ、別のものを開始します。

もちろん、ループするためのスレッドを作成する必要があります。以下のコードに示すように。

適切なエラー チェックを行う記録ループの修正版を次に示します。Queue<ByteBuffer>の代わりに a を使用しますQueue<byte[]>

private void startRecording() {

    recorder.startRecording();
    isRecording = true;
    recordingThread = new Thread(new Runnable() {

        @Override
        public void run() {
            bData = ByteBuffer.allocate(BufferElements);
            bbarray = new byte[bData.remaining()];
            bData.get(bbarray);
            while (isRecording) {

                int result = recorder.read(bbarray, 0, BufferElements);
                System.out.println("READ DATA");
                if (result > 0) {
                    qArray.add(bData);

                    --your stuffs--
                    bData = ByteBuffer.allocate(BufferElements);
                } else if (result == AudioRecord.ERROR_INVALID_OPERATION) {
                    Log.e("Recording", "Invalid operation error");
                    break;
                } else if (result == AudioRecord.ERROR_BAD_VALUE) {
                    Log.e("Recording", "Bad value error");
                    break;
                } else if (result == AudioRecord.ERROR) {
                    Log.e("Recording", "Unknown error");
                    break;
                }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
    }, "AudioRecorder Thread");
    recordingThread.start();
}

もちろん、どこかに電話する必要があります。そうしrecorder.startRecording()ないと、データを取得できません。

実際のサンプルについては、この例をご覧ください。

于 2012-11-21T12:01:32.243 に答える