logo头像

不忘初心,奋力前行

WebRTC中AGC模块分析(上)

拖了快一个月了,终于有时间来将所研究的WebRTC中的自动增益控制(AGC)模块的内容进行下系统的整理。目前个人了解的还很初步,有很多东西还没有研究透彻,所以这部分分析整理可能会比较浅薄,后续随着研究的深入,内容会不断完善。

本次先更新第一部分,包括WebRTC的AGC模块的介绍、框图、函数关系图和函数功能介绍等。下一期更新具体的函数原理内容。

1.AGC模块的简介和性能结果

WebRTC的音频处理模块分为语音活动检测(VAD)、降噪(NS和NSX)、回音消除(AEC)、回声控制(AECM)和音频增益(AGC)等5个部分。本次我要介绍的是其中的自动增益控制(AGC)部分,其代码主要位于WebRTC的modules\audio_processing\agc\legacy中。

什么时候用得到增益控制呢?实际上,当对语音的响度进行调整的需要时,就要做语音自动增益(AGC)算法处理,平时的语音聊天都会用到这个算法。

最简单的方法就是对所有的音频采样乘上一个增益系数,由于人的听觉对所有频率的感知不是线性的,所以会导致这样处理以后,听起来有的频率增强了、有的频率削弱了,导致了语音失真的方法。所以,要让整个频段听起来响度增益都是相同的,就必须在遵循响度曲线基础上,在响度这个尺度做增益,即按照响度曲线对语音的频率进行加权。

本工程以10ms为单位对语音进行模拟和数字增益的自适应调整。增益的调整仅在语音活动期间进行,语音的长度必须依照程序中所给的长度(8000Hz时为80个点,16000Hz为160个点,320000Hz为320个点,48000Hz为480个点)。本程序必须在进行回声消除后,在近端麦克风信号进行调用。

在这里介绍的时候,我以Github上的工程(https://github.com/cpuimage/WebRTC_AGC)为例进行讲解WebRTC中AGC的过程。

该方法的效果,如图1.1所示。
语音效果图

图1.1 语音效果图像

2.AGC的整体框图和函数关系图

2.1 AGC模块整体框图

整体系统框图

图2.1 AGC模块整体框图

2.2 AGC模块函数关系图

表2.1 AGC模块函数关系图

AGC模块函数关系图

2.3 AGC模块函数功能解释

表2.2 AGC模块函数功能解释
AGC模块函数功能解释

表2.3 其它相关函数功能及解释

其它相关函数功能及解释

2.4 使用到的常量

1.全通滤波器因子:

1
2
static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528};
static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255};

2.AGC的四种工作模式

表2.4 AGC的四种工作模式
AGC的四种工作模式

<![endif]–>

2.5 使用到的结构体

WebRtcAgc_config是配置targetLevelDbfs和compressionGaindB用于调节agc的动态范围。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
typedef struct {
int16_t targetLevelDbfs; // default 3 (-3 dBOv)
int16_t compressionGaindB; // default 9 dB
uint8_t limiterEnable; // default kAgcTrue (on)
} WebRtcAgcConfig;

typedef struct {
int32_t downState[8];
int16_t HPstate;
int16_t counter;
int16_t logRatio; // log( P(active) / P(inactive) ) (Q10)
int16_t meanLongTerm; // Q10
int32_t varianceLongTerm; // Q8
int16_t stdLongTerm; // Q10
int16_t meanShortTerm; // Q10
int32_t varianceShortTerm; // Q8
int16_t stdShortTerm; // Q10
} AgcVad;

typedef struct {
int32_t capacitorSlow;
int32_t capacitorFast;
int32_t gain;
int32_t gainTable[32];
int16_t gatePrevious;
int16_t agcMode;
AgcVad vadNearend;
AgcVad vadFarend;
#ifdef WEBRTC_AGC_DEBUG_DUMP
FILE* logFile;
int frameCounter;
#endif
} DigitalAgc;

