音頻自動增益 與 靜音檢測 算法 附完整C代碼

前面分享過一個算法《音頻增益響度分析 ReplayGain 附完整C代碼示例》

主要用于評估一定長度音頻的音量強度,

而分析之后,很多類似的需求,肯定是做音頻增益,提高音量諸如此類做法。

不過在項目實測的時候,其實真的很難定標準,

到底在什么樣的環境下,要增大音量,還是降低。

在通訊行業一般的做法就是采用靜音檢測,

一旦檢測為靜音或者噪音,則不做處理,反之通過一定的策略進行處理。

這里就涉及到兩個算法,一個是靜音檢測,一個是音頻增益。

增益其實沒什么好說的,類似于數據歸一化拉伸的做法。

靜音檢測?在WebRTC中?是采用計算GMM (Gaussian Mixture Model,高斯混合模型)進行特征提取的。

在很長一段時間里面,音頻特征?有3個主要的方法,

GMM? ,Spectrogram (聲譜圖), MFCC?即 Mel-Frequency Cepstrum(Mel頻率倒譜)

恕我直言,GMM?提取的特征,其魯棒性 不如后兩者。

也不多做介紹,感興趣的同學,翻翻 維基百科 ,補補課。

當然在實際使用算法時,會由此延伸出來一些小技巧。

例如,用靜音檢測?來做音頻裁剪,或者搭配音頻增益做一些音頻增強之類的操作。

自動增益在WebRTC?源代碼文件是:analog_agc.c?和?digital_agc.c

靜音檢測?源代碼文件是: webrtc_vad.c

這個命名,有一定的歷史原因了。

經過梳理后,

增益算法為 agc.c agc.h

靜音檢測為 vad.c vad.h

增益算法的完整示例代碼:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解碼
#define DR_WAV_IMPLEMENTATION
#include "dr_wav.h"
#include "agc.h"#ifndef nullptr
#define nullptr 0
#endif#ifndef MIN
#define  MIN(A, B)        ((A) < (B) ? (A) : (B))
#endif//寫wav文件
void wavWrite_int16(char *filename, int16_t *buffer, size_t sampleRate, size_t totalSampleCount) {drwav_data_format format = {};format.container = drwav_container_riff;     // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64.format.format = DR_WAVE_FORMAT_PCM;          // <-- Any of the DR_WAVE_FORMAT_* codes.format.channels = 1;format.sampleRate = (drwav_uint32) sampleRate;format.bitsPerSample = 16;drwav *pWav = drwav_open_file_write(filename, &format);if (pWav) {drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);drwav_uninit(pWav);if (samplesWritten != totalSampleCount) {fprintf(stderr, "ERROR\n");exit(1);}}
}//讀取wav文件
int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint64_t *totalSampleCount) {unsigned int channels;int16_t *buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount);if (buffer == nullptr) {printf("讀取wav文件失敗.");}//僅僅處理單通道音頻if (channels != 1) {drwav_free(buffer);buffer = nullptr;*sampleRate = 0;*totalSampleCount = 0;}return buffer;
}//分割路徑函數
void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {const char *end;const char *p;const char *s;if (path[0] && path[1] == ':') {if (drv) {*drv++ = *path++;*drv++ = *path++;*drv = '\0';}} else if (drv)*drv = '\0';for (end = path; *end && *end != ':';)end++;for (p = end; p > path && *--p != '\\' && *p != '/';)if (*p == '.') {end = p;break;}if (ext)for (s = end; (*ext = *s++);)ext++;for (p = end; p > path;)if (*--p == '\\' || *p == '/') {p++;break;}if (name) {for (s = p; s < end;)*name++ = *s++;*name = '\0';}if (dir) {for (s = path; s < p;)*dir++ = *s++;*dir = '\0';}
}int agcProcess(int16_t *buffer, uint32_t sampleRate, size_t samplesCount, int16_t agcMode) {if (buffer == nullptr) return -1;if (samplesCount == 0) return -1;WebRtcAgcConfig agcConfig;agcConfig.compressionGaindB = 9; // default 9 dBagcConfig.limiterEnable = 1; // default kAgcTrue (on)agcConfig.targetLevelDbfs = 3; // default 3 (-3 dBOv)int minLevel = 0;int maxLevel = 255;size_t samples = MIN(160, sampleRate / 100);if (samples == 0) return -1;const int maxSamples = 320;int16_t *input = buffer;size_t nTotal = (samplesCount / samples);void *agcInst = WebRtcAgc_Create();if (agcInst == NULL) return -1;int status = WebRtcAgc_Init(agcInst, minLevel, maxLevel, agcMode, sampleRate);if (status != 0) {printf("WebRtcAgc_Init fail\n");WebRtcAgc_Free(agcInst);return -1;}status = WebRtcAgc_set_config(agcInst, agcConfig);if (status != 0) {printf("WebRtcAgc_set_config fail\n");WebRtcAgc_Free(agcInst);return -1;}size_t num_bands = 1;int inMicLevel, outMicLevel = -1;int16_t out_buffer[maxSamples];int16_t *out16 = out_buffer;uint8_t saturationWarning = 1;                 //是否有溢出發生,增益放大以后的最大值超過了65536int16_t echo = 0;                                 //增益放大是否考慮回聲影響for (int i = 0; i < nTotal; i++) {inMicLevel = 0;int nAgcRet = WebRtcAgc_Process(agcInst, (const int16_t *const *) &input, num_bands, samples,(int16_t *const *) &out16, inMicLevel, &outMicLevel, echo,&saturationWarning);if (nAgcRet != 0) {printf("failed in WebRtcAgc_Process\n");WebRtcAgc_Free(agcInst);return -1;}memcpy(input, out_buffer, samples * sizeof(int16_t));input += samples;}WebRtcAgc_Free(agcInst);return 1;
}void auto_gain(char *in_file, char *out_file) {//音頻采樣率uint32_t sampleRate = 0;//總音頻采樣數uint64_t inSampleCount = 0;int16_t *inBuffer = wavRead_int16(in_file, &sampleRate, &inSampleCount);//如果加載成功if (inBuffer != nullptr) {//  kAgcModeAdaptiveAnalog  模擬音量調節//  kAgcModeAdaptiveDigital 自適應增益//  kAgcModeFixedDigital 固定增益
        agcProcess(inBuffer, sampleRate, inSampleCount, kAgcModeAdaptiveDigital);wavWrite_int16(out_file, inBuffer, sampleRate, inSampleCount);free(inBuffer);}
}int main(int argc, char *argv[]) {printf("WebRTC Automatic Gain Control\n");printf("博客:http://cpuimage.cnblogs.com/\n");printf("音頻自動增益\n");if (argc < 2)return -1;char *in_file = argv[1];char drive[3];char dir[256];char fname[256];char ext[256];char out_file[1024];splitpath(in_file, drive, dir, fname, ext);sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);auto_gain(in_file, out_file);printf("按任意鍵退出程序 \n");getchar();return 0;
}

