/*
 *  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.
 */

#include "webrtc/modules/audio_processing/high_pass_filter_impl.h"

#include <assert.h>

#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_processing/audio_buffer.h"
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
#include "webrtc/typedefs.h"


namespace webrtc {
namespace {
const int16_t kFilterCoefficients8kHz[5] =
    {3798, -7596, 3798, 7807, -3733};

const int16_t kFilterCoefficients[5] =
    {4012, -8024, 4012, 8002, -3913};

struct FilterState {
  int16_t y[4];
  int16_t x[2];
  const int16_t* ba;
};

int InitializeFilter(FilterState* hpf, int sample_rate_hz) {
  assert(hpf != NULL);

  if (sample_rate_hz == AudioProcessing::kSampleRate8kHz) {
    hpf->ba = kFilterCoefficients8kHz;
  } else {
    hpf->ba = kFilterCoefficients;
  }

  WebRtcSpl_MemSetW16(hpf->x, 0, 2);
  WebRtcSpl_MemSetW16(hpf->y, 0, 4);

  return AudioProcessing::kNoError;
}

int Filter(FilterState* hpf, int16_t* data, size_t length) {
  assert(hpf != NULL);

  int32_t tmp_int32 = 0;
  int16_t* y = hpf->y;
  int16_t* x = hpf->x;
  const int16_t* ba = hpf->ba;

  for (size_t i = 0; i < length; i++) {
    //  y[i] = b[0] * x[i] + b[1] * x[i-1] + b[2] * x[i-2]
    //         + -a[1] * y[i-1] + -a[2] * y[i-2];

    tmp_int32 = y[1] * ba[3];  // -a[1] * y[i-1] (low part)
    tmp_int32 += y[3] * ba[4];  // -a[2] * y[i-2] (low part)
    tmp_int32 = (tmp_int32 >> 15);
    tmp_int32 += y[0] * ba[3];  // -a[1] * y[i-1] (high part)
    tmp_int32 += y[2] * ba[4];  // -a[2] * y[i-2] (high part)
    tmp_int32 = (tmp_int32 << 1);

    tmp_int32 += data[i] * ba[0];  // b[0]*x[0]
    tmp_int32 += x[0] * ba[1];  // b[1]*x[i-1]
    tmp_int32 += x[1] * ba[2];  // b[2]*x[i-2]

    // Update state (input part)
    x[1] = x[0];
    x[0] = data[i];

    // Update state (filtered part)
    y[2] = y[0];
    y[3] = y[1];
    y[0] = static_cast<int16_t>(tmp_int32 >> 13);
    y[1] = static_cast<int16_t>(
        (tmp_int32 - (static_cast<int32_t>(y[0]) << 13)) << 2);

    // Rounding in Q12, i.e. add 2^11
    tmp_int32 += 2048;

    // Saturate (to 2^27) so that the HP filtered signal does not overflow
    tmp_int32 = WEBRTC_SPL_SAT(static_cast<int32_t>(134217727),
                               tmp_int32,
                               static_cast<int32_t>(-134217728));

    // Convert back to Q0 and use rounding.
    data[i] = (int16_t)(tmp_int32 >> 12);
  }

  return AudioProcessing::kNoError;
}
}  // namespace

typedef FilterState Handle;

HighPassFilterImpl::HighPassFilterImpl(const AudioProcessing* apm,
                                       CriticalSectionWrapper* crit)
  : ProcessingComponent(),
    apm_(apm),
    crit_(crit) {}

HighPassFilterImpl::~HighPassFilterImpl() {}

int HighPassFilterImpl::ProcessCaptureAudio(AudioBuffer* audio) {
  int err = apm_->kNoError;

  if (!is_component_enabled()) {
    return apm_->kNoError;
  }

  assert(audio->num_frames_per_band() <= 160);

  for (int i = 0; i < num_handles(); i++) {
    Handle* my_handle = static_cast<Handle*>(handle(i));
    err = Filter(my_handle,
                 audio->split_bands(i)[kBand0To8kHz],
                 audio->num_frames_per_band());

    if (err != apm_->kNoError) {
      return GetHandleError(my_handle);
    }
  }

  return apm_->kNoError;
}

int HighPassFilterImpl::Enable(bool enable) {
  CriticalSectionScoped crit_scoped(crit_);
  return EnableComponent(enable);
}

bool HighPassFilterImpl::is_enabled() const {
  return is_component_enabled();
}

void* HighPassFilterImpl::CreateHandle() const {
  return new FilterState;
}

void HighPassFilterImpl::DestroyHandle(void* handle) const {
  delete static_cast<Handle*>(handle);
}

int HighPassFilterImpl::InitializeHandle(void* handle) const {
  return InitializeFilter(static_cast<Handle*>(handle),
                          apm_->proc_sample_rate_hz());
}

int HighPassFilterImpl::ConfigureHandle(void* /*handle*/) const {
  return apm_->kNoError; // Not configurable.
}

int HighPassFilterImpl::num_handles_required() const {
  return apm_->num_output_channels();
}

int HighPassFilterImpl::GetHandleError(void* handle) const {
  // The component has no detailed errors.
  assert(handle != NULL);
  return apm_->kUnspecifiedError;
}
}  // namespace webrtc
