webRTC を使用して Android でエコー キャンセルを実行しようとすると問題が発生します。ほとんどの場合、ここに投稿されたプロジェクトに従っていますが、リモートデバイスから直接ストリーミングしようとしています。
/* Prepare AEC */
MobileAEC aecm = new MobileAEC(null);
aecm.setAecmMode(MobileAEC.AggressiveMode.MILD)
.prepare();
/*Get Minimum Buffer Size */
int minBufSize = AudioRecord.getMinBufferSize(HBConstants.SAMPLE_RATE,
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
AudioFormat.ENCODING_PCM_16BIT) ;
int audioLength=minBufSize/2;
byte[] buf = new byte[minBufSize];
short[] audioBuffer = new short[audioLength];
short[] aecOut = new short[audioLength];
/*Prepare Audio Track */
AudioTrack speaker = new AudioTrack(AudioManager.STREAM_MUSIC,
HBConstants.SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, audioLength,
AudioTrack.MODE_STREAM);
speaker.play();
isRunning = true;
/*Loop around and read incoming network buffer. PlayerQueue is a read LinkedBlockingQueue set elsewhere containing incoming network data */
while (isRunning) {
try {
buf = playerQueue.take();
/* Convert to short buffer and send to aecm*/
ByteBuffer.wrap(buf).order(ByteOrder.nativeOrder())
.asShortBuffer().get(audioBuffer);
aecm.farendBuffer(audioBuffer, audioLength);
aecm.echoCancellation(audioBuffer, null, aecOut,
(short) (audioLength), (short) 10);
/*Send output to speeker */
speaker.write(aecOut, 0, audioLength);
} catch (Exception ie) {
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
}
}
これを行うと、次の例外が発生します。
12-23 17:31:11.290: W/System.err(8717): java.lang.Exception: setFarendBuffer() failed due to invalid arguments.
12-23 17:31:11.290: W/System.err(8717): at com.android.webrtc.audio.MobileAEC.farendBuffer(MobileAEC.java:204)
12-23 17:31:11.290: W/System.err(8717): at com.example.twodottwo.PlayerThread.run(PlayerThread.java:62)
12-23 17:31:11.290: W/System.err(8717): at java.lang.Thread.run(Thread.java:841)
コードを少し調べてみたところ、サンプラーは一度に 80 個または 160 個のサンプルしか受け入れないことがわかりました。これを補うために、一度に 160 サンプルのみを取得しようとしましたが、これは AudioRecord オブジェクトの最小バッファー サイズよりも小さく、エラーが発生します。
したがって、これを回避するために、次のコードも試して、一度に最大 320 バイトしか配信しないようにキューを設定しました (2 バイトを短く使用するため)。
ShortBuffer sb = ShortBuffer.allocate(audioLength);
int samples = audioLength / 160;
while(i < samples) {
buf = playerQueue.take();
ByteBuffer.wrap(buf).order(ByteOrder.nativeOrder()).asShortBuffer().get(audioBuffer);
aecm.farendBuffer(audioBuffer, 160);
aecm.echoCancellation(audioBuffer, null, aecOut, (short) (160), (short) 10);
sb.put(aecOut);
i ++;
}
speaker.write(sb.array(), 0, audioLength);
これで、各 160 要素配列がバッファリングされ、WebRtc ライブラリに渡されてエコー キャンセルが実行されます。ランダムなノイズを生成するだけのようです。結果の配列の順序も逆にしようとしましたが、それでもランダム ノイズが発生します。
サウンド サンプルを分割して、WebRTC が好む方法でオリジナルのように聞こえるようにする方法はありますか? または、WebRtc が一度により多くのサンプルを受け入れるようにする方法はありますか? どちらでもいいと思いますが、今はちょっと行き詰っています。