webrtc 的audio process介绍(新版本webrtc)

webrtc的 audio processing 模块是 webrtc音频处理的核心模块,webrtc命名为The Audio Processing Module (APM) ,该模块不仅融合音频的3A(AEC(Acoustic Echo Cancelling,回声消除)、AGC(Automatic Gain Control,自动增益控制)和 ANS(Active Noise Control,降噪)), 还融于了高通滤波,语音活动检测和瞬态抑制等功能。

一 核心函数模块介绍

AudioProcessingImpl::ProcessCaptureStreamLocked 函数为音频数据处理的核心函数,

按顺序调用的主要模块算法有:(部分算法根据配置文件确认是否执行)

  1. 高通滤波 (HPF)

  2. 前置放大器 (Pre-amplifier)

  3. 回声控制 (AEC/AEC3) - 分析捕获信号

  4. 自动增益控制 (AGC/AGC2) - 分析

  5. 分频带处理 (Split into frequency bands)

  6. 噪声抑制 (NS)

  7. 回声消除处理 (Process Capture)

  8. 瞬态抑制 (Transient Suppression)

  9. 增益应用 (Gain Application)

  10. 合并频带 (Merge frequency bands)

  11. 后置处理 (Post-processing)

音频处理的主要模块类:

cpp 复制代码
 std::unique_ptr<AgcManagerDirect> agc_manager;
 std::unique_ptr<GainControlImpl> gain_control;
 std::unique_ptr<GainController2> gain_controller2;
 std::unique_ptr<HighPassFilter> high_pass_filter;
 rtc::scoped_refptr<EchoDetector> echo_detector;
 std::unique_ptr<EchoControl> echo_controller;
 std::unique_ptr<EchoControlMobileImpl> echo_control_mobile;
 std::unique_ptr<NoiseSuppressor> noise_suppressor;
 std::unique_ptr<TransientSuppressor> transient_suppressor;
 std::unique_ptr<CustomProcessing> capture_post_processor;
 std::unique_ptr<CustomProcessing> render_pre_processor;
 std::unique_ptr<GainApplier> pre_amplifier;
 std::unique_ptr<CustomAudioAnalyzer> capture_analyzer;
 std::unique_ptr<LevelEstimator> output_level_estimator;
 std::unique_ptr<VoiceDetection> voice_detector;

函数主要分为五大阶段(每个阶段流程,部分模块根据配置是否执行)

第一阶段:全频带预处理 (Full-band Pre-processing)

1.1 全频带高通滤波 (HPF)

如果配置要求在全频带进行且未被强制使用分频带,则先切除低频噪音

1.2 应用前置放大器增益 (Pre-amplifier)

用于补偿麦克风灵敏度或统一输入电平,在其它处理之前调整信号幅度

1.3 分析输入信号 RMS (均方根) 电平

用于统计和监控输入音量大小

第二阶段:分析与分频带 (Analysis & Splitting)

2.1 回声控制器 (AEC3) 前置分析

检测模拟增益、前置增益或播放音量的变化,这些变化会影响回声路径,需通知 AEC

2.2 AGC1 (旧版自动增益) 前置分析

2.3 分频带处理准备 (Split into Frequency Bands)

如果启用了需要分频带处理的模块(如 NS, AECM, VAD),则将信号从时域转换为频域子带

2.4 多通道降级处理

如果启用了 AEC 但不支持多通道捕获,强制将信号下混为单声道以简化处理

2.5 分频带高通滤波 (Split-band HPF)

如果未在全频带处理,或者被强制要求在分频带处理,则在此处执行 HPF

第三阶段:核心增强算法 (Core Enhancement)

3.1 AGC1 分析捕获音频

3.2 噪声抑制 (NS) 分析

如果未启用"分析线性AEC输出"功能,或者没有线性输出缓冲区,则分析原始捕获信号

3.3 执行回声消除 (AEC)

3.4 语音活动检测 (VAD)

3.5 AGC1 处理与应用增益

3.6 AGC1 最终处理(限幅器等)

第四阶段:后处理与合并 (Post-processing & Merging)

4.1 合并频带 (Merge Frequency Bands)

将处理后的子带信号重新合成为全频带时域信号

4.2 全频带缓冲区同步

如果存在独立的全频带缓冲区(用于某些全频带算法),且多频带处理改变了信号,

则将结果拷贝过去,并切换当前工作指针到全频带缓冲区

