私の Android Java アプリケーションは、オーディオ データを RAM に記録して処理する必要があります。これが、「MediaRecorder」ではなく「AudioRecord」クラスを使用する理由です(ファイルにのみ記録します)。
今までは、オーディオ データの "read()" によるビジー ループ ポーリングを使用していました。これはこれまでのところ機能していますが、CPU を固定しすぎています。2 つのポーリングの間に、100% の CPU 使用率を回避するためにスレッドをスリープ状態にしました。ただし、スリープの時間が保証されておらず、オーディオ スニペットが失われないようにセキュリティ時間を差し引く必要があるため、これは実際にはクリーンなソリューションではありません。これは CPU 最適化ではありません。並列実行スレッドには、できるだけ多くの空き CPU サイクルが必要です。
「OnRecordPositionUpdateListener」を使用して録音を実装しました。これは非常に有望であり、SDK ドキュメントによると正しい方法に見えます。すべてが機能しているように見えます (オーディオ デバイスを開く、データを read() するなど) が、Listner が呼び出されることはありません。
理由を知っている人はいますか?
情報: エミュレーターではなく、実際のデバイスで作業しています。Busy Loop を使用した録音は、基本的に機能します (ただし、満足はできません)。Callback Listener だけが呼び出されることはありません。
ここに私のソースコードからのスニペットがあります:
public class myApplication extends Activity {
/* audio recording */
private static final int AUDIO_SAMPLE_FREQ = 16000;
private static final int AUDIO_BUFFER_BYTESIZE = AUDIO_SAMPLE_FREQ * 2 * 3; // = 3000ms
private static final int AUDIO_BUFFER_SAMPLEREAD_SIZE = AUDIO_SAMPLE_FREQ / 10 * 2; // = 200ms
private short[] mAudioBuffer = null; // audio buffer
private int mSamplesRead; // how many samples are recently read
private AudioRecord mAudioRecorder; // Audio Recorder
...
private OnRecordPositionUpdateListener mRecordListener = new OnRecordPositionUpdateListener() {
public void onPeriodicNotification(AudioRecord recorder) {
mSamplesRead = recorder.read(mAudioBuffer, 0, AUDIO_BUFFER_SAMPLEREAD_SIZE);
if (mSamplesRead > 0) {
// do something here...
}
}
public void onMarkerReached(AudioRecord recorder) {
Error("What? Hu!? Where am I?");
}
};
...
public void onCreate(Bundle savedInstanceState) {
try {
mAudioRecorder = new AudioRecord(
android.media.MediaRecorder.AudioSource.MIC,
AUDIO_SAMPLE_FREQ,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
AUDIO_BUFFER_BYTESIZE);
} catch (Exception e) {
Error("Unable to init audio recording!");
}
mAudioBuffer = new short[AUDIO_BUFFER_SAMPLEREAD_SIZE];
mAudioRecorder.setPositionNotificationPeriod(AUDIO_BUFFER_SAMPLEREAD_SIZE);
mAudioRecorder.setRecordPositionUpdateListener(mRecordListener);
mAudioRecorder.startRecording();
/* test if I can read anything at all... (and yes, this here works!) */
mSamplesRead = mAudioRecorder.read(mAudioBuffer, 0, AUDIO_BUFFER_SAMPLEREAD_SIZE);
}
}