/* * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef MODULES_AUDIO_PROCESSING_AGC_CLIPPING_PREDICTOR_EVALUATOR_H_ #define MODULES_AUDIO_PROCESSING_AGC_CLIPPING_PREDICTOR_EVALUATOR_H_ #include #include "absl/types/optional.h" namespace webrtc { // Clipping prediction counters. struct ClippingPredictionCounters { int true_positives; // TP. int true_negatives; // TN. int false_positives; // FP. int false_negatives; // FN. }; // Counts true/false positives/negatives while observing sequences of flag pairs // that indicate whether clipping has been detected and/or if clipping is // predicted. When a true positive is found measures the time interval between // prediction and detection events. // After a prediction is observed and for a period equal to // `history_size` calls to `Observe()`, one or more detections are expected. If // the expectation is met, a true positive is added and the time interval // between the earliest prediction and the detection is recorded; otherwise, // when the deadline is reached, a false positive is added. Note that one // detection matches all the expected detections that have not expired - i.e., // one detection counts as multiple true positives. // If a detection is observed, but no prediction has been observed over the past // `history_size` calls to `Observe()`, then a false negative is added; // otherwise, a true negative is added. class ClippingPredictorEvaluator { public: // Ctor. `history_size` indicates how long to wait for a call to `Observe()` // having `clipping_detected` set to true from the time clipping is predicted. explicit ClippingPredictorEvaluator(int history_size); ClippingPredictorEvaluator(const ClippingPredictorEvaluator&) = delete; ClippingPredictorEvaluator& operator=(const ClippingPredictorEvaluator&) = delete; ~ClippingPredictorEvaluator(); // Observes whether clipping has been detected and/or if clipping is // predicted. When predicted one or more detections are expected in the next // `history_size_` calls of `Observe()`. When true positives are found returns // the prediction interval between the earliest prediction and the detection. absl::optional Observe(bool clipping_detected, bool clipping_predicted); // Removes any expectation recently set after a call to `Observe()` having // `clipping_predicted` set to true. Counters won't be reset. void RemoveExpectations(); // Resets counters and removes any expectation (see `RemoveExpectations()`). void Reset(); ClippingPredictionCounters counters() const { return counters_; } private: const int history_size_; // State of a detection expected to be observed after a prediction. struct ExpectedDetection { // Time to live (TTL); remaining number of `Observe()` calls to match a call // having `clipping_detected` set to true. int ttl; // True if an `Observe()` call having `clipping_detected` set to true has // been observed. bool detected; }; // Ring buffer of expected detections. const int ring_buffer_capacity_; std::vector ring_buffer_; int ring_buffer_tail_; int ring_buffer_size_; // Pushes `expected_detection` into `expected_matches_ring_buffer_`. void Push(ExpectedDetection expected_detection); // Decreased the TTLs in `expected_matches_ring_buffer_` and removes expired // items. void DecreaseTimesToLive(); // Returns the prediction interval for the earliest unexpired expected // detection if any. absl::optional FindEarliestPredictionInterval() const; // Marks all the items in `expected_matches_ring_buffer_` as `detected` and // returns the number of updated items. int MarkExpectedDetectionAsDetected(); // Returns true if `expected_matches_ring_buffer_` has an item having `ttl` // equal to 0 (expired) and `detected` equal to false (unmatched). bool HasExpiredUnmatchedExpectedDetection() const; // Counters. ClippingPredictionCounters counters_; }; // Clipping prediction metrics derived from the clipping prediction counters. struct ClippingPredictionMetrics { // Precision (P) is defined as TP / (TP + FP). float precision; // Recall (R) is defined as TP / (TP + FN). float recall; // The F1 score is defined as 2 * P * R / (P + R). float f1_score; }; // Derives clipping prediction metrics from the true/false positives/negatives // `counters`. Returns an unspecified value if one or more metrics are not // defined. absl::optional ComputeClippingPredictionMetrics( const ClippingPredictionCounters& counters); } // namespace webrtc #endif // MODULES_AUDIO_PROCESSING_AGC_CLIPPING_PREDICTOR_EVALUATOR_H_