当前位置:首页 > 未分类 > 正文内容

speex_agc

2025-09-30 | 分类:未分类 | 评论:0人 | 浏览:120次

嗯,用户让我分析Speex AGC的原理和公式推导,还提供了代码。首先我得确定用户的需求是什么。可能他们是在做音频处理相关的开发,比如语音通信或音频增强,需要理解AGC的工作原理来调试或优化代码。

用户提供的代码是Speex预处理的一部分,看起来是计算自动增益控制的。我得先回忆一下AGC的基本原理,然后结合代码解释。用户可能不仅想知道代码在做什么,还想了解背后的数学原理,比如为什么用特定的公式,参数如何调整。

首先,我得解析代码中的关键部分。比如loudness的计算,那里用了功率谱和权重,然后取平方根,这应该是计算感知响度。然后看到有target_gain的计算,这里用了指数和比值,可能是在调整增益以达到目标水平。

然后要考虑用户的身份,可能是开发者或研究人员,对信号处理有一定基础但不一定深入。所以需要既解释原理,又联系代码,避免太学术化。同时,用户可能想知道如何调整参数来适应不同的场景,比如防止增益变化太快或太慢。

另外,代码中有一些条件判断,比如Pframe大于0.3时才更新,这可能是为了避免在静音或噪声时过度调整。需要解释这些阈值的选择和影响。

最后,要确保推导过程清晰,步骤详细,让用户能跟着公式理解代码的每一步。同时指出关键参数如LOUDNESS_EXP的作用,以及如何根据实际需求调整它们。

好的,我们来详细分析一下 Speex 预处理器中 AGC (Automatic Gain Control) 模块的原理、公式推导,并逐行解读提供的代码。

1. AGC 核心原理
AGC 的目标是自动调整信号的增益,使其输出电平稳定在一个预设的目标水平上,无论输入信号的音量如何起伏。这可以改善语音通信的质量,避免声音忽大忽小。

Speex 的 AGC 实现基于以下核心思想:

估计瞬时响度:计算当前音频帧的“响度”或能量。这不仅仅是简单的能量计算,而是更接近人耳感知的响度,通常通过对频域功率谱进行加权求和来实现。

平滑响度估计:使用一个时间常数较大的一阶无限脉冲响应 (IIR) 低通滤波器(或称指数平滑)对瞬时响度进行平滑处理,得到一个长期的、稳定的平均响度估计。这避免了增益因信号的短暂突变(如一个突然的爆破音)而剧烈波动。

计算目标增益:将预设的目标电平与平滑后的长期响度估计进行比较,计算出将长期响度提升/降低到目标水平所需的增益。

应用增益限制:对计算出的目标增益进行限制,确保其变化不会过快(通过 max_increase_step 和 max_decrease_step 限制)且不会超过设定的最大值 (max_gain) 和初始最大值 (init_max)。

应用增益:将最终计算出的增益乘以时域或频域的信号。

2. 关键公式推导
让我们分解代码中的关键计算步骤。

a) 计算瞬时感知响度 (loudness)
c
for (i=2;i<N;i++)
{
loudness += 2.f*N*st->ps[i]* st->loudness_weight[i];
}
loudness=sqrtf(loudness);
st->ps[i]:是当前帧的功率谱。

st->loudness_weight[i]:是一个频域加权函数,用于模拟人耳的频率响应(类似于 A-weighting 或 Z-weighting),使得计算出的响度更符合人耳的主观感受。低频和高频的权重通常较低。

2.f*N:是一个缩放因子。N 是 FFT 大小的一半(ps_size)。求和通常从 i=2 开始以避开直流分量。

sqrtf(loudness):对加权求和后的能量取平方根,将其从“能量”域转换回“幅度”域,便于后续与目标电平(通常也是幅度域)进行比较。

公式表示:
$L_{\text{instant}} = \sqrt{ \sum_{i=2}^{N-1} 2N \cdot \text{ps}[i] \cdot W[i] }$
其中 $W[i]$ 是 loudness_weight[i]。

b) 平滑响度估计(更新长期响度 st->loudness)
c
$$rate = .03*Pframe*Pframe;$$
$$st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP);$$
Pframe:是当前帧的语音概率(VAD 检测结果),值在 0 到 1 之间。这是一个关键创新点。只有当可能存在语音 (Pframe > 0.3) 时,才更新长期响度估计。这防止了在静音或噪声帧期间错误地调整基准电平。

rate:是平滑滤波器的自适应更新速率。它由 Pframe 控制。语音越确定 (Pframe 越高),更新速率越快,长期响度能更快地跟踪上说话人音量的变化。Pframe*Pframe 使其变化更平滑。

$$pow(AMP_SCALE*loudness, LOUDNESS_EXP)$$:这里对瞬时响度进行了一个非线性的映射。LOUDNESS_EXP 通常 > 1(例如 2),AMP_SCALE 是一个幅度缩放常量。这个指数操作进一步模拟了人耳对响度的非线性感知(例如,声音强度需要翻倍,感知响度才显著增加)。长期响度 st->loudness 存储的是 (AMP_SCALE * loudness)^LOUDNESS_EXP 的平滑值。

公式表示(非线性平滑):
$$\text{loudness}{\text{long-term}}^{(n)} = (1 – \alpha) \cdot \text{loudness}{\text{long-term}}^{(n-1)} + \alpha \cdot (C \cdot L_{\text{instant}})^{\beta}$$
其中 $$\alpha = 0.03 \cdot P_{\text{frame}}^2$$, $C$ 是 AMP_SCALE, $\beta$ 是 LOUDNESS_EXP。

st->loudness_accum 以相同的速率平滑一个常数 1,用于归一化,确保初始阶段不会因 rate 很小而导致 st->loudness 被低估。

c) 计算目标增益 (target_gain)
c
$$target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP);$$
这是最关键的公式。

st->agc_level:用户期望达到的目标输出电平(幅度域)。

st->loudness / st->loudness_accum:这近似等于 $(C \cdot L_{\text{instant}})^{\beta}$ 的长期平均值。让我们将其记为 $S$。

pow(S, -1.0f/LOUDNESS_EXP):这是对 $S$ 进行开 $\beta$ 次方并取倒数。
$S^{\frac{-1}{\beta}} = \frac{1}{\sqrt[\beta]{S}} \approx \frac{1}{C \cdot \text{(长期平均瞬时响度)}}$