typedef struct {
// Configurable parameters/variables
uint32_t fs; // Sampling frequency
int16_t compressionGaindB; // Fixed gain level in dB
int16_t targetLevelDbfs; // Target level in -dBfs of envelope (default -3)
int16_t agcMode; // Hard coded mode (adaptAna/adaptDig/fixedDig)
uint8_t limiterEnable; // Enabling limiter (on/off (default off))
WebRtcAgcConfig defaultConfig;
WebRtcAgcConfig usedConfig;

// General variables
int16_t initFlag;
int16_t lastError;

// Target level parameters
// Based on the above: analogTargetLevel = round((32767*10^(-22/20))^2*16/2^7)
int32_t analogTargetLevel; // = RXX_BUFFER_LEN * 846805; -22 dBfs
int32_t startUpperLimit; // = RXX_BUFFER_LEN * 1066064; -21 dBfs
int32_t startLowerLimit; // = RXX_BUFFER_LEN * 672641; -23 dBfs
int32_t upperPrimaryLimit; // = RXX_BUFFER_LEN * 1342095; -20 dBfs
int32_t lowerPrimaryLimit; // = RXX_BUFFER_LEN * 534298; -24 dBfs
int32_t upperSecondaryLimit; // = RXX_BUFFER_LEN * 2677832; -17 dBfs
int32_t lowerSecondaryLimit; // = RXX_BUFFER_LEN * 267783; -27 dBfs
uint16_t targetIdx; // Table index for corresponding target level
#ifdef MIC_LEVEL_FEEDBACK
uint16_t targetIdxOffset; // Table index offset for level compensation
#endif
int16_t analogTarget; // Digital reference level in ENV scale

// Analog AGC specific variables
int32_t filterState[8]; // For downsampling wb to nb
int32_t upperLimit; // Upper limit for mic energy
int32_t lowerLimit; // Lower limit for mic energy
int32_t Rxx160w32; // Average energy for one frame
int32_t Rxx16_LPw32; // Low pass filtered subframe energies
int32_t Rxx160_LPw32; // Low pass filtered frame energies
int32_t Rxx16_LPw32Max; // Keeps track of largest energy subframe
int32_t Rxx16_vectorw32[RXX_BUFFER_LEN]; // Array with subframe energies
int32_t Rxx16w32_array[2][5]; // Energy values of microphone signal
int32_t env[2][10]; // Envelope values of subframes

int16_t Rxx16pos; // Current position in the Rxx16_vectorw32
int16_t envSum; // Filtered scaled envelope in subframes
int16_t vadThreshold; // Threshold for VAD decision
int16_t inActive; // Inactive time in milliseconds
int16_t msTooLow; // Milliseconds of speech at a too low level
int16_t msTooHigh; // Milliseconds of speech at a too high level
int16_t changeToSlowMode; // Change to slow mode after some time at target
int16_t firstCall; // First call to the process-function
int16_t msZero; // Milliseconds of zero input
int16_t msecSpeechOuterChange; // Min ms of speech between volume changes
int16_t msecSpeechInnerChange; // Min ms of speech between volume changes
int16_t activeSpeech; // Milliseconds of active speech
int16_t muteGuardMs; // Counter to prevent mute action
int16_t inQueue; // 10 ms batch indicator

// Microphone level variables
int32_t micRef; // Remember ref. mic level for virtual mic
uint16_t gainTableIdx; // Current position in virtual gain table
int32_t micGainIdx; // Gain index of mic level to increase slowly
int32_t micVol; // Remember volume between frames
int32_t maxLevel; // Max possible vol level, incl dig gain
int32_t maxAnalog; // Maximum possible analog volume level
int32_t maxInit; // Initial value of "max"
int32_t minLevel; // Minimum possible volume level
int32_t minOutput; // Minimum output volume level
int32_t zeroCtrlMax; // Remember max gain => don't amp low input
int32_t lastInMicLevel;

int16_t scale; // Scale factor for internal volume levels
#ifdef MIC_LEVEL_FEEDBACK
int16_t numBlocksMicLvlSat;
uint8_t micLvlSat;
#endif
// Structs for VAD and digital_agc
AgcVad vadMic;
DigitalAgc digitalAgc;

#ifdef WEBRTC_AGC_DEBUG_DUMP
FILE* fpt;
FILE* agcLog;
int32_t fcount;
#endif

int16_t lowLevelSignal;
} LegacyAgc;
支付宝打赏 微信打赏 QQ钱包打赏

感觉不错?欢迎给我 打个赏~我将不胜感激!