/*
 * Copyright (C) 2011, Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1.  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */

#include "modules/webaudio/DynamicsCompressorNode.h"
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "modules/webaudio/AudioNodeInput.h"
#include "modules/webaudio/AudioNodeOutput.h"
#include "modules/webaudio/DynamicsCompressorOptions.h"
#include "platform/audio/AudioUtilities.h"
#include "platform/audio/DynamicsCompressor.h"

// Set output to stereo by default.
static const unsigned defaultNumberOfOutputChannels = 2;

namespace blink {

DynamicsCompressorHandler::DynamicsCompressorHandler(
    AudioNode& node,
    float sample_rate,
    AudioParamHandler& threshold,
    AudioParamHandler& knee,
    AudioParamHandler& ratio,
    AudioParamHandler& attack,
    AudioParamHandler& release)
    : AudioHandler(kNodeTypeDynamicsCompressor, node, sample_rate),
      threshold_(&threshold),
      knee_(&knee),
      ratio_(&ratio),
      reduction_(0),
      attack_(&attack),
      release_(&release) {
  AddInput();
  AddOutput(defaultNumberOfOutputChannels);
  Initialize();
}

scoped_refptr<DynamicsCompressorHandler> DynamicsCompressorHandler::Create(
    AudioNode& node,
    float sample_rate,
    AudioParamHandler& threshold,
    AudioParamHandler& knee,
    AudioParamHandler& ratio,
    AudioParamHandler& attack,
    AudioParamHandler& release) {
  return base::AdoptRef(new DynamicsCompressorHandler(
      node, sample_rate, threshold, knee, ratio, attack, release));
}

DynamicsCompressorHandler::~DynamicsCompressorHandler() {
  Uninitialize();
}

void DynamicsCompressorHandler::Process(size_t frames_to_process) {
  AudioBus* output_bus = Output(0).Bus();
  DCHECK(output_bus);

  float threshold = threshold_->Value();
  float knee = knee_->Value();
  float ratio = ratio_->Value();
  float attack = attack_->Value();
  float release = release_->Value();

  dynamics_compressor_->SetParameterValue(DynamicsCompressor::kParamThreshold,
                                          threshold);
  dynamics_compressor_->SetParameterValue(DynamicsCompressor::kParamKnee, knee);
  dynamics_compressor_->SetParameterValue(DynamicsCompressor::kParamRatio,
                                          ratio);
  dynamics_compressor_->SetParameterValue(DynamicsCompressor::kParamAttack,
                                          attack);
  dynamics_compressor_->SetParameterValue(DynamicsCompressor::kParamRelease,
                                          release);

  dynamics_compressor_->Process(Input(0).Bus(), output_bus, frames_to_process);

  reduction_ =
      dynamics_compressor_->ParameterValue(DynamicsCompressor::kParamReduction);
}

void DynamicsCompressorHandler::ProcessOnlyAudioParams(
    size_t frames_to_process) {
  DCHECK(Context()->IsAudioThread());
  DCHECK_LE(frames_to_process, AudioUtilities::kRenderQuantumFrames);

  float values[AudioUtilities::kRenderQuantumFrames];

  threshold_->CalculateSampleAccurateValues(values, frames_to_process);
  knee_->CalculateSampleAccurateValues(values, frames_to_process);
  ratio_->CalculateSampleAccurateValues(values, frames_to_process);
  attack_->CalculateSampleAccurateValues(values, frames_to_process);
  release_->CalculateSampleAccurateValues(values, frames_to_process);
}

void DynamicsCompressorHandler::Initialize() {
  if (IsInitialized())
    return;

  AudioHandler::Initialize();
  dynamics_compressor_ = std::make_unique<DynamicsCompressor>(
      Context()->sampleRate(), defaultNumberOfOutputChannels);
}

void DynamicsCompressorHandler::ClearInternalStateWhenDisabled() {
  reduction_ = 0;
}

double DynamicsCompressorHandler::TailTime() const {
  return dynamics_compressor_->TailTime();
}

double DynamicsCompressorHandler::LatencyTime() const {
  return dynamics_compressor_->LatencyTime();
}

void DynamicsCompressorHandler::SetChannelCount(
    unsigned long channel_count,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());
  BaseAudioContext::GraphAutoLocker locker(Context());

