/*
 *  Copyright (c) 2013 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 "webrtc/modules/audio_processing/transient/transient_detector.h"

#include <assert.h>
#include <float.h>
#include <math.h>
#include <string.h>

#include "webrtc/modules/audio_processing/transient/common.h"
#include "webrtc/modules/audio_processing/transient/daubechies_8_wavelet_coeffs.h"
#include "webrtc/modules/audio_processing/transient/moving_moments.h"
#include "webrtc/modules/audio_processing/transient/wpd_tree.h"

namespace webrtc {

static const int kTransientLengthMs = 30;
static const int kChunksAtStartupLeftToDelete =
    kTransientLengthMs / ts::kChunkSizeMs;
static const float kDetectThreshold = 16.f;

TransientDetector::TransientDetector(int sample_rate_hz)
    : samples_per_chunk_(sample_rate_hz * ts::kChunkSizeMs / 1000),
      last_first_moment_(),
      last_second_moment_(),
      chunks_at_startup_left_to_delete_(kChunksAtStartupLeftToDelete),
      reference_energy_(1.f),
      using_reference_(false) {
  assert(sample_rate_hz == ts::kSampleRate8kHz ||
         sample_rate_hz == ts::kSampleRate16kHz ||
         sample_rate_hz == ts::kSampleRate32kHz ||
         sample_rate_hz == ts::kSampleRate48kHz);
  int samples_per_transient = sample_rate_hz * kTransientLengthMs / 1000;
  // Adjustment to avoid data loss while downsampling, making
  // |samples_per_chunk_| and |samples_per_transient| always divisible by
  // |kLeaves|.
  samples_per_chunk_ -= samples_per_chunk_ % kLeaves;
  samples_per_transient -= samples_per_transient % kLeaves;

  tree_leaves_data_length_ = samples_per_chunk_ / kLeaves;
  wpd_tree_.reset(new WPDTree(samples_per_chunk_,
                              kDaubechies8HighPassCoefficients,
                              kDaubechies8LowPassCoefficients,
                              kDaubechies8CoefficientsLength,
                              kLevels));
  for (size_t i = 0; i < kLeaves; ++i) {
    moving_moments_[i].reset(
        new MovingMoments(samples_per_transient / kLeaves));
  }

  first_moments_.reset(new float[tree_leaves_data_length_]);
  second_moments_.reset(new float[tree_leaves_data_length_]);

  for (int i = 0; i < kChunksAtStartupLeftToDelete; ++i) {
    previous_results_.push_back(0.f);
  }
}

TransientDetector::~TransientDetector() {}

float TransientDetector::Detect(const float* data,
                                size_t data_length,
                                const float* reference_data,
                                size_t reference_length) {
  assert(data && data_length == samples_per_chunk_);

  // TODO(aluebs): Check if these errors can logically happen and if not assert
  // on them.
  if (wpd_tree_->Update(data, samples_per_chunk_) != 0) {
    return -1.f;
  }

  float result = 0.f;

  for (size_t i = 0; i < kLeaves; ++i) {
    WPDNode* leaf = wpd_tree_->NodeAt(kLevels, i);

    moving_moments_[i]->CalculateMoments(leaf->data(),
                                         tree_leaves_data_length_,
                                         first_moments_.get(),
                                         second_moments_.get());

    // Add value delayed (Use the last moments from the last call to Detect).
    float unbiased_data = leaf->data()[0] - last_first_moment_[i];
    result +=
        unbiased_data * unbiased_data / (last_second_moment_[i] + FLT_MIN);

    // Add new values.
    for (size_t j = 1; j < tree_leaves_data_length_; ++j) {
      unbiased_data = leaf->data()[j] - first_moments_[j - 1];
      result +=
          unbiased_data * unbiased_data / (second_moments_[j - 1] + FLT_MIN);
    }

    last_first_moment_[i] = first_moments_[tree_leaves_data_length_ - 1];
    last_second_moment_[i] = second_moments_[tree_leaves_data_length_ - 1];
  }

  result /= tree_leaves_data_length_;

  result *= ReferenceDetectionValue(reference_data, reference_length);

  if (chunks_at_startup_left_to_delete_ > 0) {
    chunks_at_startup_left_to_delete_--;
    result = 0.f;
  }

  if (result >= kDetectThreshold) {
    result = 1.f;
  } else {
    // Get proportional value.
    // Proportion achieved with a squared raised cosine function with domain
    // [0, kDetectThreshold) and image [0, 1), it's always increasing.
    const float horizontal_scaling = ts::kPi / kDetectThreshold;
    const float kHorizontalShift = ts::kPi;
    const float kVerticalScaling = 0.5f;
    const float kVerticalShift = 1.f;

    result = (cos(result * horizontal_scaling + kHorizontalShift)
        + kVerticalShift) * kVerticalScaling;
    result *= result;
  }

  previous_results_.pop_front();
  previous_results_.push_back(result);

  // In the current implementation we return the max of the current result and
  // the previous results, so the high results have a width equals to
  // |transient_length|.
  return *std::max_element(previous_results_.begin(), previous_results_.end());
}

// Looks for the highest slope and compares it with the previous ones.
// An exponential transformation takes this to the [0, 1] range. This value is
// multiplied by the detection result to avoid false positives.
float TransientDetector::ReferenceDetectionValue(const float* data,
                                                 size_t length) {
  if (data == NULL) {
    using_reference_ = false;
    return 1.f;
  }
  static const float kEnergyRatioThreshold = 0.2f;
  static const float kReferenceNonLinearity = 20.f;
  static const float kMemory = 0.99f;
  float reference_energy = 0.f;
  for (size_t i = 1; i < length; ++i) {
    reference_energy += data[i] * data[i];
  }
  if (reference_energy == 0.f) {
    using_reference_ = false;
    return 1.f;
  }
  assert(reference_energy_ != 0);
  float result = 1.f / (1.f + exp(kReferenceNonLinearity *
                                  (kEnergyRatioThreshold -
                                   reference_energy / reference_energy_)));
  reference_energy_ =
      kMemory * reference_energy_ + (1.f - kMemory) * reference_energy;

  using_reference_ = true;

  return result;
}

}  // namespace webrtc
