純粋な Java を使用する VOIP アプリケーションを実装しています。ユーザーがヘッドセットを使用していない場合 (ほとんどの場合、マイクが内蔵されているラップトップ) に発生するエコーの問題があります。
現在起きていること
VOIP アプリケーションの基本は、Java のメディア フレームワークの単なるデータラインです。基本的に、出力用にスピーカーに書き込む前に、オーディオ データに対して何らかのデジタル信号処理を実行したいと考えています。
public synchronized void addAudioData(byte[] ayAudioData)
{
m_oBuffer.enqueue(ayAudioData);
this.notify();
}
ご覧のとおり、オーディオ データが到着し、バッファにエンキューされます。これは危険な接続に対応し、さまざまなパケット サイズを許可するためです。また、オーディオ データをスピーカー ラインに再生する前に、高度な DSP 操作に必要なだけのオーディオ データにアクセスできることも意味します。
動作するエコー キャンセラを 1 つ管理しましたが、多くのインタラクティブなユーザー入力が必要なため、自動エコー キャンセラが必要です。
手動エコーキャンセラー
public static byte[] removeEcho(int iDelaySamples, float fDecay, byte[] aySamples)
{
m_awDelayBuffer = new short[iDelaySamples];
m_aySamples = new byte[aySamples.length];
m_fDecay = (float) fDecay;
System.out.println("Removing echo");
m_iDelayIndex = 0;
System.out.println("Sample length:\t" + aySamples.length);
for (int i = 0; i < aySamples.length; i += 2)
{
// update the sample
short wOldSample = getSample(aySamples, i);
// remove the echo
short wNewSample = (short) (wOldSample - fDecay * m_awDelayBuffer[m_iDelayIndex]);
setSample(m_aySamples, i, wNewSample);
// update the delay buffer
m_awDelayBuffer[m_iDelayIndex] = wNewSample;
m_iDelayIndex++;
if (m_iDelayIndex == m_awDelayBuffer.length)
{
m_iDelayIndex = 0;
}
}
return m_aySamples;
}
適応フィルター
私は、適応フィルターが進むべき道であることを読みました。具体的には、最小平均二乗フィルターです。しかし、私は立ち往生しています。上記のほとんどのサンプル コードは C および C++ で記述されており、Java にうまく変換されません。
それらを Java で実装する方法についてアドバイスがある人はいますか? 他のアイデアも大歓迎です。前もって感謝します。