WebRTC音视频之噪音消除功能

Posted hbblzjy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebRTC音视频之噪音消除功能相关的知识,希望对你有一定的参考价值。

WebRTC对于iosandroid的音频处理,是有很大的不同的,WebRTC基本上是使用的iOS自身的音频降噪、环境音处理、人声增益处理,因为WebRTC认为iOS的音频处理已经满足相对理想的效果,所以在算法处理上进行了iOS和Android的区分。

但是我研究发现,如果将WebRTC用于Android的算法,也用于iOS,在部分手机上还是有相当的效果,现在就是将修改的噪音消除的代码奉上,以供参考。

bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) 
  RTC_DCHECK(worker_thread_checker_.IsCurrent());
  RTC_LOG(LS_INFO) << "WebRtcVoiceEngine::ApplyOptions: "
                   << options_in.ToString();
  AudioOptions options = options_in;  // The options are modified below.

  // Set and adjust echo canceller options.
  // kEcConference is AEC with high suppression.
  webrtc::EcModes ec_mode = webrtc::kEcConference;

#if defined(WEBRTC_IOS)
  if (options.ios_force_software_aec_HACK &&
      *options.ios_force_software_aec_HACK) 
    // EC may be forced on for a device known to have non-functioning platform
    // AEC.
    options.echo_cancellation = true;
    RTC_LOG(LS_WARNING)
        << "Force software AEC on iOS. May conflict with platform AEC.";
   else 
    // On iOS, VPIO provides built-in EC.
    options.echo_cancellation = false;
    RTC_LOG(LS_INFO) << "Always disable AEC on iOS. Use built-in instead.";
  
#elif defined(WEBRTC_ANDROID)
  ec_mode = webrtc::kEcAecm;
#endif

// Set and adjust noise suppressor options.
#if defined(WEBRTC_IOS)
  // On iOS, VPIO provides built-in NS.
    
    //修改处
  //options.noise_suppression = false;
    
  options.typing_detection = false;
  options.experimental_ns = false;
  RTC_LOG(LS_INFO) << "Always disable NS on iOS. Use built-in instead.";
#elif defined(WEBRTC_ANDROID)
  options.typing_detection = false;
  options.experimental_ns = false;
#endif

// Set and adjust gain control options.
#if defined(WEBRTC_IOS)
  // On iOS, VPIO provides built-in AGC.
  
    //修改处
    //options.auto_gain_control = false;
    
  options.experimental_agc = false;
  RTC_LOG(LS_INFO) << "Always disable AGC on iOS. Use built-in instead.";
#elif defined(WEBRTC_ANDROID)
  options.experimental_agc = false;
#endif

#if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
  // Turn off the gain control if specified by the field trial.
  // The purpose of the field trial is to reduce the amount of resampling
  // performed inside the audio processing module on mobile platforms by
  // whenever possible turning off the fixed AGC mode and the high-pass filter.
  // (https://bugs.chromium.org/p/webrtc/issues/detail?id=6181).
  if (webrtc::field_trial::IsEnabled(
          "WebRTC-Audio-MinimizeResamplingOnMobile")) 
    options.auto_gain_control = false;
    RTC_LOG(LS_INFO) << "Disable AGC according to field trial.";
    if (!(options.noise_suppression.value_or(false) ||
          options.echo_cancellation.value_or(false))) 
      // If possible, turn off the high-pass filter.
      RTC_LOG(LS_INFO)
          << "Disable high-pass filter in response to field trial.";
      options.highpass_filter = false;
    
  
