Android 2.2のマイクからの記録中の奇妙な歪み
-
30-09-2019 - |
質問
マイクからオーディオを記録するアプリケーションがあり、その後、オーディオでリアルタイムでいくつかの後処理を実行するので、使用する必要があります。 AudioRecord
標準の代わりにクラス MediaRecorder
. 。録音のための私のコードは次のとおりです。
DataOutputStream dataOutputStreamInstance = new DataOutputStream(bufferedStreamInstance);
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
int bufferSize = AudioRecord.getMinBufferSize((int)sampleRate, channelConfiguration, DEFAULT_AUDIO_ENCODING) * 2;
short[] microphoneBuffer = new short[bufferSize];
float[] processingBuffer = new float[bufferSize];
short[] outputBuffer = new short[bufferSize];
AudioRecord microphoneRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
microphoneRecorder.startRecording();
while(isRecording) {
synchronized(mutex) { ... check for pause condition, wait, etc. ... }
int numSamplesRead = microphoneRecorder.read(microphoneBuffer, 0, bufferSize);
// Convert 16-bit short data to floating point
getFloatingPointBufferFromPcmData(microphoneBuffer, processingBuffer, bufferSize);
doProcessingStuff(processingBuffer, bufferSize);
if(numSamplesRead == AudioRecord.ERROR_INVALID_OPERATION) {
throw new IllegalStateException("read() returned AudioRecord.ERROR_INVALID_OPERATION");
}
else if(numSamplesRead == AudioRecord.ERROR_BAD_VALUE) {
throw new IllegalStateException("read() returned AudioRecord.ERROR_BAD_VALUE");
}
try {
// Dump the output to the target file in 16-bit short format
getShortPcmBufferFromFloatingPointData(processingBuffer, outputBuffer, bufferSize);
for(int bufferIndex = 0; bufferIndex < numSamplesRead; bufferIndex++) {
dataOutputStreamInstance.writeShort(outputBuffer[bufferIndex]);
}
}
catch(Exception e) {
Log.e("MyApp", "Error while writing audio data to file: " + e.getMessage());
e.getStackTrace();
}
}
microphoneRecorder.stop();
上記のコードは正常に動作し、実際にデバイスからオーディオを録画することができ、自分の声などが聞こえます。問題は、数秒後に、信号全体がown死するまで非常に奇妙な歪みのパターンが出現し始めたことです。これは、マイクの上にテープを置き、アプリを1分ほど記録させることによって、私が作った沈黙の録音のスクリーンショットです。
元のウェーブファイルは次の場合があります ここからダウンロードしました.
問題は間違いなくです いいえ 私の効果の処理コードのために、私はそれをコメントアウトしようとしたので、両方の場合に同じ結果を取得しました。私は他のコードや同様の問題を経験しているかもしれないが何も見つけていない人のためにWebを精査しました。
解決 3
BAH、実際には問題はAndroidの障害ではありませんでした。これは、RAW PCMデータをWAV形式に変換するために使用していたソフトウェアによって引き起こされました。アームチップはエンディアンが大きく、波がリトルエンディアンであるため、エンディアン変換にはある程度のエラーがあります。生のPCMファイルをAudacityで開いてみようとしたとき、それらはうまく見えました。
他のヒント
Android SDKはまったく知りませんが getFloatingPointBufferFromPcmData
と getShortPcmBufferFromFloatingPointData
素敵な命名規則にもかかわらず、標準のAPI関数のように見えないでください。 :)
これらを自分で書きましたか?おそらく、彼らは共有状態を使用しており、ループの反復全体で結果を蓄積していますか?これらがあなたの実装である場合は、これらのコードを共有して、実際の問題を特定するのに役立つようにしてください。
また、PCMデータを間違った形式(ビット数、エンディアンネス数)で書き出し、オーディオエディターが異なる形式に従ってデータを解釈している可能性もあり、誤ってデコードされたオーディオデータを誤ってデコードしたように見えます。いくつかの蓄積効果が発生しています。
これらの問い合わせのいずれも問題を解決することに導かれない場合、次の推奨事項は、whileループで単一のインスタンスを使用するのではなく、各ループイテレーションの新しいマイクロフォーナバッファインスタンスを作成することです。
繰り返しますが、私はAndroid SDKの専門家ではないので、これらは、ほぼすべての種類のAPIとその実装の詳細を扱う長年の経験から生じる一般的なアドバイスです。
それがあなたの問題の診断に役立つことを願っています!
沈黙の中で、自動ゲイン制御が理由を超えて入力ゲインを増加させ、「何か」を見つけようとしている(そしてもちろんノイズフロアを見つける)ことを試みているかもしれません。
PCスピーカーを優れたオーディオ周波数sinusoidを再生するように設定するとどうなりますか?ノイズがまだ上がっていますか、それとも正弦波を記録し続けますか?