// allpass filter coefficients. // 全通滤波器系数
static const uint16_t kResampleAllpass1[3] = { 3284, 24441, 49528 }; // 全通滤波器1的系数
static const uint16_t kResampleAllpass2[3] = { 12199, 37471, 60255 }; // 全通滤波器2的系数
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; // VAD(语音活动检测)结构体,总共54字节
typedef struct {
int32_t capacitorSlow; // 慢电容器
int32_t capacitorFast; // 快电容器
int32_t gain; // 增益
int32_t gainTable[32]; // 增益表
int16_t gatePrevious; // 上一个门限
int16_t agcMode; // AGC模式
AgcVad vadNearend; // 近端VAD
AgcVad vadFarend; // 远端VAD
#ifdef WEBRTC_AGC_DEBUG_DUMP
FILE* logFile; // 日志文件
int frameCounter; // 帧计数器
#endif
} DigitalAgc; // 数字AGC结构体
// 初始化数字AGC实例
// digitalAgcInst: 指向DigitalAgc结构体实例的指针
// agcMode: AGC模式
int32_t WebRtcAgc_InitDigital(DigitalAgc *digitalAgcInst, int16_t agcMode);
// 处理数字AGC
// digitalAgcInst: 指向DigitalAgc结构体实例的指针
// inNear: 指向近端输入信号的指针数组
// num_bands: 输入信号的频带数量
// out: 指向处理后输出信号的指针数组
// FS: 采样率
// lowLevelSignal: 低电平信号标志
int32_t WebRtcAgc_ProcessDigital(DigitalAgc *digitalAgcInst,
const int16_t *const *inNear,
size_t num_bands,
int16_t *const *out,
uint32_t FS,
int16_t lowLevelSignal);
// 向数字AGC添加远端信号
// digitalAgcInst: 指向DigitalAgc结构体实例的指针
// inFar: 指向远端输入信号的指针
// nrSamples: 输入信号的样本数量
int32_t WebRtcAgc_AddFarendToDigital(DigitalAgc *digitalAgcInst,
const int16_t *inFar,
size_t nrSamples);
// 初始化VAD(声音活动检测)
// vadInst: 指向AgcVad结构体实例的指针
void WebRtcAgc_InitVad(AgcVad *vadInst);
// 处理VAD
// vadInst: VAD状态(指向AgcVad结构体实例的指针)
// in: 指向输入语音信号的指针
// nrSamples: 输入信号的样本数量
int16_t WebRtcAgc_ProcessVad(AgcVad *vadInst, // (i) VAD状态
const int16_t *in, // (i) 语音信号
size_t nrSamples); // (i) 样本数量
// 计算增益表
// gainTable: 增益表,以Q16格式
// compressionGaindB: 压缩增益,单位为dB
// targetLevelDbfs: 目标电平,单位为dBFS
// limiterEnable: 限幅器启用标志
// analogTarget: 模拟目标
int32_t WebRtcAgc_CalculateGainTable(int32_t *gainTable, // Q16
int16_t compressionGaindB, // Q0 (单位为dB)
int16_t targetLevelDbfs, // Q0 (单位为dBFS)
uint8_t limiterEnable,
int16_t analogTarget);
// 错误定义
#define AGC_UNSPECIFIED_ERROR 18000 // 未指定错误
#define AGC_UNSUPPORTED_FUNCTION_ERROR 18001 // 不支持的功能错误
#define AGC_UNINITIALIZED_ERROR 18002 // 未初始化错误
#define AGC_NULL_POINTER_ERROR 18003 // 空指针错误
#define AGC_BAD_PARAMETER_ERROR 18004 // 错误参数错误
// 警告定义
#define AGC_BAD_PARAMETER_WARNING 18050 // 错误参数警告
// AGC模式枚举
enum {
kAgcModeUnchanged, // AGC模式未改变
kAgcModeAdaptiveAnalog, // 自适应模拟AGC模式
kAgcModeAdaptiveDigital, // 自适应数字AGC模式
kAgcModeFixedDigital // 固定数字AGC模式
};
// 布尔值枚举
enum {
kAgcFalse = 0, kAgcTrue // AGC布尔值
};
// WebRTC AGC配置结构体
typedef struct {
int16_t targetLevelDbfs; // 目标电平,单位为dBFS,默认为3(-3 dBOv)
int16_t compressionGaindB; // 压缩增益,单位为dB,默认为9 dB
uint8_t limiterEnable; // 限幅器启用,默认为开启(kAgcTrue)
} WebRtcAgcConfig;
/*
* 此函数分析传递给远端的样本数量并产生可能出现的任何错误代码。
*
* 输入:
* - agcInst : AGC实例。
* - samples : 输入向量中的样本数量。
*
* 返回值:
* : 0 - 正常操作。
* : -1 - 错误。
*/
int WebRtcAgc_GetAddFarendError(void *state, size_t samples);
/*
* 此函数处理一个10毫秒的远端语音帧以确定是否存在活动语音。输入语音向量的长度必须以样本数给出
* (当FS=8000时为80,当FS=16000、FS=32000或FS=48000时为160)。
*
* 输入:
* - agcInst : AGC实例。
* - inFar : 远端输入语音向量
* - samples : 输入向量中的样本数量
*
* 返回值:
* : 0 - 正常操作。
* : -1 - 错误
*/
int WebRtcAgc_AddFarend(void *agcInst, const int16_t *inFar, size_t samples);
/*
* 此函数处理一个10毫秒的麦克风语音帧以确定是否存在活动语音。输入语音向量的长度必须以样本数给出
* (当FS=8000时为80,当FS=16000、FS=32000或FS=48000时为160)。对于非常低的输入级别,通过乘法增加输入信号的级别
* 并覆写inMic[]中的样本。
*
* 在对近端麦克风信号进行任何进一步处理之前,应调用此函数。
*
* 输入:
* - agcInst : AGC实例。
* - inMic : 每个频带的麦克风输入语音向量
* - num_bands : 输入向量中的频带数量
* - samples : 输入向量中的样本数量
*
* 返回值:
* : 0 - 正常操作。
* : -1 - 错误
*/
int WebRtcAgc_AddMic(void *agcInst,
int16_t *const *inMic,
size_t num_bands,
size_t samples);
/*
* 此函数用虚拟麦克风替换模拟麦克风。它是应用于输入信号的数字增益,在agcAdaptiveDigital模式下使用,
* 在该模式下没有可调的麦克风级别。输入语音向量的长度必须以样本数给出
* (当FS=8000时为80,当FS=16000、FS=32000或FS=48000时为160)。
*
* 输入:
* - agcInst : AGC实例。
* - inMic : 每个频带的麦克风输入语音向量
* - num_bands : 输入向量中的频带数量
* - samples : 输入向量中的样本数量
* - micLevelIn : 麦克风的输入级别(静态)
*
* 输出:
* - inMic : 处理后的麦克风输出(低频带)
* - inMic_H : 处理后的麦克风输出(高频带)
* - micLevelOut : 处理后的麦克风级别调整
*
* 返回值:
* : 0 - 正常操作。
* : -1 - 错误
*/
int WebRtcAgc_VirtualMic(void *agcInst,
int16_t *const *inMic,
size_t num_bands,
size_t samples,
int32_t micLevelIn,
int32_t *micLevelOut);
/*
* 此函数处理一个10毫秒的帧并调整(标准化)增益,包括模拟和数字增益。增益调整只在语音活动期间进行。
* 语音向量的长度必须以样本数给出(当FS=8000时为80,当FS=16000、FS=32000或FS=48000时为160)。
* echo参数可用于确保AGC在存在回声的情况下不会向上调整。
*
* 在处理近端麦克风信号之后,无论如何,在任何回声消除之后,都应调用此函数。
*
* 输入:
* - agcInst : AGC实例
* - inNear : 每个频带的近端输入语音向量
* - num_bands : 输入/输出向量中的频带数量
* - samples : 输入/输出向量中的样本数量
* - inMicLevel : 当前麦克风音量级别
* - echo : 如果传递给add_mic的信号几乎可以肯定不含回声,则设置为0;否则设置为1。如果你对回声没有信息,设置为0。
*
* 输出:
* - outMicLevel : 调整后的麦克风音量级别
* - out : 调整增益后的近端语音向量,可能与输入向量相同。
* - saturationWarning : 返回值为1表示发生了饱和事件,音量无法进一步降低。否则将设置为0。
*
* 返回值:
* : 0 - 正常操作。
* : -1 - 错误
*/
int WebRtcAgc_Process(void *agcInst,
const int16_t *const *inNear,
size_t num_bands,
size_t samples,
int16_t *const *out,
int32_t inMicLevel,
int32_t *outMicLevel,
int16_t echo,
uint8_t *saturationWarning);
/*
* 此函数设置配置参数(targetLevelDbfs、compressionGaindB和limiterEnable)。
*
* 输入:
* - agcInst : AGC实例
* - config : 配置结构体
*
* 输出:
*
* 返回值:
* : 0 - 正常操作。
* : -1 - 错误
*/
int WebRtcAgc_set_config(void *agcInst, WebRtcAgcConfig config);
/*
* 此函数返回配置参数(targetLevelDbfs、compressionGaindB和limiterEnable)。
*
* 输入:
* - agcInst : AGC实例
*
* 输出:
* - config : 配置结构体
*
* 返回值:
* : 0 - 正常操作。
* : -1 - 错误
*/
int WebRtcAgc_get_config(void *agcInst, WebRtcAgcConfig *config);
/*
* 此函数创建并返回一个AGC实例,该实例将包含一个(双工)通道的状态信息。
*/
void *WebRtcAgc_Create(void);
/*
* 此函数释放在开始时创建的AGC实例。
*
* 输入:
* - agcInst : AGC实例。
*/
void WebRtcAgc_Free(void *agcInst);
/*
* 此函数初始化一个AGC实例。
*
* 输入:
* - agcInst : AGC实例。
* - minLevel : 最小可能的麦克风级别
* - maxLevel : 最大可能的麦克风级别
* - agcMode : 0 - 未改变
* : 1 - 自适应模拟自动增益控制 -3dBOv
* : 2 - 自适应数字自动增益控制 -3dBOv
* : 3 - 固定数字增益 0dB
* - fs : 采样频率
*
* 返回值 : 0 - 正常
* -1 - 错误
*/
int WebRtcAgc_Init(void *agcInst,
int32_t minLevel,
int32_t maxLevel,
int16_t agcMode,
uint32_t fs);
/* 模拟自动增益控制变量:
* 常量声明(内部限制在这些限制内部不进行更改)
* 开始时,范围较窄,一旦测量'Rxx160_LP'在其内部,范围就会扩大。
* 目前的起始限制是-22.2+/-1dBm0,最终限制是-22.2+/-2.5dBm0。
* 这些水平使得语音信号趋向于-25.4dBm0(-31.4dBov)。
* 通过使用具有所需信号级别的文件运行AGC,然后将Rxx160_LP绘制在由
* out=10*log10(in/260537279.7)定义的dBm0域中来创建这些限制;
* 将目标级别设置为我们的测量Rxx160_LP的平均水平。
* 记住,这些级别是以16为一个块的Q(-7)。(示例matlab代码:round(db2pow(-21.2)*16/2^7))
*/
#define RXX_BUFFER_LEN 10 // 定义Rxx缓冲区长度为10
static const int16_t kMsecSpeechInner = 520; // 定义内部语音毫秒数为520,这是在没有变化发生的内部限制范围内的时间
static const int16_t kMsecSpeechOuter = 340; // 定义外部语音毫秒数为340,这是开始时较窄的范围的时间
static const int16_t kNormalVadThreshold = 400; // 定义正常的语音活动检测(VAD)阈值为400
static const int16_t kAlphaShortTerm = 6; // 短期α系数,1 >> 6 = 0.0156,表示短期平滑的快速程度
static const int16_t kAlphaLongTerm = 10; // 长期α系数,1 >> 10 = 0.000977,表示长期平滑的快速程度
typedef struct {
// 可配置参数/变量
uint32_t fs; // 采样频率
int16_t compressionGaindB; // 固定增益水平,单位为分贝(dB)
int16_t targetLevelDbfs; // 信号包络的目标电平,单位为负分贝相对于满量程(-dBfs),默认为-3
int16_t agcMode; // 硬编码模式(adaptAna/adaptDig/fixedDig)
uint8_t limiterEnable; // 是否启用限幅器(开/关,默认关闭)
WebRtcAgcConfig defaultConfig; // 默认AGC配置
WebRtcAgcConfig usedConfig; // 使用中的AGC配置
// 通用变量
int16_t initFlag; // 初始化标志
int16_t lastError; // 最后的错误码
// 目标电平参数
// 基于上述参数:analogTargetLevel = round((32767*10^(-22/20))^2*16/2^7)
int32_t analogTargetLevel; // 目标电平,-22 dBfs
int32_t startUpperLimit; // 开始的上限,-21 dBfs
int32_t startLowerLimit; // 开始的下限,-23 dBfs
int32_t upperPrimaryLimit; // 主要上限,-20 dBfs
int32_t lowerPrimaryLimit; // 主要下限,-24 dBfs
int32_t upperSecondaryLimit; // 次要上限,-17 dBfs
int32_t lowerSecondaryLimit; // 次要下限,-27 dBfs
uint16_t targetIdx; // 对应目标电平的表格索引
#ifdef MIC_LEVEL_FEEDBACK
uint16_t targetIdxOffset; // 表格索引偏移,用于电平补偿
#endif
int16_t analogTarget; // 数字参考电平,ENV比例尺度
// 模拟AGC特定变量
int32_t filterState[8]; // 用于wb到nb的降采样滤波器状态
int32_t upperLimit; // 麦克风能量上限
int32_t lowerLimit; // 麦克风能量下限
int32_t Rxx160w32; // 一帧的平均能量
int32_t Rxx16_LPw32; // 子帧能量的低通滤波结果
int32_t Rxx160_LPw32; // 帧能量的低通滤波结果
int32_t Rxx16_LPw32Max; // 存储最大子帧能量
int32_t Rxx16_vectorw32[RXX_BUFFER_LEN]; // 子帧能量数组
int32_t Rxx16w32_array[2][5]; // 麦克风信号的能量值
int32_t env[2][10]; // 子帧的包络值
int16_t Rxx16pos; // Rxx16_vectorw32当前位置
int16_t envSum; // 子帧中过滤后的缩放包络
int16_t vadThreshold; // VAD决策阈值
int16_t inActive; // 不活跃的时间,单位为毫秒
int16_t msTooLow; // 语音电平过低的毫秒数
int16_t msTooHigh; // 语音电平过高的毫秒数
int16_t changeToSlowMode; // 在目标电平一段时间后切换到慢速模式
int16_t firstCall; // 第一次调用处理函数的标志
int16_t msZero; // 输入为零的毫秒数
int16_t msecSpeechOuterChange; // 体积变化之间的最小语音毫秒数
int16_t msecSpeechInnerChange; // 体积变化之间的最小语音毫秒数
int16_t activeSpeech; // 活跃语音的毫秒数
int16_t muteGuardMs; // 用于防止静音操作的计数器
int16_t inQueue; // 10毫秒批处理指示
// 麦克风电平变量
int32_t micRef; // 虚拟麦克风的参考电平记忆
uint16_t gainTableIdx; // 虚拟增益表中的当前位置
int32_t micGainIdx; // 微调麦克风电平的增益索引
int32_t micVol; // 记忆帧之间的音量
int32_t maxLevel; // 包括数字增益的最大可能音量电平
int32_t maxAnalog; // 最大可能的模拟音量电平
int32_t maxInit; // “max”的初始值
int32_t minLevel; // 最小可能音量电平
int32_t minOutput; // 最小输出音量电平
int32_t zeroCtrlMax; // 记忆最大增益=>不增强低输入
int32_t lastInMicLevel;
int16_t scale; // 内部音量电平的缩放因子
#ifdef MIC_LEVEL_FEEDBACK
int16_t numBlocksMicLvlSat;
uint8_t micLvlSat;
#endif
// 用于VAD和数字AGC的结构体
AgcVad vadMic;
DigitalAgc digitalAgc;
#ifdef WEBRTC_AGC_DEBUG_DUMP
FILE* fpt; // 用于调试输出的文件指针
FILE* agcLog; // AGC日志文件的文件指针
int32_t fcount; // 文件计数器
#endif
int16_t lowLevelSignal; // 低电平信号标志
} LegacyAgc;