WebRTC_AGC——agc.h基础讲解(1)

// 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;
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值