/*
 *  Copyright (c) 2012 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.
 */

// Use CreateHistUnittestFile.m to generate the input file.

#include "modules/audio_processing/agc/loudness_histogram.h"

#include <stdio.h>

#include <algorithm>
#include <cmath>
#include <memory>
#include <string>

#include "absl/strings/string_view.h"
#include "modules/audio_processing/agc/utility.h"
#include "test/gtest.h"
#include "test/testsupport/file_utils.h"

namespace webrtc {

struct InputOutput {
  double rms;
  double activity_probability;
  double audio_content;
  double loudness;
};

const double kRelativeErrTol = 1e-10;

class LoudnessHistogramTest : public ::testing::Test {
 protected:
  void RunTest(bool enable_circular_buff, absl::string_view filename);

 private:
  void TestClean();
  std::unique_ptr<LoudnessHistogram> hist_;
};

void LoudnessHistogramTest::TestClean() {
  EXPECT_EQ(hist_->CurrentRms(), 7.59621091765857e-02);
  EXPECT_EQ(hist_->AudioContent(), 0);
  EXPECT_EQ(hist_->num_updates(), 0);
}

void LoudnessHistogramTest::RunTest(bool enable_circular_buff,
                                    absl::string_view filename) {
  FILE* in_file = fopen(std::string(filename).c_str(), "rb");
  ASSERT_TRUE(in_file != NULL);
  if (enable_circular_buff) {
    int buffer_size;
    EXPECT_EQ(fread(&buffer_size, sizeof(buffer_size), 1, in_file), 1u);
    hist_.reset(LoudnessHistogram::Create(buffer_size));
  } else {
    hist_.reset(LoudnessHistogram::Create());
  }
  TestClean();

  InputOutput io;
  int num_updates = 0;
  while (fread(&io, sizeof(InputOutput), 1, in_file) == 1) {
    if (io.rms < 0) {
      // We have to reset.
      hist_->Reset();
      TestClean();
      num_updates = 0;
      // Read the next chunk of input.
      if (fread(&io, sizeof(InputOutput), 1, in_file) != 1)
        break;
    }
    hist_->Update(io.rms, io.activity_probability);
    num_updates++;
    EXPECT_EQ(hist_->num_updates(), num_updates);
    double audio_content = hist_->AudioContent();

    double abs_err =
        std::min(audio_content, io.audio_content) * kRelativeErrTol;

    ASSERT_NEAR(audio_content, io.audio_content, abs_err);
    double current_loudness = Linear2Loudness(hist_->CurrentRms());
    abs_err =
        std::min(fabs(current_loudness), fabs(io.loudness)) * kRelativeErrTol;
    ASSERT_NEAR(current_loudness, io.loudness, abs_err);
  }
  fclose(in_file);
}

TEST_F(LoudnessHistogramTest, ActiveCircularBuffer) {
  RunTest(true, test::ResourcePath(
                    "audio_processing/agc/agc_with_circular_buffer", "dat")
                    .c_str());
}

TEST_F(LoudnessHistogramTest, InactiveCircularBuffer) {
  RunTest(false, test::ResourcePath(
                     "audio_processing/agc/agc_no_circular_buffer", "dat")
                     .c_str());
}

}  // namespace webrtc
