WebRTC音视频之噪音消除功能

WebRTC对于iOS和Android的音频处理,是有很大的不同的,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(
        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,ios,android,WebRTC,噪音消除,噪音算法)