?

?靜音檢測完整示例代碼:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解碼
#define DR_WAV_IMPLEMENTATION#include "dr_wav.h"
#include "vad.h"#ifndef nullptr
#define nullptr 0
#endif#ifndef MIN
#define  MIN(A, B)        ((A) < (B) ? (A) : (B))
#endif#ifndef MAX
#define  MAX(A, B)        ((A) > (B) ? (A) : (B))
#endif//讀取wav文件
int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint64_t *totalSampleCount) {unsigned int channels;int16_t *buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount);if (buffer == nullptr) {printf("讀取wav文件失敗.");}//僅僅處理單通道音頻if (channels != 1) {drwav_free(buffer);buffer = nullptr;*sampleRate = 0;*totalSampleCount = 0;}return buffer;
}int vadProcess(int16_t *buffer, uint32_t sampleRate, size_t samplesCount, int16_t vad_mode, int per_ms_frames) {if (buffer == nullptr) return -1;if (samplesCount == 0) return -1;// kValidRates : 8000, 16000, 32000, 48000// 10, 20 or 30 ms framesper_ms_frames = MAX(MIN(30, per_ms_frames), 10);size_t samples = sampleRate * per_ms_frames / 1000;if (samples == 0) return -1;int16_t *input = buffer;size_t nTotal = (samplesCount / samples);void *vadInst = WebRtcVad_Create();if (vadInst == NULL) return -1;int status = WebRtcVad_Init(vadInst);if (status != 0) {printf("WebRtcVad_Init fail\n");WebRtcVad_Free(vadInst);return -1;}status = WebRtcVad_set_mode(vadInst, vad_mode);if (status != 0) {printf("WebRtcVad_set_mode fail\n");WebRtcVad_Free(vadInst);return -1;}printf("Activity : \n");for (int i = 0; i < nTotal; i++) {int nVadRet = WebRtcVad_Process(vadInst, sampleRate, input, samples);if (nVadRet == -1) {printf("failed in WebRtcVad_Process\n");WebRtcVad_Free(vadInst);return -1;} else {// output resultprintf(" %d \t", nVadRet);}input += samples;}printf("\n");WebRtcVad_Free(vadInst);return 1;
}void vad(char *in_file) {//音頻采樣率uint32_t sampleRate = 0;//總音頻采樣數uint64_t inSampleCount = 0;int16_t *inBuffer = wavRead_int16(in_file, &sampleRate, &inSampleCount);//如果加載成功if (inBuffer != nullptr) {//    Aggressiveness mode (0, 1, 2, or 3)int16_t mode = 1;int per_ms = 30;vadProcess(inBuffer, sampleRate, inSampleCount, mode, per_ms);free(inBuffer);}
}int main(int argc, char *argv[]) {printf("WebRTC Voice Activity Detector\n");printf("博客:http://cpuimage.cnblogs.com/\n");printf("靜音檢測\n");if (argc < 2)return -1;char *in_file = argv[1];vad(in_file);printf("按任意鍵退出程序 \n");getchar();return 0;
}

