// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Modifications Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Input buffer layout, dividing the total buffer into regions (r0_ - r5_):
//
// |----------------|-----------------------------------------|----------------|
//
//                                   kBlockSize + kKernelSize / 2
//                   <--------------------------------------------------------->
//                                              r0_
//
//  kKernelSize / 2   kKernelSize / 2         kKernelSize / 2   kKernelSize / 2
// <---------------> <--------------->       <---------------> <--------------->
//        r1_               r2_                     r3_               r4_
//
//                                                     kBlockSize
//                                     <--------------------------------------->
//                                                        r5_
//
// The algorithm:
//
// 1) Consume input frames into r0_ (r1_ is zero-initialized).
// 2) Position kernel centered at start of r0_ (r2_) and generate output frames
//    until kernel is centered at start of r4_ or we've finished generating all
//    the output frames.
// 3) Copy r3_ to r1_ and r4_ to r2_.
// 4) Consume input frames into r5_ (zero-pad if we run out of input).
// 5) Goto (2) until all of input is consumed.
//
// Note: we're glossing over how the sub-sample handling works with
// |virtual_source_idx_|, etc.

#include "cobalt/media/base/interleaved_sinc_resampler.h"

#include <algorithm>
#include <cmath>

#include "base/logging.h"
#include "starboard/memory.h"

