Android實現(xiàn)錄音靜音降噪
本文實例為大家分享了Android實現(xiàn)錄音靜音降噪的具體代碼,供大家參考,具體內容如下
需求:
客戶反饋產品的錄音里面很多雜音(因為我們把Codec的錄音增益調至最大,且電路上沒有專用的音頻處理芯片、CPU直接接MIC(有包地))。在外殼、硬件不能修改的情況下,軟件得想想辦法嘗試解決問題。
首先想到的是雙麥降噪,原理大概是:一個主麥克風用來做通話,另一個收集環(huán)境噪音,對音頻波形分析和相位操作,疊加到主麥克風的采樣波形上,形成相位抵消,就降噪了。缺點是,兩個麥克風不能距離太近,并且兩個麥克風距離說話人的距離不能太遠,太遠了角度就很小了,根本無法分辨出來,另外,根據產品使用情況,上下麥克風各自都有幾率稱為主麥克風。所以實驗測試出來的結果并沒有很好。
考慮到錄音噪音在有“人聲”的時候是分辨不出來的、或者說影響很小,而在靜音時有明顯的環(huán)境噪聲,因此想使用靜音降噪的方法來規(guī)避問題。
本文只是簡單的靜音降噪,原理如下:考慮到啟動錄音時,要等待一段時間(比如0.5s)才會有人聲,可根據這0.5s時間來預測噪聲的大?。ㄩ撝担?,然后以此為基礎來檢測“人聲”的起始點。在人聲到來前,把所有音頻數據設置為0,也就是做靜音處理,所以這里叫靜音降噪。而人聲到來時,返回實際的音頻數據(包括里面的噪聲數據)。計算閾值的方法只是簡單的求和平均。
下面代碼在RK平臺上hardware/alsa_sound/AudioStreamInALSA.cpp實現(xiàn)。
#define MUTE_NOISE_REDUCTION
#ifdef MUTE_NOISE_REDUCTION
bool enable_reduction_noise = false;?? ?//由屬性sys.is.audiorecord.only控制
int threshold_def = 0x400;?? ?//默認閾值
int threshold = 0;?? ?//自適應噪聲閾值
int threshold_count = 0;?? ?//計數,超過THRESHOLD_COUNT則使用threshold來檢測“人聲”
#define THRESHOLD_COUNT 10
#define MUTE_DELAY_COUNT 15?? ??? ?//播放人聲后保留的音頻幀數、不靜音
#define AUDIO_BUFFER_NUM 4?? ??? ?//緩存音頻數據的幀數
#define AUDIO_BUFFER_SIZE 1024?? ?//一幀的音頻數據大小
char *audio_buffer[AUDIO_BUFFER_NUM];?? ?//audio_buffer用于緩存音頻數據
char *audio_buffer_temp;?? ?//用于交互音頻數據
int audio_buffer_pos=0;
#endif
#ifdef MUTE_NOISE_REDUCTION
? ? {
? ? ? ? unsigned int value = 0;
? ? ? ? int is_voice = 0;
? ? ? ? static int is_mute_delay_count;
? ? ? ? //ALOGE("in_begin_swip_num:%d in_begin_narrow_num=%d",in_begin_swip_num,in_begin_narrow_num);?? ??? ?
? ? ? ? ?if(enable_reduction_noise && bytes > AUDIO_BUFFER_SIZE){
? ? ? ? ? ? bytes = AUDIO_BUFFER_SIZE;
? ? ? ? }
? ? ? ? if(enable_reduction_noise){
? ? ? ? ? ? unsigned char * buffer_temp=(unsigned char *)buffer;
? ? ? ? ? ? unsigned int total = 0;
? ? ? ? ? ? unsigned int total_count=0;
?? ??? ??? ?unsigned int total_temp = 0;
? ? ? ? ? ? short data16;
? ? ? ? ? ? int j = 0;
? ? ? ? ? ? for(j=0; j<bytes; j=j+2){
? ? ? ? ? ? ? ? value = buffer_temp[j+1];?? ?//第二個字節(jié)為高位數據
? ? ? ? ? ? ? ? value = (value<<8)+buffer_temp[j];?? ?//獲得一個16bit的音頻數據
? ? ? ? ? ? ? ? data16 = value&0xFFFF;
? ? ? ? ? ? ? ? if( (data16 & 0x8000) == 0){//正數
?? ??? ??? ??? ??? ?total +=data16;?? ??? ?//思考:會不會溢出
?? ??? ??? ??? ??? ?total_count++;?? ??? ?//計數
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
?? ??? ??? ?total_temp = total/total_count;
? ? ? ? ? ? if(total_temp > threshold_def){
? ? ? ? ? ? ? ? is_voice++;?? ??? ?//檢測到人聲
? ? ? ? ? ? }else {?? ?//is noise
?? ??? ??? ??? ?if(threshold_count == 0){
?? ??? ??? ??? ??? ?threshold = total_temp;
?? ??? ??? ??? ?}else{
?? ??? ??? ??? ??? ?threshold = (threshold+total_temp)/2;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?threshold_count++;
?? ??? ??? ??? ?if(threshold_count >= THRESHOLD_COUNT){
?? ??? ??? ??? ??? ?threshold_def = threshold*2;?? ?//更新閾值,這里的2要對產品實驗來確定。
?? ??? ??? ??? ??? ?threshold_count = THRESHOLD_COUNT;?? ?//此后一直用新閾值,直到停止錄音
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?//is_mute_delay_count的意義是,如果前面播放了人聲,那再停止說話之后繼續(xù)保留MUTE_DELAY_COUNT的音頻數據,這樣不會“戛然而止”。
?? ? ? ? ? ?if( is_voice != 0 ){
?? ? ? ? ? ? ? ?is_mute_delay_count=MUTE_DELAY_COUNT;
?? ? ? ? ? ?}else{
?? ? ? ? ? ? ? ?if(is_mute_delay_count != 0)
?? ? ? ? ? ? ? ? ? ?is_mute_delay_count--;
?? ? ? ? ? ?}
?? ??? ??? ?//audio_buffer的意義:檢測到人聲,要返回說話前的一小段音頻數據,否則聲音從靜音到人聲有個POP聲的跳躍。
?? ??? ??? ?//這里用audio_buffer來緩存AUDIO_BUFFER_NUM幀數據。
?? ? ? ? ? ?if(is_mute_delay_count == 0){//Mute in order to remove noise
?? ? ? ? ? ? ? ?memcpy(audio_buffer[audio_buffer_pos], (char *)buffer, bytes);?? ?//緩存音頻
?? ? ? ? ? ? ? ?memset(buffer, 0, bytes);?? ?//返回靜音數據
?? ? ? ? ? ?}else {
?? ? ? ? ? ? ? ?memcpy(audio_buffer_temp, (char *)buffer, bytes);
?? ? ? ? ? ? ? ?memcpy((char *)buffer, audio_buffer[audio_buffer_pos], bytes);?? ?//返回舊的音頻數據
?? ? ? ? ? ? ? ?memcpy(audio_buffer[audio_buffer_pos], (char *)audio_buffer_temp, bytes); ?? ?//保存新的音頻數據
?? ? ? ? ? ?}
?? ??? ??? ?audio_buffer_pos++;
?? ??? ??? ?if(audio_buffer_pos>=AUDIO_BUFFER_NUM)
? ? ? ? ? ? ? ? audio_buffer_pos=0;
? ? ? ? }
? ? }
#endif以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Android給通知channel靜音的方法實例
- Android實現(xiàn)靜音檢測功能
- Android 判斷網絡狀態(tài)對音頻靜音的實現(xiàn)方法
- Android實現(xiàn)定時自動靜音小助手
- Android EasyPlayer聲音自動停止、恢復,一鍵靜音等功能
- android實現(xiàn)來電靜音示例(監(jiān)聽來電)
- android系統(tǒng)在靜音模式下關閉camera拍照聲音的方法
- Android音頻錄制MediaRecorder之簡易的錄音軟件實現(xiàn)代碼
- Android簡單的利用MediaRecorder進行錄音的實例代碼
- Android實現(xiàn)錄音功能實現(xiàn)實例(MediaRecorder)
相關文章
Android編程中沉浸式狀態(tài)欄的三種實現(xiàn)方式詳解
這篇文章主要介紹了Android編程中沉浸式狀態(tài)欄的三種實現(xiàn)方式,簡單描述了沉浸式狀態(tài)欄的概念、功能并結合實例形式詳細分析了Android實現(xiàn)沉浸式狀態(tài)欄的三種操作技巧與注意事項,需要的朋友可以參考下2018-02-02
Android?nonTransitiveRClass資源沖突問題淺析
這篇文章主要介紹了Android?nonTransitiveRClass資源沖突問題,別搞錯了,nonTransitiveRClass不能解決資源沖突,需要的朋友們下面隨著小編來一起學習吧2022-12-12
Android openGl 繪制簡單圖形的實現(xiàn)示例
這篇文章主要介紹了Android openGl 繪制簡單圖形的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03
Android的Glide庫加載圖片的用法及其與Picasso的對比
這篇文章主要介紹了Android的Glide庫加載圖片的用法及其與Picasso的對比,Glide的加載gif圖片的功能和性能受到了很多開發(fā)者的青睞,需要的朋友可以參考下2016-04-04
Android事件分發(fā)機制(下) View的事件處理
這篇文章主要介紹了Android事件分發(fā)機制下篇, View的事件處理的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01
Android PopupMenu彈出菜單的實現(xiàn)
這篇文章主要介紹了 Android PopupMenu彈出菜單的實現(xiàn)的相關資料,希望通過本文能幫助到大家,實現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10
android如何設置小區(qū)廣播默認信道(50與60并支持雙卡)
置小區(qū)廣播默認信道50與60,并支持雙卡主要是印度市場,具體的實現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06

