// Copyright 2017 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.

#include "starboard/common/log.h"
#include "starboard/configuration.h"
#include "starboard/shared/starboard/player/filter/audio_resampler.h"
#include "starboard/shared/starboard/player/filter/interleaved_sinc_resampler.h"

namespace starboard {
namespace shared {
namespace starboard {
namespace player {
namespace filter {

namespace {

// CPU based simple AudioResampler implementation.  Note that it currently only
// supports resample audio between same storage type and same channels but with
// different sample types.
class AudioResamplerImpl : public AudioResampler {
 public:
  AudioResamplerImpl(SbMediaAudioSampleType source_sample_type,
                     SbMediaAudioFrameStorageType source_storage_type,
                     int source_sample_rate,
                     SbMediaAudioSampleType destination_sample_type,
                     SbMediaAudioFrameStorageType destination_storage_type,
                     int destination_sample_rate,
                     int channels)
      : source_sample_type_(source_sample_type),
        source_storage_type_(source_storage_type),
        destination_sample_type_(destination_sample_type),
        destination_storage_type_(destination_storage_type),
        interleaved_resampler_(static_cast<double>(source_sample_rate) /
                                   static_cast<double>(destination_sample_rate),
                               channels) {}

  scoped_refptr<DecodedAudio> Resample(
      scoped_refptr<DecodedAudio> buffer) override;

  scoped_refptr<DecodedAudio> WriteEndOfStream() override;

 private:
  InterleavedSincResampler interleaved_resampler_;

  SbMediaAudioSampleType source_sample_type_;
  SbMediaAudioFrameStorageType source_storage_type_;
  SbMediaAudioSampleType destination_sample_type_;
  SbMediaAudioFrameStorageType destination_storage_type_;

  size_t frames_to_resample_ = 0;
  size_t frames_resampled_ = 0;
};

}  // namespace

// static
scoped_ptr<AudioResampler> AudioResampler::Create(
    SbMediaAudioSampleType source_sample_type,
    SbMediaAudioFrameStorageType source_storage_type,
    int source_sample_rate,
    SbMediaAudioSampleType destination_sample_type,
    SbMediaAudioFrameStorageType destination_storage_type,
    int destination_sample_rate,
    int channels) {
  return scoped_ptr<AudioResampler>(new AudioResamplerImpl(
      source_sample_type, source_storage_type, source_sample_rate,
      destination_sample_type, destination_storage_type,
      destination_sample_rate, channels));
}

scoped_refptr<DecodedAudio> AudioResamplerImpl::WriteEndOfStream() {
  double sample_rate_ratio = interleaved_resampler_.GetSampleRateRatio();
  int out_num_of_frames =
      round(frames_to_resample_ / sample_rate_ratio) - frames_resampled_;
  if (out_num_of_frames > 0) {
    interleaved_resampler_.QueueBuffer(nullptr, 0);
    int channels = interleaved_resampler_.channels();
    int resampled_audio_size = out_num_of_frames * channels * sizeof(float);
    scoped_refptr<DecodedAudio> resampled_audio = new DecodedAudio(
        channels, kSbMediaAudioSampleTypeFloat32,
        kSbMediaAudioFrameStorageTypeInterleaved, 0, resampled_audio_size);

    float* dst = reinterpret_cast<float*>(resampled_audio->data());
    interleaved_resampler_.Resample(dst, out_num_of_frames);

    if (!resampled_audio->IsFormat(destination_sample_type_,
                                   destination_storage_type_)) {
      resampled_audio = resampled_audio->SwitchFormatTo(
          destination_sample_type_, destination_storage_type_);
    }
    return resampled_audio;
  }

  return new DecodedAudio;
}

scoped_refptr<DecodedAudio> AudioResamplerImpl::Resample(
    scoped_refptr<DecodedAudio> audio_data) {
  SB_DCHECK(audio_data->channels() == interleaved_resampler_.channels());

  // It does nothing if source sample type is float and source storage type is
  // interleaved.
  if (!audio_data->IsFormat(kSbMediaAudioSampleTypeFloat32,
                            kSbMediaAudioFrameStorageTypeInterleaved)) {
    audio_data =
        audio_data->SwitchFormatTo(kSbMediaAudioSampleTypeFloat32,
                                   kSbMediaAudioFrameStorageTypeInterleaved);
  }

  int num_of_frames = audio_data->frames();
  frames_to_resample_ += num_of_frames;
  int channels = audio_data->channels();
  int out_num_of_frames = static_cast<int>(
      ceil(num_of_frames / interleaved_resampler_.GetSampleRateRatio()));

  int resampled_audio_size = out_num_of_frames * channels * sizeof(float);

  scoped_refptr<DecodedAudio> resampled_audio = nullptr;

  float* samples = reinterpret_cast<float*>(audio_data->data());
  interleaved_resampler_.QueueBuffer(samples, num_of_frames);

  if (interleaved_resampler_.HasEnoughData(out_num_of_frames)) {
    resampled_audio =
        new DecodedAudio(channels, kSbMediaAudioSampleTypeFloat32,
                         kSbMediaAudioFrameStorageTypeInterleaved,
                         audio_data->timestamp(), resampled_audio_size);
    float* dst = reinterpret_cast<float*>(resampled_audio->data());
    interleaved_resampler_.Resample(dst, out_num_of_frames);
    frames_resampled_ += out_num_of_frames;

    if (!resampled_audio->IsFormat(destination_sample_type_,
                                   destination_storage_type_)) {
      resampled_audio = resampled_audio->SwitchFormatTo(
          destination_sample_type_, destination_storage_type_);
    }
  }

  return resampled_audio;
}

}  // namespace filter
}  // namespace player
}  // namespace starboard
}  // namespace shared
}  // namespace starboard