namespace cobalt {
namespace media {

namespace {

// The kernel size can be adjusted for quality (higher is better) at the
// expense of performance.  Must be a multiple of 32.
const int kKernelSize = 32;

// The number of destination frames generated per processing pass.  Affects
// how often and for how much InterleavedSincResampler calls back for input.
// Must be greater than kKernelSize.
const int kBlockSize = 512;

// The kernel offset count is used for interpolation and is the number of
// sub-sample kernel shifts.  Can be adjusted for quality (higher is better)
// at the expense of allocating more memory.
const int kKernelOffsetCount = 32;
const int kKernelStorageSize = kKernelSize * (kKernelOffsetCount + 1);

// The size (in samples) of the internal buffer used by the resampler.
const int kBufferSize = kBlockSize + kKernelSize;

// The maximum numbers of buffer can be queued.
const int kMaximumPendingBuffers = 8;

}  // namespace

class InterleavedSincResampler::Buffer
    : public base::RefCountedThreadSafe<Buffer> {
 public:
  Buffer() : data_(NULL), frames_(0) {}
  Buffer(const float* data, int frames, int channel_count) : frames_(frames) {
    data_.reset(new float[frames * channel_count]);
    SbMemoryCopy(data_.get(), data, frames * channel_count * sizeof(float));
  }
  Buffer(scoped_array<float> data, int frames)
      : data_(data.Pass()), frames_(frames) {}

  const float* GetData() const { return data_.get(); }

  int GetNumFrames() const { return frames_; }

  bool IsEndOfStream() const { return GetData() == NULL; }

 private:
  scoped_array<float> data_;
  int frames_;

  DISALLOW_COPY_AND_ASSIGN(Buffer);
};

InterleavedSincResampler::InterleavedSincResampler(double io_sample_rate_ratio,
                                                   int channel_count)
    : io_sample_rate_ratio_(io_sample_rate_ratio),
      virtual_source_idx_(0),
      buffer_primed_(false),
      channel_count_(channel_count),
      frame_size_in_bytes_(sizeof(float) * channel_count_),
      // Create buffers with a 16-byte alignment for possible optimizations.
      kernel_storage_(static_cast<float*>(
          base::AlignedAlloc(sizeof(float) * kKernelStorageSize, 16))),
      input_buffer_(static_cast<float*>(
          base::AlignedAlloc(frame_size_in_bytes_ * kBufferSize, 16))),
      offset_in_frames_(0),
      frames_resampled_(0),
      frames_queued_(0),
      // Setup various region pointers in the buffer (see diagram above).
      r0_(input_buffer_.get() + kKernelSize / 2 * channel_count_),
      r1_(input_buffer_.get()),
      r2_(r0_),
      r3_(r0_ + (kBlockSize - kKernelSize / 2) * channel_count_),
      r4_(r0_ + kBlockSize * channel_count_),
      r5_(r0_ + kKernelSize / 2 * channel_count_) {
  // Ensure kKernelSize is a multiple of 32 for easy SSE optimizations; causes
  // r0_ and r5_ (used for input) to always be 16-byte aligned by virtue of
  // input_buffer_ being 16-byte aligned.
  DCHECK_EQ(kKernelSize % 32, 0) << "kKernelSize must be a multiple of 32!";
  DCHECK_GT(kBlockSize, kKernelSize)
      << "kBlockSize must be greater than kKernelSize!";
  // Basic sanity checks to ensure buffer regions are laid out correctly:
  // r0_ and r2_ should always be the same position.
  DCHECK_EQ(r0_, r2_);
  // r1_ at the beginning of the buffer.
  DCHECK_EQ(r1_, input_buffer_.get());
  // r1_ left of r2_, r2_ left of r5_ and r1_, r2_ size correct.
  DCHECK_EQ(r2_ - r1_, r5_ - r2_);
  // r3_ left of r4_, r5_ left of r0_ and r3_ size correct.
  DCHECK_EQ(r4_ - r3_, r5_ - r0_);
  // r3_, r4_ size correct and r4_ at the end of the buffer.
  DCHECK_EQ(r4_ + (r4_ - r3_), r1_ + kBufferSize * channel_count_);
  // r5_ size correct and at the end of the buffer.
  DCHECK_EQ(r5_ + kBlockSize * channel_count_,
            r1_ + kBufferSize * channel_count_);

  SbMemorySet(kernel_storage_.get(), 0,
              sizeof(*kernel_storage_.get()) * kKernelStorageSize);
  SbMemorySet(input_buffer_.get(), 0, frame_size_in_bytes_ * kBufferSize);

  InitializeKernel();
}

InterleavedSincResampler::~InterleavedSincResampler() {}

void InterleavedSincResampler::InitializeKernel() {
  // Blackman window parameters.
  static const double kAlpha = 0.16;
  static const double kA0 = 0.5 * (1.0 - kAlpha);
  static const double kA1 = 0.5;
  static const double kA2 = 0.5 * kAlpha;

  // |sinc_scale_factor| is basically the normalized cutoff frequency of the
  // low-pass filter.
  double sinc_scale_factor =
      io_sample_rate_ratio_ > 1.0 ? 1.0 / io_sample_rate_ratio_ : 1.0;

  // The sinc function is an idealized brick-wall filter, but since we're
  // windowing it the transition from pass to stop does not happen right away.
  // So we should adjust the low pass filter cutoff slightly downward to avoid
  // some aliasing at the very high-end.
  // TODO: this value is empirical and to be more exact should vary depending
  // on kKernelSize.
  sinc_scale_factor *= 0.9;

  // Generates a set of windowed sinc() kernels.
  // We generate a range of sub-sample offsets from 0.0 to 1.0.
  for (int offset_idx = 0; offset_idx <= kKernelOffsetCount; ++offset_idx) {
    double subsample_offset =
        static_cast<double>(offset_idx) / kKernelOffsetCount;

    for (int i = 0; i < kKernelSize; ++i) {
      // Compute the sinc with offset.
      double s =
          sinc_scale_factor * M_PI * (i - kKernelSize / 2 - subsample_offset);
      double sinc = (!s ? 1.0 : sin(s) / s) * sinc_scale_factor;

      // Compute Blackman window, matching the offset of the sinc().
      double x = (i - subsample_offset) / kKernelSize;
      double window =
          kA0 - kA1 * cos(2.0 * M_PI * x) + kA2 * cos(4.0 * M_PI * x);

      // Window the sinc() function and store at the correct offset.
      kernel_storage_.get()[i + offset_idx * kKernelSize] = sinc * window;
    }
  }
}

void InterleavedSincResampler::QueueBuffer(const float* data, int frames) {
  DCHECK(CanQueueBuffer());

  if (!pending_buffers_.empty() && pending_buffers_.back()->IsEndOfStream()) {
    DCHECK(!data);
    return;
  }

  if (!data) {
    pending_buffers_.push(new Buffer);
    return;
  } else {
    frames_queued_ += frames;
    pending_buffers_.push(new Buffer(data, frames, channel_count_));
  }
}

void InterleavedSincResampler::QueueBuffer(scoped_array<float> data,
                                           int frames) {
  DCHECK(CanQueueBuffer());

  if (!pending_buffers_.empty() && pending_buffers_.back()->IsEndOfStream()) {
    DCHECK(!data.get());
    return;
  }

  if (!data.get()) {
    pending_buffers_.push(new Buffer);
    return;
  } else {
    frames_queued_ += frames;
    pending_buffers_.push(new Buffer(data.Pass(), frames));
  }
}

void InterleavedSincResampler::Resample(float* destination, int frames) {
  DCHECK(HasEnoughData(frames));

  int remaining_frames = frames;

  // Step (1) -- Prime the input buffer at the start of the input stream.
  if (!buffer_primed_) {
    Read(r0_, kBlockSize + kKernelSize / 2);
    buffer_primed_ = true;
  }

  // Step (2) -- Resample!
  while (remaining_frames) {
    while (virtual_source_idx_ < kBlockSize) {
      // |virtual_source_idx_| lies in between two kernel offsets so figure out
      // what they are.
      int source_idx = static_cast<int>(virtual_source_idx_);
      double subsample_remainder = virtual_source_idx_ - source_idx;

      double virtual_offset_idx = subsample_remainder * kKernelOffsetCount;
      int offset_idx = static_cast<int>(virtual_offset_idx);

      // We'll compute "convolutions" for the two kernels which straddle
      // |virtual_source_idx_|.
      float* k1 = kernel_storage_.get() + offset_idx * kKernelSize;
      float* k2 = k1 + kKernelSize;

      // Initialize input pointer based on quantized |virtual_source_idx_|.
      float* input_ptr = r1_ + source_idx * channel_count_;

      // Figure out how much to weight each kernel's "convolution".
      double kernel_interpolation_factor = virtual_offset_idx - offset_idx;
      for (int i = 0; i < channel_count_; ++i) {
        *destination++ =
            Convolve(input_ptr + i, k1, k2, kernel_interpolation_factor);
      }

      // Advance the virtual index.
      virtual_source_idx_ += io_sample_rate_ratio_;

      if (!--remaining_frames) {
        frames_resampled_ += frames;
        return;
      }
    }

    // Wrap back around to the start.
    virtual_source_idx_ -= kBlockSize;

    // Step (3) Copy r3_ to r1_ and r4_ to r2_.
    // This wraps the last input frames back to the start of the buffer.
    SbMemoryCopy(r1_, r3_, frame_size_in_bytes_ * (kKernelSize / 2));
    SbMemoryCopy(r2_, r4_, frame_size_in_bytes_ * (kKernelSize / 2));

    // Step (4)
    // Refresh the buffer with more input.
    Read(r5_, kBlockSize);
  }

  NOTREACHED();
}

void InterleavedSincResampler::Flush() {
  virtual_source_idx_ = 0;
  buffer_primed_ = false;
  SbMemorySet(input_buffer_.get(), 0, frame_size_in_bytes_ * kBufferSize);
  while (!pending_buffers_.empty()) {
    pending_buffers_.pop();
  }
  offset_in_frames_ = 0;
  frames_resampled_ = 0;
  frames_queued_ = 0;
}

bool InterleavedSincResampler::CanQueueBuffer() const {
  if (pending_buffers_.empty()) {
    return true;
  }
  if (pending_buffers_.back()->IsEndOfStream()) {
    return false;
  }
  return pending_buffers_.size() < kMaximumPendingBuffers;
}

bool InterleavedSincResampler::ReachedEOS() const {
  if (pending_buffers_.empty() || !pending_buffers_.back()->IsEndOfStream()) {
    return false;
  }
  return frames_resampled_ * io_sample_rate_ratio_ >= frames_queued_;
}

bool InterleavedSincResampler::HasEnoughData(int frames_to_resample) const {
  // Always return true if EOS is seen, as in this case we will just fill 0.
  if (!pending_buffers_.empty() && pending_buffers_.back()->IsEndOfStream()) {
    return true;
  }

  // We have to decrease frames_queued_ down as the Read()s are always done in
  // blocks of kBlockSize or kBufferSize. We have to ensure that there is buffer
  // for an extra Read().
  return (frames_resampled_ + frames_to_resample) * io_sample_rate_ratio_ <
         frames_queued_ - kBufferSize;
}

void InterleavedSincResampler::Read(float* destination, int frames) {
  while (frames > 0 && !pending_buffers_.empty()) {
    scoped_refptr<Buffer> buffer = pending_buffers_.front();
    if (buffer->IsEndOfStream()) {
      // Zero fill the buffer after EOS has reached.
      SbMemorySet(destination, 0, frame_size_in_bytes_ * frames);
      return;
    }
    // Copy the data over.
    int frames_in_buffer = buffer->GetNumFrames();
    int frames_to_copy = std::min(frames_in_buffer - offset_in_frames_, frames);
    const float* source = buffer->GetData();
    source += offset_in_frames_ * channel_count_;
    SbMemoryCopy(destination, source, frame_size_in_bytes_ * frames_to_copy);
    offset_in_frames_ += frames_to_copy;
    // Pop the first buffer if all its content has been read.
    if (offset_in_frames_ == frames_in_buffer) {
      offset_in_frames_ = 0;
      pending_buffers_.pop();
    }
    frames -= frames_to_copy;
    destination += frames_to_copy * channel_count_;
  }

  // Read should always be satisfied as otherwise Resample should return false
  // to the caller directly.
  DCHECK_EQ(frames, 0);
}

float InterleavedSincResampler::Convolve(const float* input_ptr,
                                         const float* k1, const float* k2,
                                         double kernel_interpolation_factor) {
  float sum1 = 0;
  float sum2 = 0;

  // Generate a single output sample.  Unrolling this loop hurt performance in
  // local testing.
  int n = kKernelSize;
  while (n--) {
    sum1 += *input_ptr * *k1++;
    sum2 += *input_ptr * *k2++;
    input_ptr += channel_count_;
  }

  // Linearly interpolate the two "convolutions".
  return (1.0 - kernel_interpolation_factor) * sum1 +
         kernel_interpolation_factor * sum2;
}

}  // namespace media
}  // namespace cobalt
