备注:全部内容来自AI,记录下来后续慢慢消化

一、简介

DRED(DNN-based Redundant Encoding 神经网络冗余编码)

https://blog.csdn.net/CrystalShaw/article/details/155348053https://blog.csdn.net/CrystalShaw/article/details/155348053opus的silk编码器里面有带内fec编码,上面链接有详细介绍。实际应用个人更倾向RS-FEC,同样带宽下,RS-FEC保护范围更大,音质完全还原。而opus的带内fec仅能保护上一个报文,并且还牺牲了音质。

opus推出的DRED看来是要解决带内fec的局限性。

1、核心原理对比

特性 传统带内 FEC (Opus Standard FEC) DRED (Deep Redundancy)
工作原理 复制粘贴。将前一帧的音频数据(通常是低比特率版本)直接塞进当前包里一起发送。 特征压缩。利用神经网络提取音频的“潜变量”(Latents,即声音的本质特征),将这些极小的特征数据塞进当前包。
恢复方式

直接播放。如果主包丢了,解码器直接把 FEC 数据拿出来播放。

神经合成。如果主包丢了,解码器利用收到的特征数据,通过 LPCNet 神经网络 重新“画”出波形。
数据性质 它是波形域或参数域的直接拷贝。 它是语义/特征域的抽象表示。
带宽消耗 线性增长。想保护更多帧或更高质量,需要的比特数直线上升。 极高压缩率。因为只传特征,同样的比特数可以保护更长的时间窗口,或者在同等保护长度下占用更少带宽。

2、DRED 带来的具体收益

  • 收益一:在极低码率下实现“可懂度”救急 (最大的优势)

       传统FEC困境:Opus 的传统 FEC 通常在总码率低于 ~16-20 kbps 时会自动关闭。

            原因:如果在 8 kbps 的通话中拿出 4 kbps 做 FEC,主音频只剩 4 kbps,音质烂到无法接                         受;如果不拿,FEC 本身又不够清晰。这是一个死结。
       DRED的突破:由于神经网络提取的特征极其紧凑,DRED 可以在 总码率低至 8-12 kbps 的                         情况下依然开启。

            效果:即使主包丢失,接收端利用 DRED 重建的声音虽然听起来像“电话音”或有点机械感                     (神经声码器的特点),但语音内容(说了什么)依然清晰可懂。

            场景:弱网环境(如电梯、地下室、移动网络边缘),传统方案会直接断音或变成刺耳的                        噪声,DRED 能保证你听清对方在说什么。

  • 收益二:更长的保护时间窗口 (抗连续丢包)

        传统FEC困境:通常只能保护前 1 帧。如果遇到连续丢包,FEC 也丢了,那就彻底没救了。
        DRED的突破:由于特征数据很小,可以在一个包里携带过去 3~5 帧甚至更多的冗余信息。
                     这意味着它能抵抗更长时间的连续丢包。只要包最终到达了,里面的DRED数据就能                       把之前丢失的几秒语音都补回来。

  • 收益三:避免“机器人音”叠加的听感恶化

         传统FEC问题:当网络抖动导致频繁切换“主包”和“FEC 包”时,听众会听到音质在“清晰”和                         “模糊/闷”之间反复横跳,这种不连续性非常干扰听觉注意力。
         DRED的优势:DRED设计目标是在丢包发生时提供平滑的降级。虽然重建的音质不如原                       声自然,但它提供了一致性听感。神经网络的生成能力可以填补频谱空缺,听起来比传                   统插值算法产生的“嗡嗡声”或“机械音”更自然一些。

  • 收益四:针对语音特性的极致优化

          传统 FEC是通用的信号处理,它不知道自己在传语音还是音乐,只是盲目保留能量和频谱
          DRED是基于 LPCNet 训练的,它“懂”人类语音的结构(基频、共振峰、浊音/清音)。
                在极度受限的比特率下,会优先保留决定语音可懂度的关键特征,丢弃不重要的细节。                  这是一种语义层面的压缩,效率远高于传统的信号压缩。

二、实现

1、整体框架

语音 PCM → 重采样到 16kHz → LPCNet 特征提取 → RDOVAE 深度编码 → 隐向量(latents) → 熵编码 → 冗余数据包

1. 输入PCM → 重采样 16k mono
2. 存入输入缓冲
3. 凑够2帧 → 提取LPCNet特征
4. RDOVAE压缩 → 得到16维latent + 32维state
5. 保存最近多帧向量
6. 熵编码 → 生成小体积冗余包
7. 随Opus主帧一起发送
8. 丢包时,接收端用冗余向量恢复语音

2、模块分工

