tor-browser

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

agc.cc (2962B)


      1 /*
      2 *  Copyright (c) 2012 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/agc/agc.h"
     12 
     13 #include <cmath>
     14 #include <cstdint>
     15 #include <cstdlib>
     16 #include <vector>
     17 
     18 #include "api/array_view.h"
     19 #include "modules/audio_processing/agc/loudness_histogram.h"
     20 #include "modules/audio_processing/agc/utility.h"
     21 #include "rtc_base/checks.h"
     22 
     23 namespace webrtc {
     24 namespace {
     25 
     26 constexpr int kDefaultLevelDbfs = -18;
     27 constexpr int kNumAnalysisFrames = 100;
     28 constexpr double kActivityThreshold = 0.3;
     29 constexpr int kNum10msFramesInOneSecond = 100;
     30 constexpr int kMaxSampleRateHz = 384000;
     31 
     32 }  // namespace
     33 
     34 Agc::Agc()
     35    : target_level_loudness_(Dbfs2Loudness(kDefaultLevelDbfs)),
     36      target_level_dbfs_(kDefaultLevelDbfs),
     37      histogram_(LoudnessHistogram::Create(kNumAnalysisFrames)),
     38      inactive_histogram_(LoudnessHistogram::Create()) {}
     39 
     40 Agc::~Agc() = default;
     41 
     42 void Agc::Process(ArrayView<const int16_t> audio) {
     43  const int sample_rate_hz = audio.size() * kNum10msFramesInOneSecond;
     44  RTC_DCHECK_LE(sample_rate_hz, kMaxSampleRateHz);
     45  vad_.ProcessChunk(audio.data(), audio.size(), sample_rate_hz);
     46  const std::vector<double>& rms = vad_.chunkwise_rms();
     47  const std::vector<double>& probabilities =
     48      vad_.chunkwise_voice_probabilities();
     49  RTC_DCHECK_EQ(rms.size(), probabilities.size());
     50  for (size_t i = 0; i < rms.size(); ++i) {
     51    histogram_->Update(rms[i], probabilities[i]);
     52  }
     53 }
     54 
     55 bool Agc::GetRmsErrorDb(int* error) {
     56  if (!error) {
     57    RTC_DCHECK_NOTREACHED();
     58    return false;
     59  }
     60 
     61  if (histogram_->num_updates() < kNumAnalysisFrames) {
     62    // We haven't yet received enough frames.
     63    return false;
     64  }
     65 
     66  if (histogram_->AudioContent() < kNumAnalysisFrames * kActivityThreshold) {
     67    // We are likely in an inactive segment.
     68    return false;
     69  }
     70 
     71  double loudness = Linear2Loudness(histogram_->CurrentRms());
     72  *error = std::floor(Loudness2Db(target_level_loudness_ - loudness) + 0.5);
     73  histogram_->Reset();
     74  return true;
     75 }
     76 
     77 void Agc::Reset() {
     78  histogram_->Reset();
     79 }
     80 
     81 int Agc::set_target_level_dbfs(int level) {
     82  // TODO(turajs): just some arbitrary sanity check. We can come up with better
     83  // limits. The upper limit should be chosen such that the risk of clipping is
     84  // low. The lower limit should not result in a too quiet signal.
     85  if (level >= 0 || level <= -100)
     86    return -1;
     87  target_level_dbfs_ = level;
     88  target_level_loudness_ = Dbfs2Loudness(level);
     89  return 0;
     90 }
     91 
     92 int Agc::target_level_dbfs() const {
     93  return target_level_dbfs_;
     94 }
     95 
     96 float Agc::voice_probability() const {
     97  return vad_.last_voice_probability();
     98 }
     99 
    100 }  // namespace webrtc