自動增益項目地址:https://github.com/cpuimage/WebRTC_AGC

具體流程為:?

加載wav(拖放wav文件到可執行文件上)->增益處理->保存為_out.wav文件

?

靜音檢測項目地址:https://github.com/cpuimage/WebRTC_VAD

具體流程為:?

加載wav(拖放wav文件到可執行文件上)->輸出靜音檢測結果

備注 :1 為非靜音,0 為靜音

?該注意的地方和參數,見代碼注釋。

用cmake即可進行編譯示例代碼,詳情見CMakeLists.txt。

?

若有其他相關問題或者需求也可以郵件聯系俺探討。

郵箱地址是:?
gaozhihan@vip.qq.com

?

轉載于:https://www.cnblogs.com/cpuimage/p/8908551.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/538845.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538845.shtml
英文地址,請注明出處:http://en.pswp.cn/news/538845.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python繪制餅狀圖圖例_使用matplotlib的所有餅圖的通用圖例

圖例只需調用一次&#xff0c;否則將顯示7個不同的圖例。我在下面展示了一個例子。請注意&#xff0c;您必須將自己的數據替換為ax.pie()&#xff1a;data1 (10,90) # some data to be plotted data2 (40,50) data3 (70,30) labels [Sending Data, Not Sending Data] #lege…

Android初始化本地數據庫

原文&#xff1a;http://blog.csdn.net/itjavawfc/article/details/50860647 點擊閱讀原文 -------------------------------- 最近遇到一個需求&#xff0c;一個同學不會搭服務器&#xff0c;但是Android課程設計需要用到很多數據&#xff0c;這樣就出現了一個問題&#xff0c…

jsp springmvc 視圖解析器_springMVC配置jsp/html視圖解析器

1、maven項目引入freemark相關jar包freemaker是以個模板引擎&#xff0c;可以根據提供的數據和創建好的模板,去自動的創建html靜態頁面。所以在返回html視圖時可以用這個引擎結合數據生成html靜態頁面。org.springframeworkspring-context-support5.0.7.RELEASEorg.freemarkerf…

php設計模式原型模式,原型模式_設計模式_設計模式之原型模式 - Lane Blog

108Clicks: 6614 Date: 2014-04-21 21:48:35 Power By 李軒Lane原型模式提取重復功能&#xff0c;避免了程序員喜歡復制粘貼的壞習慣。設計模式中的原型模式就是&#xff0c;用原型實例指定創建對象的重力&#xff0c;通過拷貝這些原型來創建新的對象從一個對象再創建另外一個可…

Windows2003如何安裝IIS和ftp

【開始】----【控制面板】----【添加或刪除程序】 出現如下“添加或刪除程序”界面&#xff0c;點擊“添加/刪除windows組件&#xff08;a&#xff09; ” 出現如下“window組件向導”界面 下拉“組件”欄目條&#xff0c;選擇“應用程序服務器” 點擊“應用程序服務器”下的“…

hadoop臨時文件 jar包_hadoop之Mapper/reducer源碼分析之二

若當前JobClient (0.22 hadoop) 運行在YARN.則job提交任務運行在YARNRunnerHadoop Yarn 框架原理及運作機制主要步驟作業提交作業初始化資源申請與任務分配任務執行具體步驟在運行作業之前&#xff0c;Resource Manager和Node Manager都已經啟動&#xff0c;所以在上圖中&#…

ANDROID:SHOWASACTION="NEVER"是做什么用的?

原文地址&#xff1a;http://www.cnblogs.com/android-joker/p/4478491.html 點擊閱讀原文 --------------------------------------------------------- 安卓開發項目文件中有一個目錄叫做menu&#xff0c;里面有tybmain.xml item選項里有一句 android:showAsAction "…

吳恩達ex3_Wu-Enda機器學習編程作業Python實現EX3,吳恩達,machinelearning,python,ex3nn

# -*- coding: utf-8 -*-"""Created on Wed Jul 1 20:28:57 2020author: cheetah023"""import numpy as npimport matplotlib.pyplot as pltimport scipy.io as sciimport random as ra#函數定義def sigmoid(X):return 1 /(1 np.exp(-X))def pr…

