tor-browser

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

limiter.cc (5692B)


      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/limiter.h"
     12 
     13 #include <algorithm>
     14 #include <array>
     15 #include <cmath>
     16 #include <cstddef>
     17 
     18 #include "absl/strings/string_view.h"
     19 #include "api/array_view.h"
     20 #include "api/audio/audio_view.h"
     21 #include "modules/audio_processing/agc2/agc2_common.h"
     22 #include "modules/audio_processing/agc2/interpolated_gain_curve.h"
     23 #include "modules/audio_processing/logging/apm_data_dumper.h"
     24 #include "rtc_base/checks.h"
     25 #include "rtc_base/numerics/safe_conversions.h"
     26 #include "rtc_base/numerics/safe_minmax.h"
     27 
     28 namespace webrtc {
     29 namespace {
     30 
     31 // This constant affects the way scaling factors are interpolated for the first
     32 // sub-frame of a frame. Only in the case in which the first sub-frame has an
     33 // estimated level which is greater than the that of the previous analyzed
     34 // sub-frame, linear interpolation is replaced with a power function which
     35 // reduces the chances of over-shooting (and hence saturation), however reducing
     36 // the fixed gain effectiveness.
     37 constexpr float kAttackFirstSubframeInterpolationPower = 8.0f;
     38 
     39 void InterpolateFirstSubframe(float last_factor,
     40                              float current_factor,
     41                              ArrayView<float> subframe) {
     42  const int n = dchecked_cast<int>(subframe.size());
     43  constexpr float p = kAttackFirstSubframeInterpolationPower;
     44  for (int i = 0; i < n; ++i) {
     45    float t = static_cast<float>(i) / n;
     46    subframe[i] =
     47        std::pow(1.f - t, p) * (last_factor - current_factor) + current_factor;
     48  }
     49 }
     50 
     51 void ComputePerSampleSubframeFactors(
     52    const std::array<float, kSubFramesInFrame + 1>& scaling_factors,
     53    MonoView<float> per_sample_scaling_factors) {
     54  const size_t num_subframes = scaling_factors.size() - 1;
     55  const int subframe_size = CheckedDivExact(
     56      SamplesPerChannel(per_sample_scaling_factors), num_subframes);
     57 
     58  // Handle first sub-frame differently in case of attack.
     59  const bool is_attack = scaling_factors[0] > scaling_factors[1];
     60  if (is_attack) {
     61    InterpolateFirstSubframe(
     62        scaling_factors[0], scaling_factors[1],
     63        per_sample_scaling_factors.subview(0, subframe_size));
     64  }
     65 
     66  for (size_t i = is_attack ? 1 : 0; i < num_subframes; ++i) {
     67    const int subframe_start = i * subframe_size;
     68    const float scaling_start = scaling_factors[i];
     69    const float scaling_end = scaling_factors[i + 1];
     70    const float scaling_diff = (scaling_end - scaling_start) / subframe_size;
     71    for (int j = 0; j < subframe_size; ++j) {
     72      per_sample_scaling_factors[subframe_start + j] =
     73          scaling_start + scaling_diff * j;
     74    }
     75  }
     76 }
     77 
     78 void ScaleSamples(MonoView<const float> per_sample_scaling_factors,
     79                  DeinterleavedView<float> signal) {
     80  const int samples_per_channel = signal.samples_per_channel();
     81  RTC_DCHECK_EQ(samples_per_channel,
     82                SamplesPerChannel(per_sample_scaling_factors));
     83  for (size_t i = 0; i < signal.num_channels(); ++i) {
     84    MonoView<float> channel = signal[i];
     85    for (int j = 0; j < samples_per_channel; ++j) {
     86      channel[j] = SafeClamp(channel[j] * per_sample_scaling_factors[j],
     87                             kMinFloatS16Value, kMaxFloatS16Value);
     88    }
     89  }
     90 }
     91 }  // namespace
     92 
     93 Limiter::Limiter(ApmDataDumper* apm_data_dumper,
     94                 size_t samples_per_channel,
     95                 absl::string_view histogram_name)
     96    : interp_gain_curve_(apm_data_dumper, histogram_name),
     97      level_estimator_(samples_per_channel, apm_data_dumper),
     98      apm_data_dumper_(apm_data_dumper) {
     99  RTC_DCHECK_LE(samples_per_channel, kMaximalNumberOfSamplesPerChannel);
    100 }
    101 
    102 Limiter::~Limiter() = default;
    103 
    104 void Limiter::Process(DeinterleavedView<float> signal) {
    105  RTC_DCHECK_LE(signal.samples_per_channel(),
    106                kMaximalNumberOfSamplesPerChannel);
    107 
    108  const std::array<float, kSubFramesInFrame> level_estimate =
    109      level_estimator_.ComputeLevel(signal);
    110 
    111  RTC_DCHECK_EQ(level_estimate.size() + 1, scaling_factors_.size());
    112  scaling_factors_[0] = last_scaling_factor_;
    113  std::transform(level_estimate.begin(), level_estimate.end(),
    114                 scaling_factors_.begin() + 1, [this](float x) {
    115                   return interp_gain_curve_.LookUpGainToApply(x);
    116                 });
    117 
    118  MonoView<float> per_sample_scaling_factors(&per_sample_scaling_factors_[0],
    119                                             signal.samples_per_channel());
    120  ComputePerSampleSubframeFactors(scaling_factors_, per_sample_scaling_factors);
    121  ScaleSamples(per_sample_scaling_factors, signal);
    122 
    123  last_scaling_factor_ = scaling_factors_.back();
    124 
    125  // Dump data for debug.
    126  apm_data_dumper_->DumpRaw("agc2_limiter_last_scaling_factor",
    127                            last_scaling_factor_);
    128  apm_data_dumper_->DumpRaw(
    129      "agc2_limiter_region",
    130      static_cast<int>(interp_gain_curve_.get_stats().region));
    131 }
    132 
    133 InterpolatedGainCurve::Stats Limiter::GetGainCurveStats() const {
    134  return interp_gain_curve_.get_stats();
    135 }
    136 
    137 void Limiter::SetSamplesPerChannel(size_t samples_per_channel) {
    138  RTC_DCHECK_LE(samples_per_channel, kMaximalNumberOfSamplesPerChannel);
    139  level_estimator_.SetSamplesPerChannel(samples_per_channel);
    140 }
    141 
    142 void Limiter::Reset() {
    143  level_estimator_.Reset();
    144 }
    145 
    146 float Limiter::LastAudioLevel() const {
    147  return level_estimator_.LastAudioLevel();
    148 }
    149 
    150 }  // namespace webrtc