最终推导:
$$\begin{align*}
G_{\text{target}} &= C \cdot L_{\text{target}} \cdot \left( \frac{S}{1} \right)^{\frac{-1}{\beta}} \
&\approx C \cdot L_{\text{target}} \cdot \frac{1}{C \cdot \overline{L_{\text{instant}}}} \
&= \frac{L_{\text{target}}}{\overline{L_{\text{instant}}}}
\end{align*}$$

结果非常直观:目标增益 = 目标电平 / 长期平均估计的输入响度。这正是 AGC 的核心思想。

AMP_SCALE 和 LOUDNESS_EXP 在计算过程中相互抵消了,但它们的存在使得中间的平滑过程更符合人耳的听觉特性。

d) 增益限制
计算出的 target_gain 不能直接使用,必须加以限制。

c
if (target_gain > st->max_increase_step*st->agc_gain)
target_gain = st->max_increase_step*st->agc_gain; // 增益最大提升倍数
if (target_gain < st->max_decrease_step*st->agc_gain && loudness < 10*st->prev_loudness)
target_gain = st->max_decrease_step*st->agc_gain; // 增益最大降低倍数(除非响度骤增10倍以上,防止剪切)
if (target_gain > st->max_gain)
target_gain = st->max_gain; // 绝对最大增益
if (target_gain > st->init_max)
target_gain = st->init_max; // 初始阶段的最大增益,会缓慢增长

st->agc_gain = target_gain; // 更新最终增益
这些限制保证了增益变化的稳定性和安全性。

3. 代码逐行分析
c
static void speex_compute_agc(SpeexPreprocessState *st, spx_word16_t Pframe, spx_word16_t *ft)
{
int i;
int N = st->ps_size; // 获取功率谱大小(FFT阶数/2 + 1)
float target_gain;
float loudness=1.f; // 初始化为1,避免除零错误,并作为基础值
float rate;

// 1. 计算当前帧的加权感知响度
for (i=2;i<N;i++) // 从2开始,跳过直流和可能的一个低频分量
{
// 对功率谱进行加权求和
loudness += 2.f*N*st->ps[i]* st->loudness_weight[i];
}
loudness=sqrtf(loudness); // 转换到幅度域

// 2. 更新长期响度估计(仅在可能有语音时)
if (Pframe>.3f) // 语音概率阈值
{
// 计算自适应的平滑系数rate,与语音概率相关
rate = .03*Pframe*Pframe;
// 核心:使用IIR滤波器平滑 (AMP_SCALE*loudness)^LOUDNESS_EXP
st->loudness = (1-rate)*st->loudness + (rate)*pow(AMP_SCALE*loudness, LOUDNESS_EXP);
// 用相同的rate平滑常数1,用于归一化
st->loudness_accum = (1-rate)*st->loudness_accum + rate;
// 在适应期后,缓慢提高初始最大增益限制
if (st->init_max < st->max_gain && st->nb_adapt > 20)
st->init_max *= 1.f + .1f*Pframe*Pframe;
}

// 3. 计算目标增益
// 公式: target_gain = AGC_TARGET_LEVEL * (长期平均的 (SCALED_LOUDNESS^EXP) ) ^ (-1/EXP)
target_gain = AMP_SCALE*st->agc_level*pow(st->loudness/(1e-4+st->loudness_accum), -1.0f/LOUDNESS_EXP);

// 4. 应用限制条件并更新最终增益
// 条件:当前帧很可能是语音,或者新计算出的增益比当前增益小(需要衰减)
if ((Pframe>.5 && st->nb_adapt > 20) || target_gain < st->agc_gain)
{
// 限制增益增加的速度
if (target_gain > st->max_increase_step*st->agc_gain)
target_gain = st->max_increase_step*st->agc_gain;
// 限制增益减少的速度,除非输入响度突然变得非常大(防止限制衰减导致剪切)
if (target_gain < st->max_decrease_step*st->agc_gain && loudness < 10*st->prev_loudness)
target_gain = st->max_decrease_step*st->agc_gain;
// 确保增益不超过绝对最大值
if (target_gain > st->max_gain)
target_gain = st->max_gain;
// 确保增益不超过初始最大值(在启动阶段较低)
if (target_gain > st->init_max)
target_gain = st->init_max;

// 更新全局AGC增益变量
st->agc_gain = target_gain;
}

// 5. 将增益应用到帧数据(ft是频域数据?也可能是时域)
for (i=0;i<2*N;i++) // 2*N,因为可能是复数频域数据(实部+虚部)或者时域帧长度是2N
ft[i] *= st->agc_gain;

// 6. 保存当前响度,用于下一帧的限制判断
st->prev_loudness = loudness;
}
总结
Speex 的 AGC 是一个精巧且鲁棒的实现,其特点在于:

感知加权:使用 loudness_weight 模拟人耳听觉。

非线性平滑:使用 LOUDNESS_EXP 指数平滑,更符合响度感知。

语音激活更新:使用 Pframe 控制长期响度的更新,仅在可能有语音时调整,避免了噪声对增益基准的影响。

多重安全限制:对增益的变化率和绝对值进行严格限制,保证稳定性。

自适应初始最大值:init_max 在启动后缓慢增加,提供了一个“软启动”过程,防止初始增益过大。

这个算法有效地将输入信号的长期响度归一化到用户设定的目标水平,同时确保了处理过程的自然和稳定。

# Speex 噪声估计与信噪比计算原理分析与公式推导

这段代码是 Speex 预处理器的核心部分,涉及噪声估计更新、后验信噪比和先验信噪比的计算。下面我将详细分析其原理和数学推导。

## 代码功能概述

这段代码主要完成以下任务:
1. 更新噪声估计
2. 计算总噪声估计(包括环境噪声、回声噪声和混响估计)
3. 计算后验信噪比 (a posteriori SNR)
4. 计算先验信噪比 (a priori SNR)

## 代码逐行分析

### 1. 噪声估计更新
“`c
for (i=0;i<N;i++)
{
if (!st->update_prob[i] || st->ps[i] < PSHR32(st->noise[i], NOISE_SHIFT))
st->noise[i] = MAX32(EXTEND32(0),MULT16_32_Q15(beta_1,st->noise[i]) + MULT16_32_Q15(beta,SHL32(st->ps[i],NOISE_SHIFT)));
}
“`

– 只有当 `update_prob[i]` 为假(即该频率点可能不是语音)或者当前功率小于噪声估计时,才更新噪声估计
– 使用指数平滑更新噪声估计:`noise[i] = β₁ * noise[i] + β * ps[i]`
– `NOISE_SHIFT` 可能是用于调整量纲的移位操作
– `beta_1` 和 `beta` 是平滑系数,通常满足 `beta_1 + beta = 1`