重采样                 :任何采样率都要统一到16kHz(DRED 模型只支持 16k)
LPCNet 特征       :提取语音梅尔 / 线性预测特征
RDOVAE 编码器 :AI 模型把特征压缩成小维度隐向量
量化 / 熵编码       :把浮点数隐向量压缩成比特流

3、数据结构

typedef struct {
    opus_int32 Fs;             // 采样率
    int channels;             // 声道
    int loaded;               // 模型是否加载

    float input_buffer[...];  // 16k输入缓冲
    int input_buffer_fill;    // 缓冲填充量

    float state_buffer[...];  // AI状态向量(32维/帧)
    float latents_buffer[...];// AI隐向量(16维/帧)
    int latents_buffer_fill;

    float resample_mem[...];  // 重采样滤波器记忆

    RDOVAEEnc model;          // AI模型
    LPCNetEnc lpcnet_enc;     // 特征提取
    RDOVAEEncState rdovae_enc;// 编码器状态
} DREDEnc;

4、函数原理

  • 1. dred_encoder_init:编码器初始化

        作用:创建 DRED 编码器实例,设置采样率、声道、加载 AI 模型
                   保存采样率 Fs、声道数
                   加载 RDOVAE + LPCNet 模型
                   调用 dred_encoder_reset 重置状态

void dred_encoder_init(DREDEnc* enc, opus_int32 Fs, int channels)
{
    enc->Fs = Fs;
    enc->channels = channels;
    enc->loaded = 0;
// 加载AI模型
#ifndef USE_WEIGHTS_FILE
    if (init_rdovaeenc(&enc->model, rdovaeenc_arrays) == 0) enc->loaded = 1;
#endif
// 重置编码器
    dred_encoder_reset(enc);
}
  • 2. dred_encoder_reset:状态重置

     作用:清空所有历史状态,重启 AI 编码流水线,这是 DRED 最关键的状态控制函数。
     原理:清空从 DREDENC_RESET_START 开始的所有动态状态
                隐向量缓冲区
                状态缓冲区
                输入缓冲区
               重采样滤波器记忆
               设置输入缓冲区填充值 = 编码器延迟(DRED_SILK_ENCODER_DELAY)
               重新初始化 LPCNet 编码器
               重新初始化 RDOVAE 编码器

void dred_encoder_reset(DREDEnc* enc)
{
    // 清空动态状态
    OPUS_CLEAR((char*)&enc->DREDENC_RESET_START,
              sizeof(DREDEnc)-
              ((char*)&enc->DREDENC_RESET_START - (char*)enc));

    // 输入缓冲填充 = 编码器延迟
    enc->input_buffer_fill = DRED_SILK_ENCODER_DELAY;

    // 重置子模块
    lpcnet_encoder_init(&enc->lpcnet_enc_state);
    DRED_rdovae_init_encoder(&enc->rdovae_enc);
}
  • 3. dred_convert_to_16k:统一重采样到 16kHz

     原理:DRED AI 模型只支持 16kHz 单声道输入,所以必须:
               多声道 → 转单声道
              8k/12k/24k/48k/96k → 重采样 → 16k
              使用 椭圆滤波器(ellip filter) 防混叠
              支持:8000、12000、16000、24000、48000、96000(ENABLE_QEXT)

  • 4. dred_compute_latents:计算 AI 隐向量

      作用:把 PCM 语音 → 转换成 AI 冗余需要的 latents(隐向量)
      流程:重采样到 16k
                填满输入缓冲
                缓冲满 2 帧 DRED 帧 → 触发 dred_process_frame 
                滑动窗口,不断生成新的隐向量

  • 5. dred_process_frame:核心 AI 编码

      真正的 AI 编码流水线:

LPCNet 特征提取 → RDOVAE 编码 → 得到 latents + state

     特征:每帧 36 维,2 帧拼成 72 维
              RDOVAE:把 72 维特征压缩到 16 维 latent + 32 维 state
              缓冲区保存最近 N 帧,用于冗余修复

  • 6. dred_encode_latents:隐向量量化 + 熵编码

     原理:把浮点数隐向量 → 压缩成紧凑二进制包
     量化:浮点数 → 整数
               死区量化(deadzone quant):让小数值归零,提升压缩率
               拉普拉斯熵编码:超高压缩语音冗余数据

  • 7. dred_encode_silk_frame:生成最终冗余包

     作用:把所有隐向量打包成 可发送的冗余帧,并写入输出 buffer。
     逻辑:检查语音活动(VAD),静音不发冗余
                编码 state 向量
                编码多帧 latents 向量
                控制冗余包大小(max_bytes)
                返回冗余包长度(=0 表示不发送)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