#endif

  if (options.echo_cancellation) 
    // Check if platform supports built-in EC. Currently only supported on
    // Android and in combination with Java based audio layer.
    // TODO(henrika): investigate possibility to support built-in EC also
    // in combination with Open SL ES audio.
    const bool built_in_aec = adm()->BuiltInAECIsAvailable();
    if (built_in_aec) 
      // Built-in EC exists on this device. Enable/Disable it according to the
      // echo_cancellation audio option.
      const bool enable_built_in_aec = *options.echo_cancellation;
      if (adm()->EnableBuiltInAEC(enable_built_in_aec) == 0 &&
          enable_built_in_aec) 
        // Disable internal software EC if built-in EC is enabled,
        // i.e., replace the software EC with the built-in EC.
        options.echo_cancellation = false;
        RTC_LOG(LS_INFO)
            << "Disabling EC since built-in EC will be used instead";
      
    
    webrtc::apm_helpers::SetEcStatus(apm(), *options.echo_cancellation,
                                     ec_mode);
  

  if (options.auto_gain_control) 
    bool built_in_agc_avaliable = adm()->BuiltInAGCIsAvailable();
    if (built_in_agc_avaliable) 
      if (adm()->EnableBuiltInAGC(*options.auto_gain_control) == 0 &&
          *options.auto_gain_control) 
        // Disable internal software AGC if built-in AGC is enabled,
        // i.e., replace the software AGC with the built-in AGC.
        options.auto_gain_control = false;
        RTC_LOG(LS_INFO)
            << "Disabling AGC since built-in AGC will be used instead";
      
    
  

  if (options.noise_suppression) 
    if (adm()->BuiltInNSIsAvailable()) 
      bool builtin_ns = *options.noise_suppression;
      if (adm()->EnableBuiltInNS(builtin_ns) == 0 && builtin_ns) 
        // Disable internal software NS if built-in NS is enabled,
        // i.e., replace the software NS with the built-in NS.
        options.noise_suppression = false;
        RTC_LOG(LS_INFO)
            << "Disabling NS since built-in NS will be used instead";
      
    
  

  if (options.stereo_swapping) 
    RTC_LOG(LS_INFO) << "Stereo swapping enabled? " << *options.stereo_swapping;
    audio_state()->SetStereoChannelSwapping(*options.stereo_swapping);
  

  if (options.audio_jitter_buffer_max_packets) 
    RTC_LOG(LS_INFO) << "NetEq capacity is "
                     << *options.audio_jitter_buffer_max_packets;
    audio_jitter_buffer_max_packets_ =
        std::max(20, *options.audio_jitter_buffer_max_packets);
  
  if (options.audio_jitter_buffer_fast_accelerate) 
    RTC_LOG(LS_INFO) << "NetEq fast mode? "
                     << *options.audio_jitter_buffer_fast_accelerate;
    audio_jitter_buffer_fast_accelerate_ =
        *options.audio_jitter_buffer_fast_accelerate;
  
  if (options.audio_jitter_buffer_min_delay_ms) 
    RTC_LOG(LS_INFO) << "NetEq minimum delay is "
                     << *options.audio_jitter_buffer_min_delay_ms;
    audio_jitter_buffer_min_delay_ms_ =
        *options.audio_jitter_buffer_min_delay_ms;
  
  if (options.audio_jitter_buffer_enable_rtx_handling) 
    RTC_LOG(LS_INFO) << "NetEq handle reordered packets? "
                     << *options.audio_jitter_buffer_enable_rtx_handling;
    audio_jitter_buffer_enable_rtx_handling_ =
        *options.audio_jitter_buffer_enable_rtx_handling;
  

  webrtc::Config config;

  if (options.experimental_ns) 
    experimental_ns_ = options.experimental_ns;
  
  if (experimental_ns_) 
    RTC_LOG(LS_INFO) << "Experimental ns is enabled? " << *experimental_ns_;
    config.Set<webrtc::ExperimentalNs>(
        new webrtc::ExperimentalNs(*experimental_ns_));
  

  webrtc::AudioProcessing::Config apm_config = apm()->GetConfig();

  if (options.auto_gain_control) 
    const bool enabled = *options.auto_gain_control;
    apm_config.gain_controller1.enabled = enabled;
    RTC_LOG(LS_INFO) << "Setting AGC to " << enabled;
  
  if (options.tx_agc_target_dbov) 
    apm_config.gain_controller1.target_level_dbfs = *options.tx_agc_target_dbov;
  
  if (options.tx_agc_digital_compression_gain) 
    apm_config.gain_controller1.compression_gain_db =
        *options.tx_agc_digital_compression_gain;
  
  if (options.tx_agc_limiter) 
    apm_config.gain_controller1.enable_limiter = *options.tx_agc_limiter;
  

  if (options.highpass_filter) 
    apm_config.high_pass_filter.enabled = *options.highpass_filter;
  

  if (options.residual_echo_detector) 
    apm_config.residual_echo_detector.enabled = *options.residual_echo_detector;
  

  if (options.noise_suppression) 
    const bool enabled = *options.noise_suppression;
    apm_config.noise_suppression.enabled = enabled;
    apm_config.noise_suppression.level =
        webrtc::AudioProcessing::Config::NoiseSuppression::Level::kHigh;
    RTC_LOG(LS_INFO) << "NS set to " << enabled;
  

  if (options.typing_detection) 
    RTC_LOG(LS_INFO) << "Typing detection is enabled? "
                     << *options.typing_detection;
    apm_config.voice_detection.enabled = *options.typing_detection;
  

  apm()->SetExtraOptions(config);
  apm()->ApplyConfig(apm_config);
  return true;

使用方式:


    NSMutableDictionary *mandatory = [NSMutableDictionary dictionary];
    
    if (_closeNoiseSuppression) 
        [mandatory setValue:@"false" forKey:@"googNoiseSuppression"];
        [mandatory setValue:@"false" forKey:@"googAutoGainControl"];
    
    
    NSMutableDictionary *optional = [NSMutableDictionary dictionary];
    
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatory optionalConstraints:optional];
    _audioSource = [_factory audioSourceWithConstraints:constraints];
    _audioTrack = [_factory audioTrackWithSource:_audioSource trackId:kSmoothAudioTrackId];

以上是关于WebRTC音视频之噪音消除功能的主要内容,如果未能解决你的问题,请参考以下文章

WebRTC音频采样算法

webrtc ios 噪音怎么处理

WebRTC简单实现互动直播,实时直播

视频怎么消除人声?一款视频去人声软件,轻松去除视频人声

如何基于 ZEGO SDK 实现回声消除自动增益控制降噪功能

reSipWebRTC