php數組驗證用戶名密碼,求個php數組驗證問題,在線等

現在有這么一個數組,是屬性表Array([0] > Array([list_attr_id] > 30[list_attr_name] > 顏色[list_attr_attr] > 黑色|白色|金色[list_attr_price] > 0|10.1|20[list_attr_shop_id] > 28)[1] > Array([list_attr_id] > 31[list_attr_name] > 規格[…

基于python的視頻監控系統_Python實現微信監控報警系統

概述: 本文主要分享一下博主在學習wxpy 的過程中開發的一個小程序。博主在最近有一個監控報警的需求需要完成&#xff0c;然后剛好在學習wxpy 這個東西&#xff0c;因此很巧妙的將工作和學習聯系在一起。 博文中主要使用到的技術設計到Python&#xff0c;Redis&#xff0c;以及…

python 編碼文件json.loads json.dumps

python 編碼文件json.loads json.dumps import yaml d {name: 張三, age: 1} print d jd json.dumps(d, ensure_asciiFalse, encodingutf-8)) ud json.loads(jd, encodingutf-8) print ud ud yaml.safe_load(jd, encodingutf-8) print udposted on 2018-04-23 15:18 秦瑞It…

getActionBar()報空指針異常

調用 getActionBar()的Activity類 public class WlanListActivity extends AppCompatActivity 在使用getActionBar("標題內容")的時候報空指針。 原因是要用AppCompatActivity類里的getSupportActionBar()

python 類中定義列表_Python3中的自定義列表類,具有

我想用python3編寫一個自定義列表類&#xff0c;就像在這個問題How would I create a custom list class in python?中一樣&#xff0c;但與該問題不同&#xff0c;我想實現__get__和{}方法。雖然我的類與list類似&#xff0c;但是這些方法背后隱藏著一些神奇的操作。所以我想…

紅黑樹與平衡二叉樹_百圖詳解紅黑樹,想不理解都難

之前在公司組內分享了紅黑樹的工作原理&#xff0c;今天把它整理下發出來&#xff0c;希望能對大家有所幫助&#xff0c;對自己也算是一個知識點的總結。這篇文章算是我寫博客寫公眾號以來畫圖最多的一篇文章了&#xff0c;沒有之一&#xff0c;我希望盡可能多地用圖片來形象地…

linux 父子進程結束,Linux下讓父進程結束后,子進程自動結束

在多進程編程的時候&#xff0c;經常會遇到這樣的情況。父進程創建了一堆子進程&#xff0c;當遇到錯誤或者操作失誤的時候把父進程關閉了&#xff0c;但是子進程還在跑&#xff0c;不得不一個一個地殺死子進程&#xff0c;或者使用ps,grep,awk,kill來配合批量殺死。之前在寫 x…

android:showAsAction 無效

我想要的效果 但actionbar上的搜索菜單不顯示 在androidstudio里&#xff0c;android:showAsAction"always"標紅 根據提示&#xff0c;需要加入 xmlns:app"http://schemas.android.com/apk/res-auto" 加入后依然無效 正確的加入方式是&#xff1a;

Exchange_Server_2013在Windows_2008_R2部署

Exchange Server 2013可以部署在Windows Server 2012的平臺&#xff0c;也可以部署在Windows Server 2008 R2的平臺。如果部署在Windows Server 2008 R2平臺要求操作系統版本為Windows Server 2008 R2 SP1的版本。如下拓撲圖&#xff1a;在本架構中有兩臺服務器&#xff0c;都安…

建立副本名稱沖突_包的建立(一)

這次的內容&#xff0c;涉及到 R 語言包的建立。事實上&#xff0c;CRAN 提供的官方參考指南&#xff0c;并不適合快速閱讀&#xff0c;且內容繁雜。比較適合作為后期提高的 教材。而 http://r-pkgs.had.co.nz/ 上 的教程則更適合作為 R 包編寫的幫助指南。這里&#xff0c;僅僅…

Android 多選列表

原文&#xff1a;http://blog.csdn.net/wljun739/article/details/37655209 點擊閱讀原文 ----------------------------------------------------------- 1、activity_main.xml[java] view plaincopy<LinearLayout xmlns:android"http://schemas.android.com/apk/res/…

python自帶的編輯器怎么換行_Python3基礎 print 自帶換行功能

鎮場詩&#xff1a; ———大夢誰覺&#xff0c;水月中建博客。百千磨難&#xff0c;才知世事無常。 ———今持佛語&#xff0c;技術無量愿學。愿盡所學&#xff0c;鑄一良心博客。 —————————————————————————————————————————— 1 …