### 2. 滤波器组处理
“`c
filterbank_compute_bank32(st->bank, st->noise, st->noise+N);
“`

– 对噪声估计应用滤波器组,将线性频率刻度转换为感知相关的频率刻度
– 结果存储在 `st->noise+N` 开始的位置

### 3. 第一帧初始化
“`c
if (st->nb_adapt==1)
for (i=0;i<N+M;i++)
st->old_ps[i] = ps[i];
“`

– 如果是第一帧,将当前功率谱保存为旧功率谱

### 4. 信噪比计算
“`c
for (i=0;i<N+M;i++)
{
spx_word16_t gamma;
spx_word32_t tot_noise = ADD32(ADD32(ADD32(EXTEND32(1), PSHR32(st->noise[i],NOISE_SHIFT)) , st->echo_noise[i]) , st->reverb_estimate[i]);

st->post[i] = SUB16(DIV32_16_Q8(ps[i],tot_noise), QCONST16(1.f,SNR_SHIFT));
st->post[i]=MIN16(st->post[i], QCONST16(100.f,SNR_SHIFT));

gamma = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.89f,15),SQR16_Q15(DIV32_16_Q15(st->old_ps[i],ADD32(st->old_ps[i],tot_noise))));

st->prior[i] = EXTRACT16(PSHR32(ADD32(MULT16_16(gamma,MAX16(0,st->post[i])), MULT16_16(Q15_ONE-gamma,DIV32_16_Q8(st->old_ps[i],tot_noise))), 15));
st->prior[i]=MIN16(st->prior[i], QCONST16(100.f,SNR_SHIFT));
}
“`

## 原理分析与公式推导

### 1. 噪声估计更新

噪声估计使用指数平滑更新:

$$
N_i[t] = \beta_1 \cdot N_i[t-1] + \beta \cdot P_i[t]
$$

其中:
– $N_i[t]$ 是时间 t 时频率点 i 的噪声估计
– $P_i[t]$ 是时间 t 时频率点 i 的功率谱
– $\beta_1$ 和 $\beta$ 是平滑系数,满足 $\beta_1 + \beta = 1$

更新条件:
– 只有当该频率点可能不是语音 (`!update_prob[i]`) 或者当前功率小于噪声估计时,才更新噪声估计
– 这确保了噪声估计主要基于非语音帧或低功率帧

### 2. 总噪声估计

总噪声估计包括三个部分:
$$
N_{\text{total}} = 1 + N_{\text{ambient}} + N_{\text{echo}} + N_{\text{reverb}}
$$

其中:
– $N_{\text{ambient}}$ 是环境噪声估计
– $N_{\text{echo}}$ 是回声噪声估计
– $N_{\text{reverb}}$ 是混响估计
– 加 1 是为了避免除以零和数值稳定性

### 3. 后验信噪比 (a posteriori SNR)

后验信噪比定义为当前功率与总噪声的比值减 1:

$$
\gamma_i = \frac{P_i}{N_{\text{total},i}} – 1
$$

在代码中:
“`c
st->post[i] = DIV32_16_Q8(ps[i],tot_noise) – 1;
“`

后验信噪比反映了当前帧的信噪比情况。

### 4. 先验信噪比 (a priori SNR)

先验信噪比使用决策导向 (Decision-Directed) 方法计算:

$$
\xi_i = \alpha \cdot \max(0, \gamma_i) + (1 – \alpha) \cdot \frac{P_i^{\text{old}}}{N_{\text{total},i}}
$$

其中 $\alpha$ 是一个时变参数,计算为:

$$
\alpha = 0.1 + 0.89 \cdot \left(\frac{P_i^{\text{old}}}{P_i^{\text{old}} + N_{\text{total},i}}\right)^2
$$

在代码中:
“`c
gamma = 0.1 + 0.89 * (old_ps[i] / (old_ps[i] + tot_noise))^2;
st->prior[i] = gamma * max(0, post[i]) + (1 – gamma) * (old_ps[i] / tot_noise);
“`

### 5. 决策导向方法的数学推导

决策导向方法是语音增强中常用的先验信噪比估计方法,由 Ephraim 和 Malah 提出。

基本思想是先验信噪比可以通过后验信噪比和前一帧的先验信噪比组合得到:

$$
\xi_i[t] = \alpha \cdot \frac{|\hat{S}_i[t-1]|^2}{N_i[t]} + (1 – \alpha) \cdot \max(0, \gamma_i[t] – 1)
$$

其中:
– $\hat{S}_i[t-1]$ 是前一帧的语音估计
– $\alpha$ 是平滑因子,通常取 0.98

在 Speex 的实现中,对此方法进行了修改:
1. 使用自适应平滑因子 $\alpha$(代码中的 `gamma`)
2. 使用前一帧的功率谱而不是语音估计
3. 平滑因子计算为 $0.1 + 0.89 \cdot \left(\frac{P^{\text{old}}}{P^{\text{old}} + N}\right)^2$

这种修改使得:
– 当信噪比较高时($P^{\text{old}} \gg N$),$\alpha \approx 0.99$,更依赖前一帧的估计
– 当信噪比较低时($P^{\text{old}} \ll N$),$\alpha \approx 0.1$,更依赖当前的后验信噪比

### 6. 参数选择的意义

代码中的参数选择有特定意义:
– 0.1 和 0.89:确保 $\alpha$ 在 [0.1, 0.99] 范围内
– 平方操作:加强高信噪比时的依赖性,减弱低信噪比时的依赖性
– 最大值操作:确保先验信噪比非负

## 应用与意义

这些信噪比估计在语音增强中非常重要:

1. **后验信噪比**:用于计算谱增益函数,如维纳滤波器
$$
G_i = \frac{\xi_i}{1 + \xi_i}
$$

2. **先验信噪比**:用于更复杂的增益函数,如 MMSE 估计器
$$
G_i = \frac{\sqrt{\pi}}{2} \frac{\sqrt{\nu_i}}{\gamma_i} \exp\left(-\frac{\nu_i}{2}\right) \left[(1 + \nu_i) I_0\left(\frac{\nu_i}{2}\right) + \nu_i I_1\left(\frac{\nu_i}{2}\right)\right]
$$
其中 $\nu_i = \frac{\xi_i}{1 + \xi_i} \gamma_i$

3. **语音活动检测**:信噪比估计可用于检测语音是否存在

