/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "common_audio/audio_converter.h"

#include <cstring>
#include <memory>
#include <utility>
#include <vector>

#include "common_audio/channel_buffer.h"
#include "common_audio/resampler/push_sinc_resampler.h"
#include "rtc_base/checks.h"
#include "rtc_base/numerics/safe_conversions.h"

using rtc::checked_cast;

namespace webrtc {

class CopyConverter : public AudioConverter {
 public:
  CopyConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
                size_t dst_frames)
      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
  ~CopyConverter() override {};

  void Convert(const float* const* src, size_t src_size, float* const* dst,
               size_t dst_capacity) override {
    CheckSizes(src_size, dst_capacity);
    if (src != dst) {
      for (size_t i = 0; i < src_channels(); ++i)
        std::memcpy(dst[i], src[i], dst_frames() * sizeof(*dst[i]));
    }
  }
};

class UpmixConverter : public AudioConverter {
 public:
  UpmixConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
                 size_t dst_frames)
      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
  ~UpmixConverter() override {};

  void Convert(const float* const* src, size_t src_size, float* const* dst,
               size_t dst_capacity) override {
    CheckSizes(src_size, dst_capacity);
    for (size_t i = 0; i < dst_frames(); ++i) {
      const float value = src[0][i];
      for (size_t j = 0; j < dst_channels(); ++j)
        dst[j][i] = value;
    }
  }
};

class DownmixConverter : public AudioConverter {
 public:
  DownmixConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
                   size_t dst_frames)
      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
  }
  ~DownmixConverter() override {};

  void Convert(const float* const* src, size_t src_size, float* const* dst,
               size_t dst_capacity) override {
    CheckSizes(src_size, dst_capacity);
    float* dst_mono = dst[0];
    for (size_t i = 0; i < src_frames(); ++i) {
      float sum = 0;
      for (size_t j = 0; j < src_channels(); ++j)
        sum += src[j][i];
      dst_mono[i] = sum / src_channels();
    }
  }
};

class ResampleConverter : public AudioConverter {
 public:
  ResampleConverter(size_t src_channels, size_t src_frames, size_t dst_channels,
                    size_t dst_frames)
      : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {
    resamplers_.reserve(src_channels);
    for (size_t i = 0; i < src_channels; ++i)
      resamplers_.push_back(std::unique_ptr<PushSincResampler>(
          new PushSincResampler(src_frames, dst_frames)));
  }
  ~ResampleConverter() override {};

  void Convert(const float* const* src, size_t src_size, float* const* dst,
               size_t dst_capacity) override {
    CheckSizes(src_size, dst_capacity);
    for (size_t i = 0; i < resamplers_.size(); ++i)
      resamplers_[i]->Resample(src[i], src_frames(), dst[i], dst_frames());
  }

 private:
  std::vector<std::unique_ptr<PushSincResampler>> resamplers_;
};

// Apply a vector of converters in serial, in the order given. At least two
// converters must be provided.
class CompositionConverter : public AudioConverter {
 public:
  explicit CompositionConverter(
    std::vector<std::unique_ptr<AudioConverter>> converters)
      : converters_(std::move(converters)) {
    RTC_CHECK_GE(converters_.size(), 2);
    // We need an intermediate buffer after every converter.
    for (auto it = converters_.begin(); it != converters_.end() - 1; ++it)
      buffers_.push_back(
          std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
              (*it)->dst_frames(), (*it)->dst_channels())));
  }
  ~CompositionConverter() override {};

  void Convert(const float* const* src, size_t src_size, float* const* dst,
               size_t dst_capacity) override {
    converters_.front()->Convert(src, src_size, buffers_.front()->channels(),
                                 buffers_.front()->size());
    for (size_t i = 2; i < converters_.size(); ++i) {
      auto& src_buffer = buffers_[i - 2];
      auto& dst_buffer = buffers_[i - 1];
      converters_[i]->Convert(src_buffer->channels(),
                              src_buffer->size(),
                              dst_buffer->channels(),
                              dst_buffer->size());
    }
    converters_.back()->Convert(buffers_.back()->channels(),
                                buffers_.back()->size(), dst, dst_capacity);
  }

 private:
  std::vector<std::unique_ptr<AudioConverter>> converters_;
  std::vector<std::unique_ptr<ChannelBuffer<float>>> buffers_;
};

std::unique_ptr<AudioConverter> AudioConverter::Create(size_t src_channels,
                                                       size_t src_frames,
                                                       size_t dst_channels,
                                                       size_t dst_frames) {
  std::unique_ptr<AudioConverter> sp;
  if (src_channels > dst_channels) {
    if (src_frames != dst_frames) {
      std::vector<std::unique_ptr<AudioConverter>> converters;
      converters.push_back(std::unique_ptr<AudioConverter>(new DownmixConverter(
          src_channels, src_frames, dst_channels, src_frames)));
      converters.push_back(
          std::unique_ptr<AudioConverter>(new ResampleConverter(
              dst_channels, src_frames, dst_channels, dst_frames)));
      sp.reset(new CompositionConverter(std::move(converters)));
    } else {
      sp.reset(new DownmixConverter(src_channels, src_frames, dst_channels,
                                    dst_frames));
    }
  } else if (src_channels < dst_channels) {
    if (src_frames != dst_frames) {
      std::vector<std::unique_ptr<AudioConverter>> converters;
      converters.push_back(
          std::unique_ptr<AudioConverter>(new ResampleConverter(
              src_channels, src_frames, src_channels, dst_frames)));
      converters.push_back(std::unique_ptr<AudioConverter>(new UpmixConverter(
          src_channels, dst_frames, dst_channels, dst_frames)));
      sp.reset(new CompositionConverter(std::move(converters)));
    } else {
      sp.reset(new UpmixConverter(src_channels, src_frames, dst_channels,
                                  dst_frames));
    }
  } else if (src_frames != dst_frames) {
    sp.reset(new ResampleConverter(src_channels, src_frames, dst_channels,
                                   dst_frames));
  } else {
    sp.reset(new CopyConverter(src_channels, src_frames, dst_channels,
                               dst_frames));
  }

  return sp;
}

// For CompositionConverter.
AudioConverter::AudioConverter()
    : src_channels_(0),
      src_frames_(0),
      dst_channels_(0),
      dst_frames_(0) {}

AudioConverter::AudioConverter(size_t src_channels, size_t src_frames,
                               size_t dst_channels, size_t dst_frames)
    : src_channels_(src_channels),
      src_frames_(src_frames),
      dst_channels_(dst_channels),
      dst_frames_(dst_frames) {
  RTC_CHECK(dst_channels == src_channels || dst_channels == 1 ||
            src_channels == 1);
}

void AudioConverter::CheckSizes(size_t src_size, size_t dst_capacity) const {
  RTC_CHECK_EQ(src_size, src_channels() * src_frames());
  RTC_CHECK_GE(dst_capacity, dst_channels() * dst_frames());
}

}  // namespace webrtc