4.3 残留回声检测器 (Residual Echo Detector) 分析

4.4 瞬态抑制 (Transient Suppression)

抑制键盘敲击声等非平稳噪声

4.5 自定义捕获分析器 (Experimental)

4.6 AGC2 (新版自动增益控制) 处理

4.7 自定义后置处理器 (Custom Post-processor)

第五阶段:统计与指标上报 (Statistics & Metrics)

5.1 输出电平估计

5.2 分析输出信号 RMS 电平并记录直方图

5.3 记录 AGC 模拟电平用于调试

5.4 收集回声相关指标 (AEC Metrics)

5.5 收集残留回声指标

5.6 更新并上报统计数据

附函数

cpp 复制代码
int AudioProcessingImpl::ProcessCaptureStreamLocked() {
  // 1. 处理渲染端(Render/Playout)积压的音频数据
  // AEC 需要参考扬声器播放的声音来消除回声,这里处理之前缓存的渲染帧
  EmptyQueuedRenderAudioLocked();
  
  // 2. 处理捕获端的运行时动态设置(如模拟增益变化、压缩增益等)
  HandleCaptureRuntimeSettings();

  // 确保 AEC3 (echo_controller) 和 AECM (echo_control_mobile) 不会同时激活
  RTC_DCHECK_LE(
      !!submodules_.echo_controller + !!submodules_.echo_control_mobile, 1);

  AudioBuffer* capture_buffer = capture_.capture_audio.get();  // 主处理缓冲区
  AudioBuffer* linear_aec_buffer = capture_.linear_aec_output.get(); // 线性AEC输出缓冲区(可选)

  // --- 第一阶段:全频带预处理 (Full-band Pre-processing) ---

  // 3. 全频带高通滤波 (HPF)
  // 如果配置要求在全频带进行且未被强制使用分频带,则先切除低频噪音
  if (submodules_.high_pass_filter &&
      config_.high_pass_filter.apply_in_full_band &&
      !constants_.enforce_split_band_hpf) {
    submodules_.high_pass_filter->Process(capture_buffer,
                                          /*use_split_band_data=*/false);
  }

  // 4. 应用前置放大器增益 (Pre-amplifier)
  // 用于补偿麦克风灵敏度或统一输入电平,在其它处理之前调整信号幅度
  if (submodules_.pre_amplifier) {
    submodules_.pre_amplifier->ApplyGain(AudioFrameView<float>(
        capture_buffer->channels(), capture_buffer->num_channels(),
        capture_buffer->num_frames()));
  }

  // 5. 分析输入信号 RMS (均方根) 电平
  // 用于统计和监控输入音量大小
  capture_input_rms_.Analyze(rtc::ArrayView<const float>(
      capture_buffer->channels_const()[0],
      capture_nonlocked_.capture_processing_format.num_frames()));
  const bool log_rms = ++capture_rms_interval_counter_ >= 1000;
  if (log_rms) {
    capture_rms_interval_counter_ = 0;
    RmsLevel::Levels levels = capture_input_rms_.AverageAndPeak();
    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureInputLevelAverageRms",
                                levels.average, 1, RmsLevel::kMinLevelDb, 64);
    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureInputLevelPeakRms",
                                levels.peak, 1, RmsLevel::kMinLevelDb, 64);
  }

  // --- 第二阶段:分析与分频带 (Analysis & Splitting) ---

  // 6. 回声控制器 (AEC3) 前置分析
  // 检测模拟增益、前置增益或播放音量的变化,这些变化会影响回声路径,需通知 AEC
  if (submodules_.echo_controller) {
    int analog_mic_level = recommended_stream_analog_level_locked();
    capture_.echo_path_gain_change =
        capture_.prev_analog_mic_level != analog_mic_level &&
        capture_.prev_analog_mic_level != -1;
    capture_.prev_analog_mic_level = analog_mic_level;

    if (submodules_.pre_amplifier) {
      float pre_amp_gain = submodules_.pre_amplifier->GetGainFactor();
      capture_.echo_path_gain_change =
          capture_.echo_path_gain_change ||
          (capture_.prev_pre_amp_gain != pre_amp_gain &&
           capture_.prev_pre_amp_gain >= 0.f);
      capture_.prev_pre_amp_gain = pre_amp_gain;
    }

    capture_.echo_path_gain_change =
        capture_.echo_path_gain_change ||
        (capture_.prev_playout_volume != capture_.playout_volume &&
         capture_.prev_playout_volume >= 0);
    capture_.prev_playout_volume = capture_.playout_volume;

    // 分析捕获音频,提取特征用于后续回声消除
    submodules_.echo_controller->AnalyzeCapture(capture_buffer);
  }

  // 7. AGC1 (旧版自动增益) 前置分析
  if (submodules_.agc_manager) {
    submodules_.agc_manager->AnalyzePreProcess(capture_buffer);
  }

  // 8. 分频带处理准备 (Split into Frequency Bands)
  // 如果启用了需要分频带处理的模块(如 NS, AECM, VAD),则将信号从时域转换为频域子带
  if (submodule_states_.CaptureMultiBandSubModulesActive() &&
      SampleRateSupportsMultiBand(
          capture_nonlocked_.capture_processing_format.sample_rate_hz())) {
    capture_buffer->SplitIntoFrequencyBands();
  }

  // 9. 多通道降级处理
  // 如果启用了 AEC 但不支持多通道捕获,强制将信号下混为单声道以简化处理
  const bool multi_channel_capture = config_.pipeline.multi_channel_capture &&
                                     constants_.multi_channel_capture_support;
  if (submodules_.echo_controller && !multi_channel_capture) {
    capture_buffer->set_num_channels(1);
  }

  // 10. 分频带高通滤波 (Split-band HPF)
  // 如果未在全频带处理,或者被强制要求在分频带处理,则在此处执行 HPF
  if (submodules_.high_pass_filter &&
      (!config_.high_pass_filter.apply_in_full_band ||
       constants_.enforce_split_band_hpf)) {
    submodules_.high_pass_filter->Process(capture_buffer,
                                          /*use_split_band_data=*/true);
  }

  // --- 第三阶段:核心增强算法 (Core Enhancement) ---

  // 11. AGC1 分析捕获音频
  if (submodules_.gain_control) {
    RETURN_ON_ERR(
        submodules_.gain_control->AnalyzeCaptureAudio(*capture_buffer));
  }

  // 12. 噪声抑制 (NS) 分析
  // 如果未启用"分析线性AEC输出"功能,或者没有线性输出缓冲区,则分析原始捕获信号
  if ((!config_.noise_suppression.analyze_linear_aec_output_when_available ||
       !linear_aec_buffer || submodules_.echo_control_mobile) &&
      submodules_.noise_suppressor) {
    submodules_.noise_suppressor->Analyze(*capture_buffer);
  }

  // 13. 执行回声消除 (AEC)
  if (submodules_.echo_control_mobile) {
    // --- AECM (移动版回声消除) 路径 ---
    if (!capture_.was_stream_delay_set) {
      return AudioProcessing::kStreamParameterNotSetError;
    }

    // AECM 通常与 NS 紧密耦合,先处理 NS
    if (submodules_.noise_suppressor) {
      submodules_.noise_suppressor->Process(capture_buffer);
    }

    // 执行 AECM 处理
    RETURN_ON_ERR(submodules_.echo_control_mobile->ProcessCaptureAudio(
        capture_buffer, stream_delay_ms()));
  } else {
    // --- AEC3 (桌面版/高性能回声消除) 路径 ---
    if (submodules_.echo_controller) {
      data_dumper_->DumpRaw("stream_delay", stream_delay_ms());

      // 设置音频缓冲延迟,帮助 AEC3 对齐回声参考信号
      if (capture_.was_stream_delay_set) {
        submodules_.echo_controller->SetAudioBufferDelay(stream_delay_ms());
      }

      // 执行 AEC3 处理,输出线性回声消除后的信号到 linear_aec_buffer
      submodules_.echo_controller->ProcessCapture(
          capture_buffer, linear_aec_buffer, capture_.echo_path_gain_change);
    }

    // 如果配置允许,噪声抑制可以分析经过线性回声消除后的信号(更干净)
    if (config_.noise_suppression.analyze_linear_aec_output_when_available &&
        linear_aec_buffer && submodules_.noise_suppressor) {
      submodules_.noise_suppressor->Analyze(*linear_aec_buffer);
    }

    // 执行噪声抑制处理
    if (submodules_.noise_suppressor) {
      submodules_.noise_suppressor->Process(capture_buffer);
    }
  }

  // 14. 语音活动检测 (VAD)
  if (config_.voice_detection.enabled) {
    capture_.stats.voice_detected =
        submodules_.voice_detector->ProcessCaptureAudio(capture_buffer);
  } else {
    capture_.stats.voice_detected = absl::nullopt;
  }

  // 15. AGC1 处理与应用增益
  if (submodules_.agc_manager) {
    submodules_.agc_manager->Process(capture_buffer);

    // 获取计算出的数字压缩增益,并应用到 GainControl 模块
    absl::optional<int> new_digital_gain =
        submodules_.agc_manager->GetDigitalComressionGain();
    if (new_digital_gain && submodules_.gain_control) {
      submodules_.gain_control->set_compression_gain_db(*new_digital_gain);
    }
  }

  // 16. AGC1 最终处理(限幅器等)
  if (submodules_.gain_control) {
    RETURN_ON_ERR(submodules_.gain_control->ProcessCaptureAudio(
        capture_buffer, /*stream_has_echo*/ false));
  }

  // --- 第四阶段:后处理与合并 (Post-processing & Merging) ---

  // 17. 合并频带 (Merge Frequency Bands)
  // 将处理后的子带信号重新合成为全频带时域信号
  if (submodule_states_.CaptureMultiBandProcessingPresent() &&
      SampleRateSupportsMultiBand(
          capture_nonlocked_.capture_processing_format.sample_rate_hz())) {
    capture_buffer->MergeFrequencyBands();
  }

  // 18. 全频带缓冲区同步
  // 如果存在独立的全频带缓冲区(用于某些全频带算法),且多频带处理改变了信号,
  // 则将结果拷贝过去,并切换当前工作指针到全频带缓冲区
  if (capture_.capture_fullband_audio) {
    const auto& ec = submodules_.echo_controller;
    bool ec_active = ec ? ec->ActiveProcessing() : false;
    if (submodule_states_.CaptureMultiBandProcessingActive(ec_active)) {
      capture_buffer->CopyTo(capture_.capture_fullband_audio.get());
    }
    capture_buffer = capture_.capture_fullband_audio.get();
  }

  // 19. 残留回声检测器 (Residual Echo Detector) 分析
  if (config_.residual_echo_detector.enabled) {
    RTC_DCHECK(submodules_.echo_detector);
    submodules_.echo_detector->AnalyzeCaptureAudio(rtc::ArrayView<const float>(
        capture_buffer->channels()[0], capture_buffer->num_frames()));
  }

  // 20. 瞬态抑制 (Transient Suppression)
  // 抑制键盘敲击声等非平稳噪声
  if (submodules_.transient_suppressor) {
    float voice_probability = submodules_.agc_manager.get()
                                  ? submodules_.agc_manager->voice_probability()
                                  : 1.f;

    submodules_.transient_suppressor->Suppress(
        capture_buffer->channels()[0], capture_buffer->num_frames(),
        capture_buffer->num_channels(),
        capture_buffer->split_bands_const(0)[kBand0To8kHz],
        capture_buffer->num_frames_per_band(),
        capture_.keyboard_info.keyboard_data,
        capture_.keyboard_info.num_keyboard_frames, voice_probability,
        capture_.key_pressed);
  }

  // 21. 自定义捕获分析器 (Experimental)
  if (submodules_.capture_analyzer) {
    submodules_.capture_analyzer->Analyze(capture_buffer);
  }

  // 22. AGC2 (新版自动增益控制) 处理
  if (submodules_.gain_controller2) {
    submodules_.gain_controller2->NotifyAnalogLevel(
        recommended_stream_analog_level_locked());
    submodules_.gain_controller2->Process(capture_buffer);
  }

  // 23. 自定义后置处理器 (Custom Post-processor)
  if (submodules_.capture_post_processor) {
    submodules_.capture_post_processor->Process(capture_buffer);
  }

  // --- 第五阶段:统计与指标上报 (Statistics & Metrics) ---

  // 24. 输出电平估计
  if (config_.level_estimation.enabled) {
    submodules_.output_level_estimator->ProcessStream(*capture_buffer);
    capture_.stats.output_rms_dbfs = submodules_.output_level_estimator->RMS();
  } else {
    capture_.stats.output_rms_dbfs = absl::nullopt;
  }

  // 25. 分析输出信号 RMS 电平并记录直方图
  capture_output_rms_.Analyze(rtc::ArrayView<const float>(
      capture_buffer->channels_const()[0],
      capture_nonlocked_.capture_processing_format.num_frames()));
  if (log_rms) {
    RmsLevel::Levels levels = capture_output_rms_.AverageAndPeak();
    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureOutputLevelAverageRms",
                                levels.average, 1, RmsLevel::kMinLevelDb, 64);
    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.ApmCaptureOutputLevelPeakRms",
                                levels.peak, 1, RmsLevel::kMinLevelDb, 64);
  }

  // 26. 记录 AGC 模拟电平用于调试
  if (submodules_.agc_manager) {
    int level = recommended_stream_analog_level_locked();
    data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
                          &level);
  }

  // 27. 收集回声相关指标 (AEC Metrics)
  if (submodules_.echo_controller) {
    auto ec_metrics = submodules_.echo_controller->GetMetrics();
    capture_.stats.echo_return_loss = ec_metrics.echo_return_loss;
    capture_.stats.echo_return_loss_enhancement =
        ec_metrics.echo_return_loss_enhancement;
    capture_.stats.delay_ms = ec_metrics.delay_ms;
  }
  
  // 28. 收集残留回声指标
  if (config_.residual_echo_detector.enabled) {
    RTC_DCHECK(submodules_.echo_detector);
    auto ed_metrics = submodules_.echo_detector->GetMetrics();
    capture_.stats.residual_echo_likelihood = ed_metrics.echo_likelihood;
    capture_.stats.residual_echo_likelihood_recent_max =
        ed_metrics.echo_likelihood_recent_max;
  }

  // 29. 更新并上报统计数据
  stats_reporter_.UpdateStatistics(capture_.stats);

  // 重置流延迟标记,等待下一帧的设置
  capture_.was_stream_delay_set = false;
  return kNoError;
}

