// Copyright (c) 2012 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.

#include "media/base/multi_channel_resampler.h"

#include <algorithm>
#include <memory>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "media/base/audio_bus.h"

namespace media {

MultiChannelResampler::MultiChannelResampler(int channels,
                                             double io_sample_rate_ratio,
                                             size_t request_size,
                                             const ReadCB& read_cb)
    : read_cb_(read_cb),
      wrapped_resampler_audio_bus_(AudioBus::CreateWrapper(channels)),
      output_frames_ready_(0) {
  // Allocate each channel's resampler.
  resamplers_.reserve(channels);
  for (int i = 0; i < channels; ++i) {
    resamplers_.push_back(std::make_unique<SincResampler>(
        io_sample_rate_ratio, request_size,
        base::Bind(&MultiChannelResampler::ProvideInput, base::Unretained(this),
                   i)));
  }

  // Setup the wrapped AudioBus for channel data.
  wrapped_resampler_audio_bus_->set_frames(request_size);

  // Allocate storage for all channels except the first, which will use the
  // |destination| provided to ProvideInput() directly.
  if (channels > 1) {
    resampler_audio_bus_ = AudioBus::Create(channels - 1, request_size);
    for (int i = 0; i < resampler_audio_bus_->channels(); ++i) {
      wrapped_resampler_audio_bus_->SetChannelData(
          i + 1, resampler_audio_bus_->channel(i));
    }
  }
}

MultiChannelResampler::~MultiChannelResampler() = default;

void MultiChannelResampler::Resample(int frames, AudioBus* audio_bus) {
  DCHECK_EQ(static_cast<size_t>(audio_bus->channels()), resamplers_.size());

  // Optimize the single channel case to avoid the chunking process below.
  if (audio_bus->channels() == 1) {
    resamplers_[0]->Resample(frames, audio_bus->channel(0));
    return;
  }

  // We need to ensure that SincResampler only calls ProvideInput once for each
  // channel.  To ensure this, we chunk the number of requested frames into
  // SincResampler::ChunkSize() sized chunks.  SincResampler guarantees it will
  // only call ProvideInput() once when we resample this way.
  output_frames_ready_ = 0;
  while (output_frames_ready_ < frames) {
    int chunk_size = resamplers_[0]->ChunkSize();
    int frames_this_time = std::min(frames - output_frames_ready_, chunk_size);

    // Resample each channel.
    for (size_t i = 0; i < resamplers_.size(); ++i) {
      DCHECK_EQ(chunk_size, resamplers_[i]->ChunkSize());

      // Depending on the sample-rate scale factor, and the internal buffering
      // used in a SincResampler kernel, this call to Resample() will only
      // sometimes call ProvideInput().  However, if it calls ProvideInput() for
      // the first channel, then it will call it for the remaining channels,
      // since they all buffer in the same way and are processing the same
      // number of frames.
      resamplers_[i]->Resample(
          frames_this_time, audio_bus->channel(i) + output_frames_ready_);
    }

    output_frames_ready_ += frames_this_time;
  }
}

void MultiChannelResampler::ProvideInput(int channel,
                                         int frames,
                                         float* destination) {
  // Get the data from the multi-channel provider when the first channel asks
  // for it.  For subsequent channels, we can just dish out the channel data
  // from that (stored in |resampler_audio_bus_|).
  if (channel == 0) {
    wrapped_resampler_audio_bus_->SetChannelData(0, destination);
    read_cb_.Run(output_frames_ready_, wrapped_resampler_audio_bus_.get());
  } else {
    // All channels must ask for the same amount.  This should always be the
    // case, but let's just make sure.
    DCHECK_EQ(frames, wrapped_resampler_audio_bus_->frames());

    // Copy the channel data from what we received from |read_cb_|.
    memcpy(destination, wrapped_resampler_audio_bus_->channel(channel),
           sizeof(*wrapped_resampler_audio_bus_->channel(channel)) * frames);
  }
}

void MultiChannelResampler::Flush() {
  for (size_t i = 0; i < resamplers_.size(); ++i)
    resamplers_[i]->Flush();
}

void MultiChannelResampler::SetRatio(double io_sample_rate_ratio) {
  for (size_t i = 0; i < resamplers_.size(); ++i)
    resamplers_[i]->SetRatio(io_sample_rate_ratio);
}

int MultiChannelResampler::ChunkSize() const {
  DCHECK(!resamplers_.empty());
  return resamplers_[0]->ChunkSize();
}


double MultiChannelResampler::BufferedFrames() const {
  DCHECK(!resamplers_.empty());
  return resamplers_[0]->BufferedFrames();
}

void MultiChannelResampler::PrimeWithSilence() {
  DCHECK(!resamplers_.empty());
  for (size_t i = 0; i < resamplers_.size(); ++i)
    resamplers_[i]->PrimeWithSilence();
}

}  // namespace media
