// 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.
//
// AudioConverter implementation.  Uses MultiChannelSincResampler for resampling
// audio, ChannelMixer for channel mixing, and AudioPullFifo for buffering.
//
// Delay estimates are provided to InputCallbacks based on the frame delay
// information reported via the resampler and FIFO units.

#include "media/base/audio_converter.h"

#include <algorithm>
#include <memory>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_pull_fifo.h"
#include "media/base/channel_mixer.h"
#include "media/base/multi_channel_resampler.h"
#include "media/base/vector_math.h"

namespace media {

AudioConverter::AudioConverter(const AudioParameters& input_params,
                               const AudioParameters& output_params,
                               bool disable_fifo)
    : chunk_size_(input_params.frames_per_buffer()),
      downmix_early_(false),
      initial_frames_delayed_(0),
      resampler_frames_delayed_(0),
      io_sample_rate_ratio_(input_params.sample_rate() /
                            static_cast<double>(output_params.sample_rate())),
      input_channel_count_(input_params.channels()) {
  CHECK(input_params.IsValid());
  CHECK(output_params.IsValid());

  // Handle different input and output channel layouts.
  if (input_params.channel_layout() != output_params.channel_layout() ||
      input_params.channels() != output_params.channels()) {
    DVLOG(1) << "Remixing channel layout from " << input_params.channel_layout()
             << " to " << output_params.channel_layout() << "; from "
             << input_params.channels() << " channels to "
             << output_params.channels() << " channels.";
    channel_mixer_ =
        std::make_unique<ChannelMixer>(input_params, output_params);

    // Pare off data as early as we can for efficiency.
    downmix_early_ = input_params.channels() > output_params.channels();
  }

  // Only resample if necessary since it's expensive.
  if (input_params.sample_rate() != output_params.sample_rate()) {
    DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
             << output_params.sample_rate();
    const int request_size = disable_fifo ? SincResampler::kDefaultRequestSize :
        input_params.frames_per_buffer();
    resampler_ = std::make_unique<MultiChannelResampler>(
        downmix_early_ ? output_params.channels() : input_params.channels(),
        io_sample_rate_ratio_, request_size,
        base::BindRepeating(&AudioConverter::ProvideInput,
                            base::Unretained(this)));
  }

  // The resampler can be configured to work with a specific request size, so a
  // FIFO is not necessary when resampling.
  if (disable_fifo || resampler_)
    return;

  // Since the output device may want a different buffer size than the caller
  // asked for, we need to use a FIFO to ensure that both sides read in chunk
  // sizes they're configured for.
  if (input_params.frames_per_buffer() != output_params.frames_per_buffer()) {
    DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer()
             << " to " << output_params.frames_per_buffer();
    chunk_size_ = input_params.frames_per_buffer();
    audio_fifo_ = std::make_unique<AudioPullFifo>(
        downmix_early_ ? output_params.channels() : input_params.channels(),
        chunk_size_,
        base::BindRepeating(&AudioConverter::SourceCallback,
                            base::Unretained(this)));
  }
}

AudioConverter::~AudioConverter() = default;

void AudioConverter::AddInput(InputCallback* input) {
  DCHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) ==
         transform_inputs_.end());
  transform_inputs_.push_back(input);
}

void AudioConverter::RemoveInput(InputCallback* input) {
  DCHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) !=
         transform_inputs_.end());
  transform_inputs_.remove(input);

  if (transform_inputs_.empty())
    Reset();
}

void AudioConverter::Reset() {
  if (audio_fifo_)
    audio_fifo_->Clear();
  if (resampler_)
    resampler_->Flush();
}

int AudioConverter::ChunkSize() const {
  if (!resampler_)
    return chunk_size_;
  return resampler_->ChunkSize();
}

void AudioConverter::PrimeWithSilence() {
  if (resampler_) {
    resampler_->PrimeWithSilence();
  }
}

int AudioConverter::GetMaxInputFramesRequested(int output_frames_requested) {
  return resampler_
             ? resampler_->GetMaxInputFramesRequested(output_frames_requested)
             : output_frames_requested;
}

void AudioConverter::ConvertWithDelay(uint32_t initial_frames_delayed,
                                      AudioBus* dest) {
  initial_frames_delayed_ = initial_frames_delayed;

  if (transform_inputs_.empty()) {
    dest->Zero();
    return;
  }

  // Determine if channel mixing should be done and if it should be done before
  // or after resampling.  If it's possible to reduce the channel count prior to
  // resampling we can save a lot of processing time.  Vice versa, we don't want
  // to increase the channel count prior to resampling for the same reason.
  bool needs_mixing = channel_mixer_ && !downmix_early_;

  if (needs_mixing)
    CreateUnmixedAudioIfNecessary(dest->frames());

  AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest;
  DCHECK(temp_dest);

  // Figure out which method to call based on whether we're resampling and
  // rebuffering, just resampling, or just mixing.  We want to avoid any extra
  // steps when possible since we may be converting audio data in real time.
  if (!resampler_ && !audio_fifo_) {
    SourceCallback(0, temp_dest);
  } else {
    if (resampler_)
      resampler_->Resample(temp_dest->frames(), temp_dest);
    else
      ProvideInput(0, temp_dest);
  }

  // Finally upmix the channels if we didn't do so earlier.
  if (needs_mixing) {
    DCHECK_EQ(temp_dest->frames(), dest->frames());
    channel_mixer_->Transform(temp_dest, dest);
  }
}

