xref: /aosp_15_r20/external/webrtc/modules/audio_processing/agc2/clipping_predictor_level_buffer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2021 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/clipping_predictor_level_buffer.h"
12 
13 #include <algorithm>
14 #include <cmath>
15 
16 #include "rtc_base/checks.h"
17 #include "rtc_base/logging.h"
18 
19 namespace webrtc {
20 
operator ==(const Level & level) const21 bool ClippingPredictorLevelBuffer::Level::operator==(const Level& level) const {
22   constexpr float kEpsilon = 1e-6f;
23   return std::fabs(average - level.average) < kEpsilon &&
24          std::fabs(max - level.max) < kEpsilon;
25 }
26 
ClippingPredictorLevelBuffer(int capacity)27 ClippingPredictorLevelBuffer::ClippingPredictorLevelBuffer(int capacity)
28     : tail_(-1), size_(0), data_(std::max(1, capacity)) {
29   if (capacity > kMaxCapacity) {
30     RTC_LOG(LS_WARNING) << "[agc]: ClippingPredictorLevelBuffer exceeds the "
31                         << "maximum allowed capacity. Capacity: " << capacity;
32   }
33   RTC_DCHECK(!data_.empty());
34 }
35 
Reset()36 void ClippingPredictorLevelBuffer::Reset() {
37   tail_ = -1;
38   size_ = 0;
39 }
40 
Push(Level level)41 void ClippingPredictorLevelBuffer::Push(Level level) {
42   ++tail_;
43   if (tail_ == Capacity()) {
44     tail_ = 0;
45   }
46   if (size_ < Capacity()) {
47     size_++;
48   }
49   data_[tail_] = level;
50 }
51 
52 // TODO(bugs.webrtc.org/12774): Optimize partial computation for long buffers.
53 absl::optional<ClippingPredictorLevelBuffer::Level>
ComputePartialMetrics(int delay,int num_items) const54 ClippingPredictorLevelBuffer::ComputePartialMetrics(int delay,
55                                                     int num_items) const {
56   RTC_DCHECK_GE(delay, 0);
57   RTC_DCHECK_LT(delay, Capacity());
58   RTC_DCHECK_GT(num_items, 0);
59   RTC_DCHECK_LE(num_items, Capacity());
60   RTC_DCHECK_LE(delay + num_items, Capacity());
61   if (delay + num_items > Size()) {
62     return absl::nullopt;
63   }
64   float sum = 0.0f;
65   float max = 0.0f;
66   for (int i = 0; i < num_items && i < Size(); ++i) {
67     int idx = tail_ - delay - i;
68     if (idx < 0) {
69       idx += Capacity();
70     }
71     sum += data_[idx].average;
72     max = std::fmax(data_[idx].max, max);
73   }
74   return absl::optional<Level>({sum / static_cast<float>(num_items), max});
75 }
76 
77 }  // namespace webrtc
78