  // A DynamicsCompressorNode only supports 1 or 2 channels
  if (channel_count > 0 && channel_count <= 2) {
    if (channel_count_ != channel_count) {
      channel_count_ = channel_count;
      if (InternalChannelCountMode() != kMax)
        UpdateChannelsForInputs();
    }
  } else {
    exception_state.ThrowDOMException(
        kNotSupportedError, ExceptionMessages::IndexOutsideRange<unsigned long>(
                                "channelCount", channel_count, 1,
                                ExceptionMessages::kInclusiveBound, 2,
                                ExceptionMessages::kInclusiveBound));
  }
}

void DynamicsCompressorHandler::SetChannelCountMode(
    const String& mode,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());
  BaseAudioContext::GraphAutoLocker locker(Context());

  ChannelCountMode old_mode = InternalChannelCountMode();

  if (mode == "clamped-max") {
    new_channel_count_mode_ = kClampedMax;
  } else if (mode == "explicit") {
    new_channel_count_mode_ = kExplicit;
  } else if (mode == "max") {
    // This is not supported for a DynamicsCompressorNode, which can
    // only handle 1 or 2 channels.
    exception_state.ThrowDOMException(kNotSupportedError,
                                      "The provided value 'max' is not an "
                                      "allowed value for ChannelCountMode");
    new_channel_count_mode_ = old_mode;
  } else {
    // Do nothing for other invalid values.
    new_channel_count_mode_ = old_mode;
  }

  if (new_channel_count_mode_ != old_mode)
    Context()->GetDeferredTaskHandler().AddChangedChannelCountMode(this);
}
// ----------------------------------------------------------------

DynamicsCompressorNode::DynamicsCompressorNode(BaseAudioContext& context)
    : AudioNode(context),
      threshold_(AudioParam::Create(context,
                                    kParamTypeDynamicsCompressorThreshold,
                                    "DynamicsCompressor.threshold",
                                    -24,
                                    -100,
                                    0)),
      knee_(AudioParam::Create(context,
                               kParamTypeDynamicsCompressorKnee,
                               "DynamicsCompressor.knee",
                               30,
                               0,
                               40)),
      ratio_(AudioParam::Create(context,
                                kParamTypeDynamicsCompressorRatio,
                                "DynamicsCompressor.ratio",
                                12,
                                1,
                                20)),
      attack_(AudioParam::Create(context,
                                 kParamTypeDynamicsCompressorAttack,
                                 "DynamicsCompressor.attack",
                                 0.003,
                                 0,
                                 1)),
      release_(AudioParam::Create(context,
                                  kParamTypeDynamicsCompressorRelease,
                                  "DynamicsCompressor.release",
                                  0.250,
                                  0,
                                  1)) {
  SetHandler(DynamicsCompressorHandler::Create(
      *this, context.sampleRate(), threshold_->Handler(), knee_->Handler(),
      ratio_->Handler(), attack_->Handler(), release_->Handler()));
}

DynamicsCompressorNode* DynamicsCompressorNode::Create(
    BaseAudioContext& context,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  if (context.IsContextClosed()) {
    context.ThrowExceptionForClosedState(exception_state);
    return nullptr;
  }

  return new DynamicsCompressorNode(context);
}

DynamicsCompressorNode* DynamicsCompressorNode::Create(
    BaseAudioContext* context,
    const DynamicsCompressorOptions& options,
    ExceptionState& exception_state) {
  DynamicsCompressorNode* node = Create(*context, exception_state);

  if (!node)
    return nullptr;

  node->HandleChannelOptions(options, exception_state);

  node->attack()->setValue(options.attack());
  node->knee()->setValue(options.knee());
  node->ratio()->setValue(options.ratio());
  node->release()->setValue(options.release());
  node->threshold()->setValue(options.threshold());

  return node;
}

void DynamicsCompressorNode::Trace(blink::Visitor* visitor) {
  visitor->Trace(threshold_);
  visitor->Trace(knee_);
  visitor->Trace(ratio_);
  visitor->Trace(attack_);
  visitor->Trace(release_);
  AudioNode::Trace(visitor);
}

DynamicsCompressorHandler&
DynamicsCompressorNode::GetDynamicsCompressorHandler() const {
  return static_cast<DynamicsCompressorHandler&>(Handler());
}

AudioParam* DynamicsCompressorNode::threshold() const {
  return threshold_;
}

AudioParam* DynamicsCompressorNode::knee() const {
  return knee_;
}

AudioParam* DynamicsCompressorNode::ratio() const {
  return ratio_;
}

float DynamicsCompressorNode::reduction() const {
  return GetDynamicsCompressorHandler().ReductionValue();
}

AudioParam* DynamicsCompressorNode::attack() const {
  return attack_;
}

AudioParam* DynamicsCompressorNode::release() const {
  return release_;
}

}  // namespace blink
