// Copyright 2019 The Fuchsia 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 "src/media/audio/audio_core/mixer/sinc_sampler.h"

#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>

#include <algorithm>
#include <memory>

#include "fidl/fuchsia.mediastreams/cpp/wire_types.h"
#include "src/media/audio/lib/processing/position_manager.h"
#include "src/media/audio/lib/processing/sampler.h"
#include "src/media/audio/lib/processing/sinc_sampler.h"

namespace media::audio::mixer {

namespace {

using ::media_audio::PositionManager;
using ::media_audio::Sampler;

fuchsia_mediastreams::wire::AudioSampleFormat ToNewSampleFormat(
    fuchsia::media::AudioSampleFormat sample_format) {
  switch (sample_format) {
    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
      return fuchsia_mediastreams::wire::AudioSampleFormat::kUnsigned8;
    case fuchsia::media::AudioSampleFormat::SIGNED_16:
      return fuchsia_mediastreams::wire::AudioSampleFormat::kSigned16;
    case fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32:
      return fuchsia_mediastreams::wire::AudioSampleFormat::kSigned24In32;
    case fuchsia::media::AudioSampleFormat::FLOAT:
    default:
      return fuchsia_mediastreams::wire::AudioSampleFormat::kFloat;
  }
}

media_audio::Format ToNewFormat(const fuchsia::media::AudioStreamType& format) {
  return media_audio::Format::CreateOrDie(
      {ToNewSampleFormat(format.sample_format), format.channels, format.frames_per_second});
}

}  // namespace

std::unique_ptr<Mixer> SincSampler::Select(const fuchsia::media::AudioStreamType& source_format,
                                           const fuchsia::media::AudioStreamType& dest_format,
                                           Gain::Limits gain_limits) {
  TRACE_DURATION("audio", "SincSampler::Select");

  auto sinc_sampler =
      media_audio::SincSampler::Create(ToNewFormat(source_format), ToNewFormat(dest_format));
  if (!sinc_sampler) {
    return nullptr;
  }

  struct MakePublicCtor : SincSampler {
    MakePublicCtor(Gain::Limits gain_limits, std::shared_ptr<Sampler> sinc_sampler)
        : SincSampler(gain_limits, std::move(sinc_sampler)) {}
  };
  return std::make_unique<MakePublicCtor>(gain_limits, std::move(sinc_sampler));
}

void SincSampler::EagerlyPrepare() { sinc_sampler_->EagerlyPrepare(); }

void SincSampler::Mix(float* dest_ptr, int64_t dest_frames, int64_t* dest_offset_ptr,
                      const void* source_void_ptr, int64_t source_frames, Fixed* source_offset_ptr,
                      bool accumulate) {
  TRACE_DURATION("audio", "SincSampler::Mix");

  auto info = &bookkeeping();
  PositionManager::CheckPositions(
      dest_frames, dest_offset_ptr, source_frames, source_offset_ptr->raw_value(),
      sinc_sampler_->pos_filter_length().raw_value(), info->step_size.raw_value(),
      info->rate_modulo(), info->denominator(), info->source_pos_modulo);
  static_cast<media_audio::SincSampler*>(sinc_sampler_.get())
      ->SetRateValues(info->step_size.raw_value(), info->rate_modulo(), info->denominator(),
                      &info->source_pos_modulo);

  Sampler::Source source{source_void_ptr, source_offset_ptr, source_frames};
  Sampler::Dest dest{dest_ptr, dest_offset_ptr, dest_frames};
  if (info->gain.IsSilent()) {
    // If the gain is silent, the mixer simply skips over the appropriate range in the destination
    // buffer, leaving whatever data is already there. We do not take further effort to clear the
    // buffer if `accumulate` is false. In fact, we IGNORE `accumulate` if silent. The caller is
    // responsible for clearing the destination buffer before Mix is initially called.
    sinc_sampler_->Process(source, dest, Sampler::Gain{.type = media_audio::GainType::kSilent},
                           true);
  } else if (info->gain.IsUnity()) {
    sinc_sampler_->Process(source, dest, Sampler::Gain{.type = media_audio::GainType::kUnity},
                           accumulate);
  } else if (info->gain.IsRamping()) {
    sinc_sampler_->Process(
        source, dest,
        Sampler::Gain{.type = media_audio::GainType::kRamping, .scale_ramp = info->scale_arr.get()},
        accumulate);
  } else {
    sinc_sampler_->Process(
        source, dest,
        Sampler::Gain{.type = media_audio::GainType::kNonUnity, .scale = info->gain.GetGainScale()},
        accumulate);
  }
}

}  // namespace media::audio::mixer