## 总结

这段代码实现了 Speex 预处理器的核心噪声估计和信噪比计算功能:

1. **噪声估计更新**:使用条件指数平滑更新噪声估计
2. **总噪声计算**:结合环境噪声、回声噪声和混响估计
3. **后验信噪比**:反映当前帧的信噪比情况
4. **先验信噪比**:使用改进的决策导向方法估计,具有自适应平滑因子

这些计算为后续的语音增强算法(如谱减法、维纳滤波等)提供了关键参数。算法的性能取决于多个因素:
– 噪声估计的准确性
– 信噪比估计的可靠性
– 参数选择的合理性

Speex 的实现通过经验参数和自适应机制,在各种环境下都能提供相对稳定的性能。

# Speex 语音增强算法原理分析与公式推导

这段代码是 Speex 预处理器的核心部分,实现了基于 Ephraim-Malah 算法的语音增强处理。下面我将详细分析其原理和数学推导。

## 代码功能概述

这段代码主要完成以下任务:
1. 平滑先验信噪比估计
2. 计算帧级语音存在概率
3. 计算有效的回声抑制参数
4. 计算增益下限
5. 在 Bark 尺度上计算 Ephraim-Malah 增益和语音存在概率
6. 将增益转换到线性频率尺度
7. 应用增益并进行逆 FFT

## 代码逐行分析

### 1. 平滑先验信噪比
“`c
st->zeta[0] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[0]), MULT16_16(QCONST16(.3f,15),st->prior[0])),15);
for (i=1;i<N-1;i++)
st->zeta[i] = PSHR32(ADD32(ADD32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.15f,15),st->prior[i])),
MULT16_16(QCONST16(.075f,15),st->prior[i-1])), MULT16_16(QCONST16(.075f,15),st->prior[i+1])),15);
for (i=N-1;i<N+M;i++)
st->zeta[i] = PSHR32(ADD32(MULT16_16(QCONST16(.7f,15),st->zeta[i]), MULT16_16(QCONST16(.3f,15),st->prior[i])),15);
“`
– 对先验信噪比进行时空平滑
– 对边缘频率点使用 70% 历史值 + 30% 当前值
– 对中间频率点使用 70% 历史值 + 15% 当前值 + 7.5% 左邻 + 7.5% 右邻

### 2. 计算帧级语音存在概率
“`c
Zframe = 0;
for (i=N;i<N+M;i++)
Zframe = ADD32(Zframe, EXTEND32(st->zeta[i]));
Pframe = QCONST16(.1f,15)+MULT16_16_Q15(QCONST16(.899f,15),qcurve(DIV32_16(Zframe,st->nbands)));
“`
– 计算 Bark 尺度上先验信噪比的平均值
– 通过 qcurve 函数将其映射到语音存在概率
– 基础概率为 0.1,最大可达到约 0.999

### 3. 计算有效回声抑制
“`c
effective_echo_suppress = EXTRACT16(PSHR32(ADD32(MULT16_16(SUB16(Q15_ONE,Pframe), st->echo_suppress), MULT16_16(Pframe, st->echo_suppress_active)),15));
“`
– 根据语音存在概率在两种回声抑制参数之间插值
– 无语音时使用 `echo_suppress`,有语音时使用 `echo_suppress_active`

### 4. 计算增益下限
“`c
compute_gain_floor(st->noise_suppress, effective_echo_suppress, st->noise+N, st->echo_noise+N, st->gain_floor+N, M);
“`
– 根据噪声抑制和回声抑制参数计算增益下限
– 确保增益不会过低,避免过度抑制

### 5. Bark 尺度上的 Ephraim-Malah 增益计算
“`c
for (i=N;i<N+M;i++)
{
prior_ratio = PDIV32_16(SHL32(EXTEND32(st->prior[i]), 15), ADD16(st->prior[i], SHL32(1,SNR_SHIFT)));
theta = MULT16_32_P15(prior_ratio, QCONST32(1.f,EXPIN_SHIFT)+SHL32(EXTEND32(st->post[i]),EXPIN_SHIFT-SNR_SHIFT));

MM = hypergeom_gain(theta);
st->gain[i] = EXTRACT16(MIN32(Q15_ONE, MULT16_32_Q15(prior_ratio, MM)));
st->old_ps[i] = MULT16_32_P15(QCONST16(.2f,15),st->old_ps[i]) + MULT16_32_P15(MULT16_16_P15(QCONST16(.8f,15),SQR16_Q15(st->gain[i])),ps[i]);

P1 = QCONST16(.199f,15)+MULT16_16_Q15(QCONST16(.8f,15),qcurve (st->zeta[i]));
q = Q15_ONE-MULT16_16_Q15(Pframe,P1);

// 计算考虑语音存在概率的增益
// …
}
“`
– 计算先验比:`prior_ratio = ξ / (1 + ξ)`,其中 ξ 是先验信噪比
– 计算 θ 参数:`θ = prior_ratio * (1 + γ)`,其中 γ 是后验信噪比
– 使用超几何函数计算 MMSE 增益
– 更新旧功率谱估计
– 计算基于 Bark 子带的语音存在概率 P1
– 计算语音不存在概率 q

### 6. 转换到线性频率尺度
“`c
filterbank_compute_psd16(st->bank,st->gain2+N, st->gain2);
filterbank_compute_psd16(st->bank,st->gain+N, st->gain);
“`
– 将 Bark 尺度上的增益转换到线性频率尺度

### 7. 线性频率上的增益计算和应用
“`c
for (i=0;i<N;i++)
{
// 计算维纳滤波增益和超几何增益
// …

// 约束增益与 Bark 尺度增益一致
if (MULT16_16_Q15(QCONST16(.333f,15),g) > st->gain[i])
g = MULT16_16(3,st->gain[i]);

// 应用增益下限
if (st->gain[i] < st->gain_floor[i])
st->gain[i] = st->gain_floor[i];

// 考虑语音存在概率的最终增益
tmp = MULT16_16_P15(p,spx_sqrt(SHL32(EXTEND32(st->gain[i]),15))) + MULT16_16_P15(SUB16(Q15_ONE,p),spx_sqrt(SHL32(EXTEND32(st->gain_floor[i]),15)));
st->gain2[i]=SQR16_Q15(tmp);
}
“`
– 计算线性频率上的增益
– 确保增益与 Bark 尺度增益一致
– 应用增益下限
– 根据语音存在概率计算最终增益

