xref: /aosp_15_r20/external/webrtc/modules/audio_processing/agc/loudness_histogram_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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 // Use CreateHistUnittestFile.m to generate the input file.
12 
13 #include "modules/audio_processing/agc/loudness_histogram.h"
14 
15 #include <stdio.h>
16 
17 #include <algorithm>
18 #include <cmath>
19 #include <memory>
20 #include <string>
21 
22 #include "absl/strings/string_view.h"
23 #include "modules/audio_processing/agc/utility.h"
24 #include "test/gtest.h"
25 #include "test/testsupport/file_utils.h"
26 
27 namespace webrtc {
28 
29 struct InputOutput {
30   double rms;
31   double activity_probability;
32   double audio_content;
33   double loudness;
34 };
35 
36 const double kRelativeErrTol = 1e-10;
37 
38 class LoudnessHistogramTest : public ::testing::Test {
39  protected:
40   void RunTest(bool enable_circular_buff, absl::string_view filename);
41 
42  private:
43   void TestClean();
44   std::unique_ptr<LoudnessHistogram> hist_;
45 };
46 
TestClean()47 void LoudnessHistogramTest::TestClean() {
48   EXPECT_EQ(hist_->CurrentRms(), 7.59621091765857e-02);
49   EXPECT_EQ(hist_->AudioContent(), 0);
50   EXPECT_EQ(hist_->num_updates(), 0);
51 }
52 
RunTest(bool enable_circular_buff,absl::string_view filename)53 void LoudnessHistogramTest::RunTest(bool enable_circular_buff,
54                                     absl::string_view filename) {
55   FILE* in_file = fopen(std::string(filename).c_str(), "rb");
56   ASSERT_TRUE(in_file != NULL);
57   if (enable_circular_buff) {
58     int buffer_size;
59     EXPECT_EQ(fread(&buffer_size, sizeof(buffer_size), 1, in_file), 1u);
60     hist_.reset(LoudnessHistogram::Create(buffer_size));
61   } else {
62     hist_.reset(LoudnessHistogram::Create());
63   }
64   TestClean();
65 
66   InputOutput io;
67   int num_updates = 0;
68   while (fread(&io, sizeof(InputOutput), 1, in_file) == 1) {
69     if (io.rms < 0) {
70       // We have to reset.
71       hist_->Reset();
72       TestClean();
73       num_updates = 0;
74       // Read the next chunk of input.
75       if (fread(&io, sizeof(InputOutput), 1, in_file) != 1)
76         break;
77     }
78     hist_->Update(io.rms, io.activity_probability);
79     num_updates++;
80     EXPECT_EQ(hist_->num_updates(), num_updates);
81     double audio_content = hist_->AudioContent();
82 
83     double abs_err =
84         std::min(audio_content, io.audio_content) * kRelativeErrTol;
85 
86     ASSERT_NEAR(audio_content, io.audio_content, abs_err);
87     double current_loudness = Linear2Loudness(hist_->CurrentRms());
88     abs_err =
89         std::min(fabs(current_loudness), fabs(io.loudness)) * kRelativeErrTol;
90     ASSERT_NEAR(current_loudness, io.loudness, abs_err);
91   }
92   fclose(in_file);
93 }
94 
TEST_F(LoudnessHistogramTest,ActiveCircularBuffer)95 TEST_F(LoudnessHistogramTest, ActiveCircularBuffer) {
96   RunTest(true, test::ResourcePath(
97                     "audio_processing/agc/agc_with_circular_buffer", "dat")
98                     .c_str());
99 }
100 
TEST_F(LoudnessHistogramTest,InactiveCircularBuffer)101 TEST_F(LoudnessHistogramTest, InactiveCircularBuffer) {
102   RunTest(false, test::ResourcePath(
103                      "audio_processing/agc/agc_no_circular_buffer", "dat")
104                      .c_str());
105 }
106 
107 }  // namespace webrtc
108