/*
 * 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/WaveShaperDSPKernel.h"

#include <algorithm>
#include <memory>

#include "platform/audio/AudioUtilities.h"
#include "platform/wtf/Threading.h"

namespace blink {

WaveShaperDSPKernel::WaveShaperDSPKernel(WaveShaperProcessor* processor)
    : AudioDSPKernel(processor) {
  if (processor->Oversample() != WaveShaperProcessor::kOverSampleNone)
    LazyInitializeOversampling();
}

void WaveShaperDSPKernel::LazyInitializeOversampling() {
  if (!temp_buffer_) {
    temp_buffer_ = std::make_unique<AudioFloatArray>(
        AudioUtilities::kRenderQuantumFrames * 2);
    temp_buffer2_ = std::make_unique<AudioFloatArray>(
        AudioUtilities::kRenderQuantumFrames * 4);
    up_sampler_ =
        std::make_unique<UpSampler>(AudioUtilities::kRenderQuantumFrames);
    down_sampler_ =
        std::make_unique<DownSampler>(AudioUtilities::kRenderQuantumFrames * 2);
    up_sampler2_ =
        std::make_unique<UpSampler>(AudioUtilities::kRenderQuantumFrames * 2);
    down_sampler2_ =
        std::make_unique<DownSampler>(AudioUtilities::kRenderQuantumFrames * 4);
  }
}

void WaveShaperDSPKernel::Process(const float* source,
                                  float* destination,
                                  size_t frames_to_process) {
  switch (GetWaveShaperProcessor()->Oversample()) {
    case WaveShaperProcessor::kOverSampleNone:
      ProcessCurve(source, destination, frames_to_process);
      break;
    case WaveShaperProcessor::kOverSample2x:
      ProcessCurve2x(source, destination, frames_to_process);
      break;
    case WaveShaperProcessor::kOverSample4x:
      ProcessCurve4x(source, destination, frames_to_process);
      break;

    default:
      NOTREACHED();
  }
}

void WaveShaperDSPKernel::ProcessCurve(const float* source,
                                       float* destination,
                                       size_t frames_to_process) {
  DCHECK(source);
  DCHECK(destination);
  DCHECK(GetWaveShaperProcessor());

  Vector<float>* curve = GetWaveShaperProcessor()->Curve();
  if (!curve) {
    // Act as "straight wire" pass-through if no curve is set.
    memcpy(destination, source, sizeof(float) * frames_to_process);
    return;
  }

  float* curve_data = curve->data();
  int curve_length = curve->size();

  DCHECK(curve_data);

  if (!curve_data || !curve_length) {
    memcpy(destination, source, sizeof(float) * frames_to_process);
    return;
  }

  // Apply waveshaping curve.
  for (unsigned i = 0; i < frames_to_process; ++i) {
    const float input = source[i];

    // Calculate a virtual index based on input -1 -> +1 with -1 being curve[0],
    // +1 being curve[curveLength - 1], and 0 being at the center of the curve
    // data. Then linearly interpolate between the two points in the curve.
    double virtual_index = 0.5 * (input + 1) * (curve_length - 1);
    double output;

    if (virtual_index < 0) {
      // input < -1, so use curve[0]
      output = curve_data[0];
    } else if (virtual_index >= curve_length - 1) {
      // input >= 1, so use last curve value
      output = curve_data[curve_length - 1];
    } else {
      // The general case where -1 <= input < 1, where 0 <= virtualIndex <
      // curveLength - 1, so interpolate between the nearest samples on the
      // curve.
      unsigned index1 = static_cast<unsigned>(virtual_index);
      unsigned index2 = index1 + 1;
      double interpolation_factor = virtual_index - index1;

      double value1 = curve_data[index1];
      double value2 = curve_data[index2];

      output =
          (1.0 - interpolation_factor) * value1 + interpolation_factor * value2;
    }
    destination[i] = output;
  }
}

void WaveShaperDSPKernel::ProcessCurve2x(const float* source,
                                         float* destination,
                                         size_t frames_to_process) {
  bool is_safe = frames_to_process == AudioUtilities::kRenderQuantumFrames;
  DCHECK(is_safe);
  if (!is_safe)
    return;

  float* temp_p = temp_buffer_->Data();

  up_sampler_->Process(source, temp_p, frames_to_process);

  // Process at 2x up-sampled rate.
  ProcessCurve(temp_p, temp_p, frames_to_process * 2);

  down_sampler_->Process(temp_p, destination, frames_to_process * 2);
}

void WaveShaperDSPKernel::ProcessCurve4x(const float* source,
                                         float* destination,
                                         size_t frames_to_process) {
  bool is_safe = frames_to_process == AudioUtilities::kRenderQuantumFrames;
  DCHECK(is_safe);
  if (!is_safe)
    return;

  float* temp_p = temp_buffer_->Data();
  float* temp_p2 = temp_buffer2_->Data();

  up_sampler_->Process(source, temp_p, frames_to_process);
  up_sampler2_->Process(temp_p, temp_p2, frames_to_process * 2);

  // Process at 4x up-sampled rate.
  ProcessCurve(temp_p2, temp_p2, frames_to_process * 4);

  down_sampler2_->Process(temp_p2, temp_p, frames_to_process * 4);
  down_sampler_->Process(temp_p, destination, frames_to_process * 2);
}

void WaveShaperDSPKernel::Reset() {
  if (up_sampler_) {
    up_sampler_->Reset();
    down_sampler_->Reset();
    up_sampler2_->Reset();
    down_sampler2_->Reset();
  }
}

double WaveShaperDSPKernel::LatencyTime() const {
  size_t latency_frames = 0;
  WaveShaperDSPKernel* kernel = const_cast<WaveShaperDSPKernel*>(this);

  switch (kernel->GetWaveShaperProcessor()->Oversample()) {
    case WaveShaperProcessor::kOverSampleNone:
      break;
    case WaveShaperProcessor::kOverSample2x:
      latency_frames += up_sampler_->LatencyFrames();
      latency_frames += down_sampler_->LatencyFrames();
      break;
    case WaveShaperProcessor::kOverSample4x: {
      // Account for first stage upsampling.
      latency_frames += up_sampler_->LatencyFrames();
      latency_frames += down_sampler_->LatencyFrames();

      // Account for second stage upsampling.
      // and divide by 2 to get back down to the regular sample-rate.
      size_t latency_frames2 =
          (up_sampler2_->LatencyFrames() + down_sampler2_->LatencyFrames()) / 2;
      latency_frames += latency_frames2;
      break;
    }
    default:
      NOTREACHED();
  }

  return static_cast<double>(latency_frames) / SampleRate();
}

}  // namespace blink