### 8. 应用增益和逆 FFT
“`c
for (i=1;i<N;i++)
{
st->ft[2*i-1] = MULT16_16_P15(st->gain2[i],st->ft[2*i-1]);
st->ft[2*i] = MULT16_16_P15(st->gain2[i],st->ft[2*i]);
}
spx_ifft(st->fft_lookup, st->ft, st->frame);
for (i=0;i<2*N;i++)
st->frame[i] = PSHR16(st->frame[i], st->frame_shift);
“`
– 将增益应用到频域数据
– 执行逆 FFT 将信号转换回时域
– 进行幅度缩放

## 原理分析与公式推导

### 1. Ephraim-Malah 算法

Ephraim-Malah 算法是一种基于 MMSE(最小均方误差)的语音增强算法,其核心是计算最优增益函数。

#### 先验比计算
$$
\text{prior\_ratio} = \frac{\xi}{1 + \xi}
$$
其中 $\xi$ 是先验信噪比。

#### θ 参数计算
$$
\theta = \frac{\xi}{1 + \xi} (1 + \gamma)
$$
其中 $\gamma$ 是后验信噪比。

#### 超几何增益
$$
G_{\text{MMSE}} = \frac{\sqrt{\pi}}{2} \frac{\sqrt{\nu}}{\gamma} \exp\left(-\frac{\nu}{2}\right) \left[(1 + \nu) I_0\left(\frac{\nu}{2}\right) + \nu I_1\left(\frac{\nu}{2}\right)\right]
$$
其中 $\nu = \frac{\xi}{1 + \xi} \gamma$,$I_0$ 和 $I_1$ 是修正贝塞尔函数。

在代码中,这个计算由 `hypergeom_gain` 函数完成。

### 2. 语音存在概率

#### 帧级语音存在概率
$$
P_{\text{frame}} = 0.1 + 0.899 \cdot Q\left(\frac{1}{M} \sum_{i=N}^{N+M-1} \zeta_i\right)
$$
其中 $Q$ 是 `qcurve` 函数,$\zeta_i$ 是平滑后的先验信噪比。

#### 子带语音存在概率
$$
P_1 = 0.199 + 0.8 \cdot Q(\zeta_i)
$$
其中 $\zeta_i$ 是第 i 个子带的平滑先验信噪比。

#### 语音不存在概率
$$
q = 1 – P_{\text{frame}} \cdot P_1
$$

### 3. 考虑语音存在概率的增益

#### 最终增益计算
$$
G_{\text{final}} = \left[p \cdot \sqrt{G} + (1 – p) \cdot \sqrt{G_{\text{floor}}}\right]^2
$$
其中:
– $G$ 是 MMSE 增益
– $G_{\text{floor}}$ 是增益下限
– $p$ 是语音存在概率

这种计算方式确保了在语音可能存在时使用较大的增益,在语音可能不存在时使用较小的增益。

### 4. 增益下限计算

增益下限基于噪声抑制和回声抑制参数:
$$
G_{\text{floor}} = f(\text{noise\_suppress}, \text{echo\_suppress}, N, N_{\text{echo}})
$$
其中 $N$ 是噪声估计,$N_{\text{echo}}$ 是回声估计。

### 5. 时空平滑

先验信噪比的时空平滑减少了估计的方差:
$$
\zeta_i[t] = 0.7 \cdot \zeta_i[t-1] + 0.3 \cdot \xi_i[t] \quad \text{(边缘频率点)}
$$
$$
\zeta_i[t] = 0.7 \cdot \zeta_i[t-1] + 0.15 \cdot \xi_i[t] + 0.075 \cdot \xi_{i-1}[t] + 0.075 \cdot \xi_{i+1}[t] \quad \text{(中间频率点)}
$$

这种平滑结合了时间上的指数平滑和空间上的邻域平滑,提高了估计的稳定性。

## 算法特点

1. **多尺度处理**:在 Bark 尺度和线性频率尺度上分别处理,充分利用感知特性
2. **语音存在概率**:同时使用帧级和子带级的语音存在概率,提高决策准确性
3. **增益约束**:确保 Bark 尺度和线性频率尺度的增益一致
4. **增益下限**:防止过度抑制,保持背景噪声的自然性
5. **时空平滑**:减少估计方差,提高算法稳定性

## 总结

这段代码实现了 Speex 预处理器的核心语音增强功能,基于 Ephraim-Malah 算法并进行了多项改进:

1. **多尺度处理**:在感知相关的 Bark 尺度和线性频率尺度上分别处理
2. **语音存在概率**:使用帧级和子带级的语音存在概率指导增益计算
3. **增益计算**:结合 MMSE 增益、增益下限和语音存在概率计算最终增益
4. **时空平滑**:通过时空平滑提高估计的稳定性
5. **增益约束**:确保不同尺度上的增益一致性

这种算法在各种环境下都能提供良好的语音增强效果,同时保持背景噪声的自然性和语音质量。算法的性能取决于多个参数的选择,这些参数通常通过大量实验优化得到。

好的,我们来详细推导和解释经典的 Ephraim-Malah 噪声抑制算法。这是一个非常优美且强大的算法,是现代语音增强领域的基石。

### 1. 问题设定与基本假设

Ephraim-Malah 算法处理的是频域信号。我们假设已经通过短时傅里叶变换(STFT)将含噪语音信号分解为多个频带(frequency bin)和帧(frame)。

**定义:**
* $Y(k, m)$: 观测到的含噪语音的 **复频谱**。其中 $k$ 是频率索引,$m$ 是时间帧索引。
* $X(k, m)$: 我们想要估计的 **纯净语音的复频谱**。
* $D(k, m)$: **噪声的复频谱**。
* 因此有: $Y(k, m) = X(k, m) + D(k, m)$

**核心假设:**
1. **加性噪声**:噪声与语音是加性的(如上式所示)。
2. **统计独立性**:语音 $X$ 和噪声 $D$ 是统计独立的零均值随机过程。
3. **高斯分布**:$X(k, m)$ 和 $D(k, m)$ 的实部和虚部均服从高斯分布。也就是说,$X(k, m)$ 和 $D(k, m)$ 都是**复高斯随机变量**。
* $X \sim \mathcal{N}_c(0, \lambda_x(k, m))$,其中 $\lambda_x(k, m) = E[|X(k, m)|^2]$ 是**语音的功率谱**(我们需要估计的量)。
* $D \sim \mathcal{N}_c(0, \lambda_d(k, m))$,其中 $\lambda_d(k, m) = E[|D(k, m)|^2]$ 是**噪声的功率谱**(可以通过无语音段估计得到)。

