有谁知道如何使用 Android 设备的内置声学回声消除?它位于硅片中的某处,用于 GSM/CDMA 免提通话。我们真的很想利用它来开发 VoIP 应用程序,而不是自己开发。
本
有谁知道如何使用 Android 设备的内置声学回声消除?它位于硅片中的某处,用于 GSM/CDMA 免提通话。我们真的很想利用它来开发 VoIP 应用程序,而不是自己开发。
本
我终于能够在我的 Arm5 (WM8650) 处理器 (Android 2.2) 上使用回声消除功能。以下是我采取的步骤。
我用 JNI 包装了 Speex,并在将 PCM 帧发送到编码器之前调用了回声处理例程。无论我尝试什么 Speex 设置,都没有取消回声。
因为 Speex 对播放和回显帧之间的延迟非常敏感,所以我实现了一个队列并将所有发送到 AudioTrack 的数据包排队。队列的大小应该大致等于内部 AudioTrack 缓冲区的大小。当 AudioTrack 将数据包从其内部缓冲区发送到声卡时,数据包被发送到 echo_playback。使用这种方法消除了延迟,但仍然没有取消回声
我用 JNI 包装了 WebRtc 回声消除部分,并在将数据包发送到编码器之前调用了它的方法。回声仍然存在,但图书馆显然正试图取消它。
我应用了 P2 中描述的缓冲技术,它终于开始起作用了。但是,需要为每个设备调整延迟。另请注意,WebRtc 具有移动版和完整版回声消除功能。完整版大大减慢了处理器的速度,应该只能在 ARM7 上运行。移动版可以工作,但质量较低
我希望这会对某人有所帮助。
Since API Level 11, there is a new value for MediaRecorder.AudioSource, it is VOICE_COMMUNICATION. Android docs say: "Microphone audio source tuned for voice communications such as VoIP. It will for instance take advantage of echo cancellation or automatic gain control if available. It otherwise behaves like DEFAULT if no voice processing is applied." I tried this, but couldn't make it worked. The problem may be the device I'd used, which is Sony Tablet S. Worth trying, though.
我去过同一个地方,成功地将 Speex AEC 移植到 Android 并在 2 个不同的 Android VoIP 客户端中使用它。大多数回声在扬声器上全音量时被消除 - 在各种设备上进行了测试。Speex 官方文档和谷歌搜索应该足以让它工作。
我尝试了这里描述的所有方法,发现它们效率不高。
最后我决定最好的回声消除器是增益控制器。
我在播放音频线程中编写了下一个代码:
float volume = ((float)audioManager.getStreamVolume(audioManager.STREAM_VOICE_CALL))/
audioManager.getStreamMaxVolume(audioManager.STREAM_VOICE_CALL);
track.setStereoVolume(0.5f, 0.5f);
for (int i = 0; i < FRAME_SIZE; i++)
{
int gained_low_byte = (int) ((outBuf[2*i] & 0xFF) * 2.0f*volume*.75f);
outBuf[2*i] = (byte) (gained_low_byte & 0xFF);
outBuf[2*i+1] = (byte) (outBuf[2*i+1] * 2.0f*volume*.75f + (gained_low_byte >> 8));
}
float avg = 0.0f;
for (int i = 0; i < FRAME_SIZE; i++)
{
avg += Math.abs((float)((outBuf[2*i+1] << 8) | (outBuf[2*i] & 0xFF))) / 32768.0f;
}
avg /= FRAME_SIZE;
if (avg > max_onair*9/10 || onair_counter == 0)
{
if (avg > max_onair || onair_counter == 0)
max_onair = avg;
else
Log.v(TAG, "On Air: support max_onair level " + max_onair + " by "+avg);
onair_counter = 75; // You can play with this value to make the effect more fit
}
else onair_counter--;
记录线程中的下一个
float control_number = max_onair*333; // Other important value
//Log.v(TAG, "Control microphone number is "+control_number);
if (control_number > 1.0f)
{
control_number = (float) Math.exp(control_number);
for (int i = 0; i < FRAME_SIZE; i++)
{
clearedBuf[2*i] = (byte) ((clearedBuf[2*i] & 0xFF) / control_number);
clearedBuf[2*i+1] /= control_number;
}
}
所以它不是真正的回声消除器,但至少它有效。