tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gain_applier.cc (3461B)


      1 /*
      2 *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/audio_processing/agc2/gain_applier.h"
     12 
     13 #include <cstddef>
     14 
     15 #include "api/audio/audio_view.h"
     16 #include "modules/audio_processing/agc2/agc2_common.h"
     17 #include "rtc_base/checks.h"
     18 #include "rtc_base/numerics/safe_minmax.h"
     19 
     20 namespace webrtc {
     21 namespace {
     22 
     23 // Returns true when the gain factor is so close to 1 that it would
     24 // not affect int16 samples.
     25 bool GainCloseToOne(float gain_factor) {
     26  return 1.f - 1.f / kMaxFloatS16Value <= gain_factor &&
     27         gain_factor <= 1.f + 1.f / kMaxFloatS16Value;
     28 }
     29 
     30 void ClipSignal(DeinterleavedView<float> signal) {
     31  for (size_t k = 0; k < signal.num_channels(); ++k) {
     32    MonoView<float> channel_view = signal[k];
     33    for (auto& sample : channel_view) {
     34      sample = SafeClamp(sample, kMinFloatS16Value, kMaxFloatS16Value);
     35    }
     36  }
     37 }
     38 
     39 void ApplyGainWithRamping(float last_gain_linear,
     40                          float gain_at_end_of_frame_linear,
     41                          float inverse_samples_per_channel,
     42                          DeinterleavedView<float> float_frame) {
     43  // Do not modify the signal.
     44  if (last_gain_linear == gain_at_end_of_frame_linear &&
     45      GainCloseToOne(gain_at_end_of_frame_linear)) {
     46    return;
     47  }
     48 
     49  // Gain is constant and different from 1.
     50  if (last_gain_linear == gain_at_end_of_frame_linear) {
     51    for (size_t k = 0; k < float_frame.num_channels(); ++k) {
     52      MonoView<float> channel_view = float_frame[k];
     53      for (auto& sample : channel_view) {
     54        sample *= gain_at_end_of_frame_linear;
     55      }
     56    }
     57    return;
     58  }
     59 
     60  // The gain changes. We have to change slowly to avoid discontinuities.
     61  const float increment = (gain_at_end_of_frame_linear - last_gain_linear) *
     62                          inverse_samples_per_channel;
     63  for (size_t ch = 0; ch < float_frame.num_channels(); ++ch) {
     64    float gain = last_gain_linear;
     65    for (float& sample : float_frame[ch]) {
     66      sample *= gain;
     67      gain += increment;
     68    }
     69  }
     70 }
     71 
     72 }  // namespace
     73 
     74 GainApplier::GainApplier(bool hard_clip_samples, float initial_gain_factor)
     75    : hard_clip_samples_(hard_clip_samples),
     76      last_gain_factor_(initial_gain_factor),
     77      current_gain_factor_(initial_gain_factor) {}
     78 
     79 void GainApplier::ApplyGain(DeinterleavedView<float> signal) {
     80  if (static_cast<int>(signal.samples_per_channel()) != samples_per_channel_) {
     81    Initialize(signal.samples_per_channel());
     82  }
     83 
     84  ApplyGainWithRamping(last_gain_factor_, current_gain_factor_,
     85                       inverse_samples_per_channel_, signal);
     86 
     87  last_gain_factor_ = current_gain_factor_;
     88 
     89  if (hard_clip_samples_) {
     90    ClipSignal(signal);
     91  }
     92 }
     93 
     94 // TODO(bugs.webrtc.org/7494): Remove once switched to gains in dB.
     95 void GainApplier::SetGainFactor(float gain_factor) {
     96  RTC_DCHECK_GT(gain_factor, 0.f);
     97  current_gain_factor_ = gain_factor;
     98 }
     99 
    100 void GainApplier::Initialize(int samples_per_channel) {
    101  RTC_DCHECK_GT(samples_per_channel, 0);
    102  samples_per_channel_ = static_cast<int>(samples_per_channel);
    103  inverse_samples_per_channel_ = 1.f / samples_per_channel_;
    104 }
    105 
    106 }  // namespace webrtc