### 2. 两个关键的信噪比 (SNR)

算法依赖于两个重要的信噪比定义:

1. **先验信噪比 (A Priori SNR) – $\xi(k, m)$**
* **定义**:当前帧语音功率与噪声功率的比值。
$\xi(k, m) = \frac{\lambda_x(k, m)}{\lambda_d(k, m)}$
* **物理意义**:在**当前帧数据 $Y(k, m)$ 被观测到之前**,我们对信噪比的最佳估计。它代表了“我们预期信噪比有多高”。
* **估计方法**:无法直接获得,需要使用**判决引导(Decision-Directed, DD)** 法进行估计:
$\hat{\xi}(k, m) = \alpha \frac{|\hat{X}(k, m-1)|^2}{\lambda_d(k, m-1)} + (1-\alpha) \max(\gamma(k, m) – 1, 0)$
其中 $\alpha$ 是一个平滑因子(通常 ~0.98),$\hat{X}(k, m-1)$ 是上一帧的语音频谱估计值。第一项是上一帧的信噪比,第二项是当前帧的瞬时信噪比(见后文)的修正。

2. **后验信噪比 (A Posteriori SNR) – $\gamma(k, m)$**
* **定义**:当前观测功率与噪声功率的比值。
$\gamma(k, m) = \frac{|Y(k, m)|^2}{\lambda_d(k, m)}$
* **物理意义**:在**当前帧数据 $Y(k, m)$ 被观测到之后**,计算出的信噪比。它是一个**瞬时**的、**有偏**的估计(因为 $|Y|^2 = |X+D|^2$)。

### 3. MMSE 估计器推导

我们的目标是找到一个频域增益 $G(k, m)$,使得估计的纯净语音频谱 $\hat{X}(k, m)$ 与真实纯净语音频谱 $X(k, m)$ 的均方误差最小:
$\hat{X}(k, m) = G(k, m) \cdot Y(k, m)$
$G(k, m) = \arg\min_G E[|X(k, m) – G \cdot Y(k, m)|^2]$

根据MMSE准则,对于复频谱,最优估计是**条件均值**:
$\hat{X} = E[X | Y]$

我们需要计算在已知观测值 $Y$ 的条件下,$X$ 的期望。由于 $X$ 和 $Y$ 是联合高斯的,我们可以利用贝叶斯定理。推导过程涉及复杂的积分,但其最终形式非常简洁。

**推导结果:**
最优增益 $G$ 是**幅度谱增益**,其平方 $|G|^2$ 是**功率谱增益**。Ephraim和Malah推导出了**最优幅度谱估计器(OM-LSA)**,其增益函数为:

$G_{H}(\xi, \gamma) = \frac{\sqrt{\pi}}{2} \frac{\sqrt{\nu}}{\gamma} \exp\left(-\frac{\nu}{2}\right) \left[ (1+\nu) I_0\left(\frac{\nu}{2}\right) + \nu I_1\left(\frac{\nu}{2}\right) \right]$

其中:
* $\nu(k, m) = \frac{\xi(k, m)}{1+\xi(k, m)} \gamma(k, m)$
* $I_0(\cdot)$ 和 $I_1(\cdot)$ 分别是**零阶和一阶修正贝塞尔函数**。
* $G_H$ 被称为**超几何增益(Hypergeometric Gain)**。

这个公式就是 Speex 代码中 `hypergeom_gain(theta)` 函数所计算的内容。代码中的 `theta` 变量对应的就是推导中的 $\nu$。

### 4. 直观解释与代码对应

1. **增益特性**:
* 当**先验信噪比 $\xi$ 很高**(强语音,弱噪声)时,$G_H \approx 1$,信号几乎无衰减通过。
* 当**先验信噪比 $\xi$ 很低**(弱语音,强噪声)时,$G_H \approx 0$,信号被大幅抑制。
* 增益值在 0 和 1 之间平滑变化,提供了良好的语音质量和噪声抑制的平衡。

2. **与 Speex 代码的对应关系**:
* `st->prior[i]`:对应 $\xi(k, m)$,**先验信噪比**。
* `st->post[i]`:对应 $\gamma(k, m) – 1$,**后验信噪比偏移**(代码中减1是为了计算方便)。
* `prior_ratio = ξ / (1+ξ)`:这是**维纳滤波器的增益**。代码中先计算了这个值。
* `theta = prior_ratio * (1 + post)`:这正好等于 $\nu = \frac{\xi}{1+\xi} \gamma$。因为 `post` 在代码中定义为 $\gamma – 1$,所以 `1 + post = γ`。
* `MM = hypergeom_gain(theta)`:计算的就是上面的 $G_H(\xi, \gamma)$ 函数。
* `st->gain[i] = prior_ratio * MM`:得到最终的增益值。

### 总结

Ephraim-Malah 算法的精髓在于:

1. **统计模型**:通过假设语音和噪声的复频谱服从高斯分布,为问题提供了一个坚实的概率论框架。
2. **两个信噪比**:创新性地区分并利用了**先验信噪比 $\xi$**(历史信息)和**后验信噪比 $\gamma$**(当前观测),通过判决引导法将两者结合,鲁棒地跟踪语音和噪声的变化。
3. **最优估计**:从MM准则出发,严格推导出了在统计意义上最优的幅度谱增益函数 $G_H$。这个增益能最大程度地减少失真。
4. **音乐噪声控制**:与简单的谱减法相比,基于MMSE的增益函数能极大地减少残留的“音乐噪声”(musical noise),听感更加自然。

因此,Ephraim-Malah 算法并非一个简单的启发式公式,而是基于严谨统计推导的最优估计器,这也是它至今仍在各种语音增强系统中被广泛使用或作为基准的原因。Speex 预处理器的实现正是这一经典理论的高效工程化。

 

好的,我们将详细推导最优幅度谱估计器 (OM-LSA) 的增益函数。这个推导是 Ephraim 和 Malah 于 1984 年在他们的开创性论文中提出的,是语音增强领域的里程碑。

### 1. 问题建模与目标

**目标**:在已知观测到的含噪语音频谱 $Y$ 的情况下,找到一个对纯净语音频谱幅度 $|X|$ 的估计 $\widehat{|X|}$,使得**均方误差 (MSE)** 最小:
$$\mathcal{E} = E\left\{ \left( |X| – \widehat{|X|} \right)^2 \mid Y \right\}$$
根据最小均方误差 (MMSE) 准则,最优估计是**条件均值**:
$$\widehat{|X|}_{\text{opt}} = E\left\{ |X| \mid Y \right\}$$

