有谁知道如何使用Android设备的内置声学回声消除功能?它位于硅片的某个地方,用于GSM / CDMA免提电话。我们真的很想进入VoIP应用程序,而不是自己动手。
本
答案 0 :(得分:4)
我终于能够在我的Arm5(WM8650)处理器(Android 2.2)上使用回音消除功能。以下是我采取的步骤。
我将Speex与JNI包装在一起,并在将PCM帧发送到编码器之前调用了回显处理例程。无论我尝试过何种Speex设置,都没有取消回音。
因为Speex对回放帧和回显帧之间的延迟非常敏感,所以我实现了一个队列并将发送到AudioTrack的所有数据包排队。队列的大小应大致等于内部AudioTrack缓冲区的大小。这样,当AudioTrack从内部缓冲区向声卡发送数据包时,数据包大致被发送到echo_playback。采用这种方法消除了延迟,但仍未取消回声
我用JNI包装了WebRtc回声消除部分,并在将数据包发送到编码器之前调用了它的方法。回声仍然存在,但图书馆显然试图取消它。
我应用了P2中描述的缓冲技术,它终于开始工作了。但是,需要针对每个设备调整延迟。另请注意,WebRtc具有移动和完整版本的回声消除功能。完整版本大大减慢了处理器速度,应该只能在ARM7上运行。移动版本可以使用,但质量较低
我希望这会对某人有所帮助。
答案 1 :(得分:0)
我去过同一个地方,成功将Speex AEC移植到Android并在2个不同的Android VoIP客户端中使用它。当在全音量的扬声器电话上时,大多数回声被取消 - 在各种设备上进行测试。 Speex官方文档和谷歌搜索应该足以让它发挥作用。
答案 2 :(得分:0)
自API级别11以来,MediaRecorder.AudioSource有一个新值,它是VOICE_COMMUNICATION。 Android文档say:"针对语音通信(如VoIP)调整的麦克风音频源。例如,它将利用回声消除或自动增益控制(如果可用)。如果不应用语音处理,它的行为就像DEFAULT一样。"我尝试过这个,但无法使它奏效。问题可能是我使用的设备,这是Sony Tablet S.值得尝试的。
答案 3 :(得分:0)
我尝试了此处介绍的所有方法,但发现它们效率不高。
最后我决定最好的回声消除器是增益控制器。
我已经在播放音频线程中编写了下一个代码:
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;
}
}
因此它不是真正的回声消除器,但至少它可以工作。