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

#include "modules/audio_processing/rms_level.h"

#include <math.h>
#include <algorithm>
#include <numeric>

#include "rtc_base/checks.h"

namespace webrtc {
namespace {
static constexpr float kMaxSquaredLevel = 32768 * 32768;
// kMinLevel is the level corresponding to kMinLevelDb, that is 10^(-127/10).
static constexpr float kMinLevel = 1.995262314968883e-13f;

// Calculates the normalized RMS value from a mean square value. The input
// should be the sum of squared samples divided by the number of samples. The
// value will be normalized to full range before computing the RMS, wich is
// returned as a negated dBfs. That is, 0 is full amplitude while 127 is very
// faint.
int ComputeRms(float mean_square) {
  if (mean_square <= kMinLevel * kMaxSquaredLevel) {
    // Very faint; simply return the minimum value.
    return RmsLevel::kMinLevelDb;
  }
  // Normalize by the max level.
  const float mean_square_norm = mean_square / kMaxSquaredLevel;
  RTC_DCHECK_GT(mean_square_norm, kMinLevel);
  // 20log_10(x^0.5) = 10log_10(x)
  const float rms = 10.f * log10(mean_square_norm);
  RTC_DCHECK_LE(rms, 0.f);
  RTC_DCHECK_GT(rms, -RmsLevel::kMinLevelDb);
  // Return the negated value.
  return static_cast<int>(-rms + 0.5f);
}
}  // namespace

RmsLevel::RmsLevel() {
  Reset();
}

RmsLevel::~RmsLevel() = default;

void RmsLevel::Reset() {
  sum_square_ = 0.f;
  sample_count_ = 0;
  max_sum_square_ = 0.f;
  block_size_ = rtc::nullopt;
}

void RmsLevel::Analyze(rtc::ArrayView<const int16_t> data) {
  if (data.empty()) {
    return;
  }

  CheckBlockSize(data.size());

  const float sum_square =
      std::accumulate(data.begin(), data.end(), 0.f,
                      [](float a, int16_t b) { return a + b * b; });
  RTC_DCHECK_GE(sum_square, 0.f);
  sum_square_ += sum_square;
  sample_count_ += data.size();

  max_sum_square_ = std::max(max_sum_square_, sum_square);
}

void RmsLevel::AnalyzeMuted(size_t length) {
  CheckBlockSize(length);
  sample_count_ += length;
}

int RmsLevel::Average() {
  int rms = (sample_count_ == 0) ? RmsLevel::kMinLevelDb
                                 : ComputeRms(sum_square_ / sample_count_);
  Reset();
  return rms;
}

RmsLevel::Levels RmsLevel::AverageAndPeak() {
  // Note that block_size_ should by design always be non-empty when
  // sample_count_ != 0. Also, the * operator of rtc::Optional enforces this
  // with a DCHECK.
  Levels levels = (sample_count_ == 0)
                      ? Levels{RmsLevel::kMinLevelDb, RmsLevel::kMinLevelDb}
                      : Levels{ComputeRms(sum_square_ / sample_count_),
                               ComputeRms(max_sum_square_ / *block_size_)};
  Reset();
  return levels;
}

void RmsLevel::CheckBlockSize(size_t block_size) {
  if (block_size_ != block_size) {
    Reset();
    block_size_ = block_size;
  }
}
}  // namespace webrtc