**假设**(与之前一致):
1. **加性噪声**:$Y = X + D$
2. **统计独立性**:$X$ 和 $D$ 是统计独立的。
3. **复高斯分布**:$X$ 和 $D$ 是循环对称复高斯随机变量,其均值为零,方差分别为 $\lambda_x \equiv E\{|X|^2\}$ 和 $\lambda_d \equiv E\{|D|^2\}$。
* 这意味着它们的实部和虚部是联合高斯的、不相关的,且具有相同的方差。

由于噪声是加性的且与语音独立,观测信号 $Y$ 也是零均值复高斯的,其方差为 $\lambda_y = \lambda_x + \lambda_d$。

### 2. 推导准备:概率密度函数 (PDF)

我们需要用到以下概率密度函数:

1. **纯净语音幅度 $|X|$ 的 PDF**:
由于 $X$ 是复高斯的,其幅度 $R = |X|$ 服从瑞利分布:
$$p_R(r) = \frac{2r}{\lambda_x} \exp\left(-\frac{r^2}{\lambda_x}\right), \quad r \geq 0$$

2. **给定 $X$ 时,$Y$ 的条件 PDF**:
由于 $D$ 是高斯分布,$Y$ 在给定 $X$ 的条件下的分布是 $D$ 的分布平移 $X$ 个单位。
$$p(Y | X) = \frac{1}{\pi \lambda_d} \exp\left(-\frac{|Y – X|^2}{\lambda_d}\right)$$

3. **联合 PDF $p(Y, |X|)$**:
为了求条件期望 $E[|X| | Y]$,我们需要联合分布。一个更巧妙的方法是使用**贝叶斯定理**将条件期望写为:
$$E[|X| | Y] = \frac{\int_0^\infty r \cdot p(Y | r) \cdot p_R(r) \, dr}{\int_0^\infty p(Y | r) \cdot p_R(r) \, dr}$$
这里,$p(Y | r)$ 是**给定语音幅度 $|X|=r$ 时,观测 $Y$ 的条件概率**。注意,$Y$ 依赖于 $X$ 的相位 $\theta_x$,而不仅仅是幅度 $r$。因此,我们需要对相位 $\theta_x$ 进行积分。

### 3. 核心推导步骤

**第1步:表达 $p(Y | r)$**
给定幅度 $r$,$X$ 可以表示为 $X = r e^{j\theta_x}$,其中 $\theta_x$ 是在 $[0, 2\pi]$ 上均匀分布的随机相位。
$$p(Y | r) = \int_0^{2\pi} p(Y | X=r e^{j\theta_x}) p(\theta_x) \, d\theta_x$$
代入 $p(Y | X)$ 和 $p(\theta_x) = \frac{1}{2\pi}$:
$$p(Y | r) = \frac{1}{2\pi} \int_0^{2\pi} \frac{1}{\pi \lambda_d} \exp\left(-\frac{|Y – r e^{j\theta_x}|^2}{\lambda_d}\right) d\theta_x$$

**第2步:计算积分**
展开指数项:
$$|Y – r e^{j\theta_x}|^2 = |Y|^2 + r^2 – 2r \operatorname{Re}\{Y e^{-j\theta_x}\}$$
令 $Y = |Y| e^{j\theta_y}$,则 $Y e^{-j\theta_x} = |Y| e^{j(\theta_y – \theta_x)}$,其**实部**为 $|Y|\cos(\theta_y – \theta_x)$。
定义 $\phi = \theta_x – \theta_y$,则 $d\phi = d\theta_x$。积分变为:
$$p(Y | r) = \frac{1}{2\pi^2 \lambda_d} \exp\left(-\frac{|Y|^2 + r^2}{\lambda_d}\right) \int_0^{2\pi} \exp\left(\frac{2r |Y| \cos \phi}{\lambda_d}\right) d\phi$$

利用**零阶修正贝塞尔函数**的定义:
$$I_0(z) = \frac{1}{2\pi} \int_0^{2\pi} \exp(z \cos \phi) \, d\phi$$
我们可以简化上面的积分:
$$p(Y | r) = \frac{1}{\pi \lambda_d} \exp\left(-\frac{|Y|^2 + r^2}{\lambda_d}\right) I_0\left( \frac{2r |Y|}{\lambda_d} \right)$$

**第3步:代入贝叶斯公式**
现在我们将 $p(Y | r)$ 和 $p_R(r) = \frac{2r}{\lambda_x} \exp\left(-\frac{r^2}{\lambda_x}\right)$ 代入条件期望公式:
$$E[|X| | Y] = \frac{ \int_0^\infty r \cdot \left[ \frac{1}{\pi \lambda_d} \exp\left(-\frac{|Y|^2 + r^2}{\lambda_d}\right) I_0\left( \frac{2r |Y|}{\lambda_d} \right) \right] \cdot \left[ \frac{2r}{\lambda_x} \exp\left(-\frac{r^2}{\lambda_x}\right) \right] dr }{ \int_0^\infty \left[ \frac{1}{\pi \lambda_d} \exp\left(-\frac{|Y|^2 + r^2}{\lambda_d}\right) I_0\left( \frac{2r |Y|}{\lambda_d} \right) \right] \cdot \left[ \frac{2r}{\lambda_x} \exp\left(-\frac{r^2}{\lambda_x}\right) \right] dr }$$

提取与 $r$ 无关的项(如 $\frac{2}{\pi \lambda_d \lambda_x} \exp(-|Y|^2/\lambda_d)$)到分数外面,它们会在分子和分母中**抵消**。简化后得到:
$$E[|X| | Y] = \frac{ \int_0^\infty r^2 \exp\left(-a r^2\right) I_0(\beta r) \, dr }{ \int_0^\infty r \exp\left(-a r^2\right) I_0(\beta r) \, dr }$$
其中我们定义了:
$$a = \frac{1}{\lambda_d} + \frac{1}{\lambda_x} = \frac{\lambda_x + \lambda_d}{\lambda_x \lambda_d} = \frac{\lambda_y}{\lambda_x \lambda_d}$$
$$\beta = \frac{2 |Y|}{\lambda_d}$$