二,audio_processing 模块调用

引用audio_processing.lib 和 audio_processing.h 文件

获取 webrtc::AudioProcessing 对象, 然后可以调用ProcessStream 进行音频增益处理

cpp 复制代码
//使用默认配置
rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing = AudioProcessingBuilder().Create();

或者

//自定义配置,定义是否使用3A等相关音频增益算法
webrtc::Config config;

config.PreAmplifier.enable = true/false;

config.HighPassFilter.enable   = true/false;

其它配置......

rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing = AudioProcessingBuilder().Create(config);

webrtc中的具体调用为:

cpp 复制代码
void ProcessCaptureFrame(uint32_t delay_ms,
                         bool key_pressed,
                         bool swap_stereo_channels,
                         AudioProcessing* audio_processing,
                         AudioFrame* audio_frame) {
  RTC_DCHECK(audio_frame);
  if (audio_processing) {
    audio_processing->set_stream_delay_ms(delay_ms);
    audio_processing->set_stream_key_pressed(key_pressed);
    int error = ProcessAudioFrame(audio_processing, audio_frame);

    RTC_DCHECK_EQ(0, error) << "ProcessStream() error: " << error;
  }

  if (swap_stereo_channels) {
    AudioFrameOperations::SwapStereoChannels(audio_frame);
  }
}
相关推荐
ZENERGY-众壹14 小时前
30MW 渔光互补监控实录:高湿环境下视频与传感器集成的三个坑
音视频
美狐美颜SDK开放平台19 小时前
直播APP开发教程:视频美颜SDK接入需要注意哪些问题?
人工智能·音视频·美颜sdk·第三方美颜sdk·短视频美颜sdk
Elastic 中国社区官方博客19 小时前
从多模态 LLM 中引导构建音频嵌入
大数据·人工智能·elasticsearch·搜索引擎·ai·全文检索·音视频
qetfw21 小时前
yt-dlp:下载公开视频、字幕、封面和音频的实用命令
python·音视频·开源项目·效率工具
美丽的欣情21 小时前
C++音频开发:什么是50Hz、100Hz测试音?以及如何生成16bit/8000Hz的WAV测试文件
开发语言·c++·音视频
AI服务老曹21 小时前
实战记录:H264/H265视频分析项目接入与性能评估指南
音视频
amongdata1 天前
MyVoiceTyping:面向中文语音输入的本地优先开源方案
python·开源·音视频·语音识别
做萤石二次开发的哈哈1 天前
如何接入萤石开放平台 ERTC Windows SDK?
windows·音视频·萤石开放平台
xian_wwq1 天前
【学习笔记】多模态部署:VLM、语音、视频理解(29/35)
笔记·学习·音视频
对牛乱弹琴1 天前
音视频格式解析工具推荐
音视频·视频编解码