5

私はAndroidAPIのAudioRecord機能をいじり回していて、それでいくつかの奇妙な振る舞いを見つけました。

背景情報:私の電話はHTCIncredibleです。エミュレーターでAndroid開発用のEclipseプラグインを使用しています。ターゲットプラットフォームまたはOSは2.2です...それは私の電話が使用しているものだからです。

いくつかのコード:

bufferSize = AudioRecord.getMinBufferSize(FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, FREQUENCY, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);

これは、AudioRecordAPIをセットアップするために使用するコードです。さて、エミュレーターの場合、それが機能するためにFREQUENCYを8000に設定するのが好きです。バッファサイズ640で戻ってきます。私が44100を使用している電話の場合、ここでの1つの問題は、ウェーブの結果のPCMデータが8ビットの符号付きウェーブのように見えることです。-127から128までの値を取得します。この値AudioFormat.ENCODING_PCM_16BITは別の値を生成すると思いました。

音声をスレッドで処理します。

public void run() {
  while(isRecording) {
    audioRecord.startRecording();
    byte[] data = new byte[bufferSize];
    audioRecord.read(data, 0, bufferSize);
    listener.setData(data);
    handleData(data);
  }
  audioRecord.release();
}

を使用して、対応するウェーブをリアルタイムでグラフィカルに表示する方法がありSurfaceViewます。MICからのノイズが多いようです。このノイズは、エミュレーターと電話からも発生します。ある種のフィルターを介してデータを実行する必要がありますか?このデータを使用して、波をいじくり回すための楽しいFFTなどを計算したいと思います。しかし、私はどうにかしてノイズを減らす必要があります。

他の誰かもこれを経験していますか?誰かが解決策を持っていますか?

私はあなたの時間と応答に感謝します、ありがとう、dk

4

4 に答える 4

12

「AudioFormat.ENCODING_PCM_16BIT」ストリームからバイトを読み取ると、実際には各サンプルの上位バイトと下位バイトの両方が 2 つの連続したバイトとして提供されます。これは、各バイトを (実際の半分のサンプルではなく) サンプルとして使用すると、非常にノイズが多いように見えます。また、最初のバイトの署名が正しくありません (リトル エンディアン順です)。

意味のあるデータをストリームから取得するには、short 経由で読み取ります。

public void run() {
  while(isRecording) {
    audioRecord.startRecording();
    short[] data = new short[bufferSize/2];
    audioRecord.read(data, 0, bufferSize/2);
    listener.setData(data);
    handleData(data);
  }
  audioRecord.release();
}
于 2011-11-30T04:43:26.237 に答える
9

この質問が出されてからしばらく経ちましたので、回答がこれ以上関係があるかどうかはわかりません。

-127 から 128 までの値を取得している理由は、それぞれが符号付き 8 ビット数を保持するバイト配列を読み取っているためです。16 ビット オーディオの場合は、short の配列に読み込みます。

騒音問題については、どうしようもありません。

于 2011-06-28T09:34:59.067 に答える
3

少しでもお役に立てるかもしれません。しかし、私はあなたと同じ状況にあるので、私の経験についてしかお話しできません。

次のように、デバイスの優先 sampleRate を取得できると思います。

int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);

16Bit エンコーディング モードは、AudioRecord で動作する唯一のモードです。8Bit のような出力が得られる理由がわかりません (右?)。多分誰かが知っています。

また、取得したバイトから振幅を引き出す方法もわかりませんが、これを行いましたか?

最後に、次のように定期的なリスナー関数を使用する必要があると思います。

int sampleRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_SYSTEM);
int channelMode = AudioFormat.CHANNEL_IN_MONO;
int encodingMode = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelMode, encodingMode);

AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelMode, encodingMode, bufferSize);

recorder.setPositionNotificationPeriod(intervalFrames);
recorder.setRecordPositionUpdateListener(recordListener);
recorder.startRecording();

private RecordListener recordListener = new RecordListener();
private class RecordListener implements AudioRecord.OnRecordPositionUpdateListener {
    public void onMarkerReached(AudioRecord recorder) {
        Log.v("MicInfoService", "onMarkedReached CALL");
    }

    public void onPeriodicNotification(AudioRecord recorder) {
        Log.v("MicInfoService", "onPeriodicNotification CALL");
    }
}

ここには、私が答えることができない 2 つの大きな質問があり、自分自身の答えも知りたいと思っています。

  1. intervalFrames として何を設定する必要がありますか?
  2. リスナーメソッドが呼び出されないのはなぜですか?

もっとお役に立てれば幸いです。

于 2011-01-24T15:58:27.560 に答える
2

このオープン ソース プロジェクトには、音声データを取得して分析を試すのに役立つヘルパー クラスが多数用意されています。

https://github.com/gast-lib/gast-lib

AsyncTaskがあります

AudioRecorderを制御するものがあります

単純な周波数推定アルゴリズムも備えています

于 2012-06-07T12:42:34.573 に答える