**第4步:求解积分**
这是一个最复杂的部分,需要用到积分表中有以下恒等式:
$$\int_0^\infty x^{\mu} e^{-\alpha x^2} I_\nu(\beta x) \, dx = \frac{\beta^\nu \Gamma\left(\frac{\mu+\nu+1}{2}\right) }{2^{\nu+1} \alpha^{(\mu+\nu+1)/2} \Gamma(\nu+1)} {}_1F_1\left(\frac{\mu+\nu+1}{2}; \nu+1; \frac{\beta^2}{4\alpha}\right)$$
其中 ${}_1F_1(a; b; z)$ 是**合流超几何函数 (Confluent Hypergeometric Function)**,也称为 Kummer’s Function。

* **分母积分** ($\mu=1, \nu=0$):
$\int_0^\infty r \exp\left(-a r^2\right) I_0(\beta r) \, dr = \frac{1}{2a} \exp\left(\frac{\beta^2}{4a}\right)$
* **分子积分** ($\mu=2, \nu=0$):
$\int_0^\infty r^2 \exp\left(-a r^2\right) I_0(\beta r) \, dr = \frac{1}{2a} \sqrt{\frac{\pi}{a}} \frac{1}{2} \left(1 + \frac{\beta^2}{4a}\right) \exp\left(\frac{\beta^2}{4a}\right) \cdot {}_1F_1\left(-\frac{1}{2}; 1; -\frac{\beta^2}{4a}\right)$
${}_1F_1\left(-\frac{1}{2}; 1; -z\right)$ 有已知的闭合形式,可以进一步简化为:
${}_1F_1\left(-\frac{1}{2}; 1; -z\right) = e^{-z/2} \left[ (1+z) I_0\left(\frac{z}{2}\right) + z I_1\left(\frac{z}{2}\right) \right]$

**第5步:代入并简化**
将积分结果代回 $E[|X| | Y]$ 的表达式。$\exp(\beta^2/4a)$ 项和 $1/2a$ 项会被抵消。
令 $z = \frac{\beta^2}{4a}$。经过一系列代数运算(包括代入 $a$ 和 $\beta$ 的定义),我们可以得到:
$$E[|X| | Y] = \frac{\sqrt{\pi}}{2} \frac{\sqrt{v}}{\gamma} \lambda_d^{1/2} \exp\left(-\frac{v}{2}\right) \left[ (1+v) I_0\left(\frac{v}{2}\right) + v I_1\left(\frac{v}{2}\right) \right]$$
其中我们引入了两个关键参数:
* **先验信噪比 (A Priori SNR)**: $\xi = \frac{\lambda_x}{\lambda_d}$
* **后验信噪比 (A Posteriori SNR)**: $\gamma = \frac{|Y|^2}{\lambda_d}$
* 以及一个中间变量: $v = \frac{\xi}{1+\xi} \gamma$

**第6步:得到增益函数**
最优估计 $\widehat{|X|}_{\text{opt}} = E[|X| | Y]$。我们希望将其表示为一个增益 $G$ 与观测幅度 $|Y|$ 的乘积:
$$\widehat{|X|}_{\text{opt}} = G \cdot |Y|$$
因此,**最优幅度谱增益函数 $G_{\text{OM-LSA}}$** 为:
$$G_{\text{OM-LSA}}(\xi, \gamma) = \frac{E[|X| | Y]}{|Y|} = \frac{\sqrt{\pi}}{2} \frac{\sqrt{v}}{\gamma} \exp\left(-\frac{v}{2}\right) \left[ (1+v) I_0\left(\frac{v}{2}\right) + v I_1\left(\frac{v}{2}\right) \right]$$

$$
\boxed{G_{H}(\xi, \gamma) = \frac{\sqrt{\pi}}{2} \frac{\sqrt{\nu}}{\gamma} \exp\left(-\frac{\nu}{2}\right) \left[ (1+\nu) I_0\left(\frac{\nu}{2}\right) + \nu I_1\left(\frac{\nu}{2}\right) \right] \quad \text{其中} \quad \nu = \frac{\xi}{1+\xi} \gamma}
$$

### 4. 原理与直观解释

1. **MMSE 准则**:该增益函数是在**幅度域**均方误差意义下的**最优**解。它最小了估计的语音幅度与真实语音幅度之间的期望误差。

2. **两个信噪比的作用**:
* **先验信噪比 $\xi$**:代表了“我们期望语音有多强”。它决定了增益的整体“基线”。$\xi$ 高,增益 $G$ 趋近于 1;$\xi$ 低,增益 $G$ 趋近于 0。
* **后验信噪比 $\gamma$**:代表了“当前观测值有多强”。它是一个瞬时测量值,用于**微调**基于 $\xi$ 的增益估计。如果当前帧的 $\gamma$ 异常高,即使 $\xi$ 不高,$v$ 也会变大,导致增益 $G$ 临时增大。

3. **中间变量 $v$**:$v = \frac{\xi}{1+\xi} \gamma$ 可以理解为一种**加权后的瞬时信噪比**。它是先验知识和当前观测的融合。

4. **贝塞尔函数 $I_0, I_1$**:这些函数来源于推导过程中对随机相位的积分。它们决定了增益函数在 $v$ 的中间值处的具体**形状**,使其平滑地从 0 过渡到 1。

5. **与维纳滤波器的关系**:维纳滤波器是**功率谱**域的最优 MMSE 估计器,其增益为 $G_{\text{Wiener}} = \frac{\xi}{1+\xi}$。OM-LSA 增益可以近似看作是维纳增益的一个**非线性、幅度域**的修正版本:$G_H \approx \sqrt{G_{\text{Wiener}}}$(在高信噪比时),但在低信噪比时,OM-LSA 提供了更好的抑制效果和更自然的残余噪声。

### 总结

OM-LSA 增益函数的推导是一个经典的统计信号处理案例。它从一个明确的优化目标(最小化幅度误差)和合理的统计假设(高斯性、独立性)出发,通过严谨的数学推导(贝叶斯估计、积分变换、特殊函数),最终得到了一个闭合形式的解。这个解巧妙地融合了历史信息 ($\xi$) 和当前观测 ($\gamma$),从而能够在抑制噪声的同时,最大限度地保留语音质量并减少音乐噪声,使其成为实际应用中效果最好的增益规则之一。Speex 代码中的 `hypergeom_gain(theta)` 函数就是对这一复杂增益函数的高效实现。

来源:image processing(微信号/QQ号:1439279),转载请注明出处,谢谢!
上一篇: 下一篇:

  • 评论:(0)

已有 0 位网友发表了一针见血的评论,你还等什么?

◎欢迎参与讨论!

站内搜索

浙ICP备2022036695号-1

浙公网安备 33010902003475号