欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)聲音采集回聲與回聲消除

 更新時間:2021年08月25日 10:21:08   作者:大飛飛魚  
這篇文章主要為大家詳細介紹了Android實現(xiàn)聲音采集回聲與回聲消除,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Android實現(xiàn)聲音采集回聲與回聲消除的具體代碼,供大家參考,具體內(nèi)容如下

一、回聲產(chǎn)生的原因

  回聲(或稱回音)是指障礙物對聲音的反射。聲波在遇到障礙物時,一部分聲波會穿過障礙物,而另一部分聲波會反射回來形成回聲。若障礙物具有堅硬光滑的表面易產(chǎn)生回聲;反之,具有柔軟的表面則易吸收聲音;另外,粗糙的表面易散射聲音?;芈曄啾饶切┲苯觽鞑サ穆曇羲?jīng)過的路程更長,所以會比直接傳播的聲音晚被聽到。如果兩列聲波的時間間隔小于0.1秒,人耳邊無法分辨,只能聽到被延長的聲音。因為室溫(20℃)時空氣中的聲速是343米每秒,所以站在聲源處的人要聽到回聲需要障礙物到聲源的距離至少17米。

二、消除回聲的原理

  很多時候直播有連麥的需求,這時候就需要對采集的聲音進行回聲消除。當處在連麥的情況下,手機一邊播放對方的聲音,一邊用麥克風進行采集,然后又將采集的聲音傳送給對方,這樣的話對方就會聽到自己的回聲,由于這個循環(huán)回路一直進行,從而就會使得回聲越來越多,最后出現(xiàn)嗡鳴聲。
回聲消除就是在麥克風錄制外音的時候去除掉手機自身播放出來的聲音,這樣就將對方的聲音從采集的聲音中過濾出去,從而就避免了回聲的產(chǎn)生。下面一張圖片很好展示了回聲消除的機制。 

 

  在近端,麥克風會采集到揚聲器播放出來的遠端聲音,假設(shè)這路聲音為y(n),當然由于需要將遠端傳來播放出來,我們當然能得到遠端傳來的聲音信號,假設(shè)這路聲音為x(n)。不難發(fā)現(xiàn)x(n)經(jīng)過揚聲器的播放,然后經(jīng)過空氣的傳播,最后被麥克風采集,然后變?yōu)閥(n),x(n)和y(n)具有明顯的相關(guān)性。假設(shè)麥克風采集到的總聲音信號為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,還需要將麥克風打開。

有一點需要特別注意,音頻采樣率必須設(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;
}

當使用Speex或者Webrtc第三方庫進行回聲消除的時候,需要將采集到的音頻數(shù)據(jù)傳入作為源數(shù)據(jù),需要將此刻播放的音頻數(shù)據(jù)傳入作為參考數(shù)據(jù),然后還需要傳入一個延時間隔,這樣第三方庫就能工作,從而得到回聲消除后的聲音。因為播放的聲音需要傳播,而且麥克風采集聲音還有相應(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”。不同的聲音模式聲音的輸出行為不一樣。

當設(shè)置為MODE_IN_COMMUNICATION模式時,聲音默認是聽筒出聲,這時候如果是在連麥模式而且主播沒有戴耳機的情況下顯然這樣不符合,這時候需要調(diào)用audioManager.setSpeakerphoneOn(true)切換成外放出聲。當插上耳機后,聲音不需要外放,需要從耳機出聲,這樣可以設(shè)置audioManager.setSpeakerphoneOn(false)。

當聲音模式為MODE_NORMAL,沒有插耳機的時候聲音自動外放,插上耳機聲音從耳機出聲,不需要進行相應(yīng)的設(shè)置。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論