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 
21 #include "modules/audio_processing/agc/utility.h"
22 #include "test/gtest.h"
23 #include "test/testsupport/file_utils.h"
24 
25 namespace webrtc {
26 
27 struct InputOutput {
28   double rms;
29   double activity_probability;
30   double audio_content;
31   double loudness;
32 };
33 
34 const double kRelativeErrTol = 1e-10;
35 
36 class LoudnessHistogramTest : public ::testing::Test {
37  protected:
38   void RunTest(bool enable_circular_buff, const char* filename);
39 
40  private:
41   void TestClean();
42   std::unique_ptr<LoudnessHistogram> hist_;
43 };
44 
TestClean()45 void LoudnessHistogramTest::TestClean() {
46   EXPECT_EQ(hist_->CurrentRms(), 7.59621091765857e-02);
47   EXPECT_EQ(hist_->AudioContent(), 0);
48   EXPECT_EQ(hist_->num_updates(), 0);
49 }
50 
RunTest(bool enable_circular_buff,const char * filename)51 void LoudnessHistogramTest::RunTest(bool enable_circular_buff,
52                                     const char* filename) {
53   FILE* in_file = fopen(filename, "rb");
54   ASSERT_TRUE(in_file != NULL);
55   if (enable_circular_buff) {
56     int buffer_size;
57     EXPECT_EQ(fread(&buffer_size, sizeof(buffer_size), 1, in_file), 1u);
58     hist_.reset(LoudnessHistogram::Create(buffer_size));
59   } else {
60     hist_.reset(LoudnessHistogram::Create());
61   }
62   TestClean();
63 
64   InputOutput io;
65   int num_updates = 0;
66   int num_reset = 0;
67   while (fread(&io, sizeof(InputOutput), 1, in_file) == 1) {
68     if (io.rms < 0) {
69       // We have to reset.
70       hist_->Reset();
71       TestClean();
72       num_updates = 0;
73       num_reset++;
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