void AudioConverter::Convert(AudioBus* dest) {
  TRACE_EVENT1("audio", "AudioConverter::Convert", "sample rate ratio",
               io_sample_rate_ratio_);
  ConvertWithDelay(0, dest);
}

void AudioConverter::SourceCallback(int fifo_frame_delay, AudioBus* dest) {
  TRACE_EVENT1("audio", "AudioConverter::SourceCallback", "fifo frame delay",
               fifo_frame_delay);
  const bool needs_downmix = channel_mixer_ && downmix_early_;

  if (!mixer_input_audio_bus_ ||
      mixer_input_audio_bus_->frames() != dest->frames()) {
    mixer_input_audio_bus_ =
        AudioBus::Create(input_channel_count_, dest->frames());
  }

  // If we're downmixing early we need a temporary AudioBus which matches
  // the the input channel count and input frame size since we're passing
  // |unmixed_audio_| directly to the |source_callback_|.
  if (needs_downmix)
    CreateUnmixedAudioIfNecessary(dest->frames());

  AudioBus* const temp_dest = needs_downmix ? unmixed_audio_.get() : dest;

  // Sanity check our inputs.
  DCHECK_EQ(temp_dest->frames(), mixer_input_audio_bus_->frames());
  DCHECK_EQ(temp_dest->channels(), mixer_input_audio_bus_->channels());

  // |total_frames_delayed| is reported to the *input* source in terms of the
  // *input* sample rate. |initial_frames_delayed_| is given in terms of the
  // output sample rate, so we scale by sample rate ratio (in/out).
  uint32_t total_frames_delayed =
      std::round(initial_frames_delayed_ * io_sample_rate_ratio_);
  if (resampler_) {
    // |resampler_frames_delayed_| tallies frames queued up inside the resampler
    // that are already converted to the output format. Scale by ratio to get
    // delay in terms of input sample rate.
    total_frames_delayed +=
        std::round(resampler_frames_delayed_ * io_sample_rate_ratio_);
  }
  if (audio_fifo_) {
    total_frames_delayed += fifo_frame_delay;
  }

  // If we only have a single input, avoid an extra copy.
  AudioBus* const provide_input_dest =
      transform_inputs_.size() == 1 ? temp_dest : mixer_input_audio_bus_.get();

  // Have each mixer render its data into an output buffer then mix the result.
  for (auto* input : transform_inputs_) {
    const float volume =
        input->ProvideInput(provide_input_dest, total_frames_delayed);
    // Optimize the most common single input, full volume case.
    if (input == transform_inputs_.front()) {
      if (volume == 1.0f) {
        if (temp_dest != provide_input_dest)
          provide_input_dest->CopyTo(temp_dest);
      } else if (volume > 0) {
        for (int i = 0; i < provide_input_dest->channels(); ++i) {
          vector_math::FMUL(
              provide_input_dest->channel(i), volume,
              provide_input_dest->frames(), temp_dest->channel(i));
        }
      } else {
        // Zero |temp_dest| otherwise, so we're mixing into a clean buffer.
        temp_dest->Zero();
      }

      continue;
    }

    // Volume adjust and mix each mixer input into |temp_dest| after rendering.
    if (volume > 0) {
      for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
        vector_math::FMAC(
            mixer_input_audio_bus_->channel(i), volume,
            mixer_input_audio_bus_->frames(), temp_dest->channel(i));
      }
    }
  }

  if (needs_downmix) {
    DCHECK_EQ(temp_dest->frames(), dest->frames());
    channel_mixer_->Transform(temp_dest, dest);
  }
}

void AudioConverter::ProvideInput(int resampler_frame_delay, AudioBus* dest) {
  TRACE_EVENT1("audio", "AudioConverter::ProvideInput", "resampler frame delay",
               resampler_frame_delay);
  resampler_frames_delayed_ = resampler_frame_delay;
  if (audio_fifo_)
    audio_fifo_->Consume(dest, dest->frames());
  else
    SourceCallback(0, dest);
}

void AudioConverter::CreateUnmixedAudioIfNecessary(int frames) {
  if (!unmixed_audio_ || unmixed_audio_->frames() != frames)
    unmixed_audio_ = AudioBus::Create(input_channel_count_, frames);
}

}  // namespace media
