Android實現(xiàn)聲音采集回聲與回聲消除
本文實例為大家分享了Android實現(xiàn)聲音采集回聲與回聲消除的具體代碼,供大家參考,具體內(nèi)容如下
一、回聲產(chǎn)生的原因
回聲(或稱回音)是指障礙物對聲音的反射。聲波在遇到障礙物時,一部分聲波會穿過障礙物,而另一部分聲波會反射回來形成回聲。若障礙物具有堅硬光滑的表面易產(chǎn)生回聲;反之,具有柔軟的表面則易吸收聲音;另外,粗糙的表面易散射聲音?;芈曄啾饶切┲苯觽鞑サ穆曇羲?jīng)過的路程更長,所以會比直接傳播的聲音晚被聽到。如果兩列聲波的時間間隔小于0.1秒,人耳邊無法分辨,只能聽到被延長的聲音。因為室溫(20℃)時空氣中的聲速是343米每秒,所以站在聲源處的人要聽到回聲需要障礙物到聲源的距離至少17米。
二、消除回聲的原理
很多時候直播有連麥的需求,這時候就需要對采集的聲音進行回聲消除。當(dāng)處在連麥的情況下,手機一邊播放對方的聲音,一邊用麥克風(fēng)進行采集,然后又將采集的聲音傳送給對方,這樣的話對方就會聽到自己的回聲,由于這個循環(huán)回路一直進行,從而就會使得回聲越來越多,最后出現(xiàn)嗡鳴聲。
回聲消除就是在麥克風(fēng)錄制外音的時候去除掉手機自身播放出來的聲音,這樣就將對方的聲音從采集的聲音中過濾出去,從而就避免了回聲的產(chǎn)生。下面一張圖片很好展示了回聲消除的機制。
在近端,麥克風(fēng)會采集到揚聲器播放出來的遠(yuǎn)端聲音,假設(shè)這路聲音為y(n),當(dāng)然由于需要將遠(yuǎn)端傳來播放出來,我們當(dāng)然能得到遠(yuǎn)端傳來的聲音信號,假設(shè)這路聲音為x(n)。不難發(fā)現(xiàn)x(n)經(jīng)過揚聲器的播放,然后經(jīng)過空氣的傳播,最后被麥克風(fēng)采集,然后變?yōu)閥(n),x(n)和y(n)具有明顯的相關(guān)性。假設(shè)麥克風(fēng)采集到的總聲音信號為z(n),這時候需要通過自適應(yīng)濾波器根據(jù)x(n)找出z(n)中的y(n),然后從z(n)中過濾掉y(n)。
三、Android 中的聲音采集與回聲消除
在Android中回聲消除可以通過三種方式進行處理:
1、通過VOICE_COMMUNICATION模式進行錄音,自動實現(xiàn)回聲消除;
2、利用Android自身帶的AcousticEchoCanceler進行回聲消除處理;
3、使用第三方庫(Speex、Webrtc)進行回聲消除處理。
使用AudioRecord模式進行錄音的時候,需要將AudioManager設(shè)置模式為MODE_IN_COMMUNICATION,還需要將麥克風(fēng)打開。
有一點需要特別注意,音頻采樣率必須設(shè)置8000或者16000,通道數(shù)必須設(shè)為1個。
AudioManager audioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); audioManager.setSpeakerphoneOn(true);
使用AcousticEchoCanceler過程比較簡單,錄制聲音的時候可以通過AudioRecord得到AudioSessionId,在創(chuàng)建AudioTrack的時候也可以傳入一個AudioSessionId,這時候?qū)⑦@個統(tǒng)一的AudioSessionId傳入AcousticEchoCanceler,那么AcousticEchoCanceler將根據(jù)之前講過的回聲消除的原理進行回聲消除。
private void initAec(int audioSessionId) {
if(!AudioAecUtils.isAcousticEchoCancelerApproved()) {
aecSwitch.setEnabled(false);
return;
}
aec = AcousticEchoCanceler.create(audioSessionId);
if (aec == null) {
Log.e(TAG, "AcousticEchoCanceler.create failed");
aecSwitch.setEnabled(false);
return;
}
}
private boolean setEnableAec(boolean enable) {
if (aec == null) {
return false;
}
int ret = aec.setEnabled(enable);
if (ret != AudioEffect.SUCCESS) {
Log.e(TAG, "AcousticEchoCanceler.setEnabled failed");
return false;
}
if(enable) {
Log.d(TAG, "Aec On");
} else {
Log.d(TAG, "Aec Off");
}
return true;
}
當(dāng)使用Speex或者Webrtc第三方庫進行回聲消除的時候,需要將采集到的音頻數(shù)據(jù)傳入作為源數(shù)據(jù),需要將此刻播放的音頻數(shù)據(jù)傳入作為參考數(shù)據(jù),然后還需要傳入一個延時間隔,這樣第三方庫就能工作,從而得到回聲消除后的聲音。因為播放的聲音需要傳播,而且麥克風(fēng)采集聲音還有相應(yīng)的緩沖區(qū),因此需要傳入一個延時間隔。關(guān)于Speex和Webrtc在github上能找到相應(yīng)的Android ndk庫。
本人對三種方式都進行了嘗試,發(fā)現(xiàn)第一種效果最好,兼容性也較好,因為手機免提通話的時候就進行了回聲消除處理,所以基本上所有的手機是支持的。第二種方式支持的很少,Nexus 5支持第二種方式。理論上第三種方式兼容性最好,但是本人多次實驗發(fā)現(xiàn)要設(shè)置合適的延時間隔很難,有些時候設(shè)置好了,但是通話一段時間效果又變差。
四、Android中的聲音模式設(shè)置與回聲消除
在Android系統(tǒng)中有著多種的聲音模式,通過AudioManager.setMode()可以設(shè)置聲音的模式。就像上面回聲消除所描述的,通過設(shè)置聲音模式為MODE_IN_COMMUNICATION,加上一些聲音參數(shù)的設(shè)置可以啟動Android自身的硬件回聲消除(通話時候的回聲消除)。
設(shè)置聲音模式的時候需要權(quán)限“android.permission.MODIFY_AUDIO_SETTINGS”。不同的聲音模式聲音的輸出行為不一樣。
當(dāng)設(shè)置為MODE_IN_COMMUNICATION模式時,聲音默認(rèn)是聽筒出聲,這時候如果是在連麥模式而且主播沒有戴耳機的情況下顯然這樣不符合,這時候需要調(diào)用audioManager.setSpeakerphoneOn(true)切換成外放出聲。當(dāng)插上耳機后,聲音不需要外放,需要從耳機出聲,這樣可以設(shè)置audioManager.setSpeakerphoneOn(false)。
當(dāng)聲音模式為MODE_NORMAL,沒有插耳機的時候聲音自動外放,插上耳機聲音從耳機出聲,不需要進行相應(yīng)的設(shè)置。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android TextView跑馬燈效果實現(xiàn)方法
這篇文章主要介紹了Android TextView跑馬燈效果實現(xiàn)方法,涉及Android布局文件中相關(guān)屬性的設(shè)置技巧,非常簡單實用,需要的朋友可以參考下2016-01-01
Android?Kotlin全面詳細(xì)類使用語法學(xué)習(xí)指南
這篇文章主要為大家介紹了Android?Kotlin全面詳細(xì)類使用語法學(xué)習(xí)指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
Android開發(fā)使用ProgressBar實現(xiàn)進度條功能示例
這篇文章主要介紹了Android開發(fā)使用ProgressBar實現(xiàn)進度條功能,結(jié)合實例形式分析了Android進度條ProgressBar的具體樣式、布局與功能實現(xiàn)技巧,需要的朋友可以參考下2019-03-03
android 中 webview 怎么用 localStorage
這篇文章主要介紹了android 中 webview 怎么用 localStorage方法的相關(guān)資料,需要的朋友可以參考下2015-07-07
Android動畫 實現(xiàn)開關(guān)按鈕動畫(屬性動畫之平移動畫)實例代碼
這篇文章主要介紹了Android動畫 實現(xiàn)開關(guān)按鈕動畫(屬性動畫之平移動畫)實例代碼的相關(guān)資料,需要的朋友可以參考下2016-11-11
Android開發(fā)中優(yōu)秀的app 異常處理機制
這篇文章主要介紹了Android開發(fā)中優(yōu)秀的app 異常處理機制 的相關(guān)資料,需要的朋友可以參考下2015-12-12
Android 如何實現(xiàn)彈窗順序&優(yōu)先級控制
這篇文章主要介紹了Android 如何實現(xiàn)彈窗順序&優(yōu)先級控制,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-03-03
Android中實現(xiàn)自動生成布局View的初始化代碼方法
這篇文章主要介紹了Android中實現(xiàn)自動生成布局View的初始化代碼方法,本文使用解析layout 布局文件的方法實現(xiàn)需求,需要的朋友可以參考下2014-10-10

