如果经过前面介绍的决策判定,该帧需要正常播放,那么正常播放又分为以下几种情况:
上一包是PLC (expand,丢包)
需要计算平滑系数,使上一包和当前包"过渡自然".
平滑系数计算:
D为解码后的数据,即input中的数据,BNG为背景噪声(用默认的初始值)。muteFactor为expand中的muteFactor,64即为8ms数据。
const int fs_mult = fs_hz_ / 8000;
size_t energy_length =
std::min(static_cast<size_t>(fs_mult * 64), length_per_channel);
// energy为平均功率
int local_mute_factor = 16384; // 1.0 in Q14.
if ((energy != 0) && (energy > background_noise_.Energy(channel_ix))) {
// Normalize new frame energy to 15 bits.
scaling = WebRtcSpl_NormW32(energy) - 16;
// We want background_noise_.energy() / energy in Q14.
int32_t bgn_energy = WEBRTC_SPL_SHIFT_W32(
background_noise_.Energy(channel_ix), scaling + 14);
int16_t energy_scaled =
static_cast<int16_t>(WEBRTC_SPL_SHIFT_W32(energy, scaling));
int32_t ratio = WebRtcSpl_DivW32W16(bgn_energy, energy_scaled);
local_mute_factor =
std::min(local_mute_factor, WebRtcSpl_SqrtFloor(ratio << 14));
}
mute_factor = std::max<int16_t>(mute_factor, local_mute_factor);
根据平滑因子平滑decoder_buffer中的数据
// If muted increase by 0.64 for every 20 ms (NB/WB 0.0040/0.0020 in Q14),
// or as fast as it takes to come back to full gain within the frame
// length.
const int back_to_fullscale_inc =
static_cast<int>((16384 - mute_factor) / length_per_channel);
const int increment = std::max(64 / fs_mult, back_to_fullscale_inc);
for (size_t i = 0; i < length_per_channel; i++) {
// Scale with mute factor.
RTC_DCHECK_LT(channel_ix, output->Channels());
RTC_DCHECK_LT(i, output->Size());
int32_t scaled_signal = (*output)[channel_ix][i] * mute_factor;
// Shift 14 with proper rounding.
(*output)[channel_ix][i] =
static_cast<int16_t>((scaled_signal + 8192) >> 14);
// Increase mute_factor towards 16384.
mute_factor =
static_cast<int16_t>(std::min(mute_factor + increment, 16384));
}
再对上一包和本包前后1ms的数据进行平滑
计算公式为:
E 为上一包expand的数据。
上述公式还需要再加上0.5和下述代码对应。
size_t win_length = samples_per_ms_; // 1 ms数据量
int16_t win_slope_Q14 = default_win_slope_Q14_;// default_win_slope_Q14 1个sample增长率 1ms从0增加到1
RTC_DCHECK_LT(channel_ix, output->Channels());
if (win_length > output->Size()) {
win_length = output->Size();
win_slope_Q14 = (1 << 14) / static_cast<int16_t>(win_length);
}
int16_t win_up_Q14 = 0;
for (size_t i = 0; i < win_length; i++) {
win_up_Q14 += win_slope_Q14;
// 依据公式
// expanded为噪声数据
(*output)[channel_ix][i] =
(win_up_Q14 * (*output)[channel_ix][i] +
((1 << 14) - win_up_Q14) * expanded[channel_ix][i] + (1 << 13)) >> // 补偿数据,数据写入都算法缓冲区
14;
}
上一包是CNG
和上一包是expand情况类似,先生成CNG,然后在这一包数据前面用背景噪音做平滑。
float win_up = 0;
for (size_t i = 0; i < win_length; i++) {
//win_up_Q14 += win_slope_Q14;
win_up += win_slope;
(*output)[0].set_array_index_float(i, win_up * (*output)[0].get_array_index_float(i)+
(1.0 - win_up) * cng_output[i]);
}
其它情况
直接把decoder_buffer中的数据写入algorithm_buffer中