// Copyright 2022 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/lib/processing/sinc_sampler.h"

#include <lib/trace/event.h>

#include <algorithm>
#include <cstdint>
#include <memory>

#include <ffl/string.h>

#include "fidl/fuchsia.mediastreams/cpp/wire_types.h"
#include "lib/syslog/cpp/macros.h"
#include "src/media/audio/lib/format2/channel_mapper.h"
#include "src/media/audio/lib/format2/fixed.h"
#include "src/media/audio/lib/format2/format.h"
#include "src/media/audio/lib/processing/channel_strip.h"
#include "src/media/audio/lib/processing/filter.h"
#include "src/media/audio/lib/processing/gain.h"
#include "src/media/audio/lib/processing/position_manager.h"

namespace media_audio {

namespace {

template <typename SourceSampleType, size_t SourceChannelCount, size_t DestChannelCount>
class SincSamplerImpl : public SincSampler {
 public:
  SincSamplerImpl(int32_t source_frame_rate, int32_t dest_frame_rate)
      : SincSampler(SincFilter::Length(source_frame_rate, dest_frame_rate),
                    // Sinc filters are symmetric.
                    SincFilter::Length(source_frame_rate, dest_frame_rate)),
        source_frame_rate_(source_frame_rate),
        dest_frame_rate_(dest_frame_rate),
        position_(SourceChannelCount, DestChannelCount, pos_filter_length().raw_value(),
                  neg_filter_length().raw_value()),
        working_data_(DestChannelCount, kDataCacheLength),
        // `SincFilter` holds one side of coefficients (positive), we invert the position to
        // calculate the other side (negative).
        filter_(source_frame_rate_, dest_frame_rate_, pos_filter_length().raw_value()) {
    FX_CHECK(pos_filter_length() == neg_filter_length())
        << "SincSampler assumes a symmetric filter, pos_filter_length (" << ffl::String::DecRational
        << pos_filter_length() << ") != neg_filter_length (" << neg_filter_length() << ")";

    const int64_t cache_length_needed =
        Sampler::Floor(neg_filter_length().raw_value() + pos_filter_length().raw_value() - 1);
    FX_CHECK(kDataCacheLength >= cache_length_needed)
        << "Data cache (len " << kDataCacheLength << ") must be at least " << cache_length_needed
        << " long to support SRC ratio " << source_frame_rate << "/" << dest_frame_rate;
  }

  void EagerlyPrepare() final { filter_.EagerlyPrepare(); }

  void Process(Source source, Dest dest, Gain gain, bool accumulate) final {
    TRACE_DURATION("audio", "SincSamplerImpl::Process", "source_rate", source_frame_rate_,
                   "dest_rate", dest_frame_rate_, "source_chans", SourceChannelCount, "dest_chans",
                   DestChannelCount);

    position_.SetSourceValues(source.samples, source.frame_count, source.frame_offset_ptr);
    position_.SetDestValues(dest.samples, dest.frame_count, dest.frame_offset_ptr);

    switch (gain.type) {
      case GainType::kSilent:
        if (accumulate) {
          ProcessWith<GainType::kSilent, true>(source, dest, gain);
        } else {
          ProcessWith<GainType::kSilent, false>(source, dest, gain);
        }
        break;
      case GainType::kNonUnity:
        if (accumulate) {
          ProcessWith<GainType::kNonUnity, true>(source, dest, gain);
        } else {
          ProcessWith<GainType::kNonUnity, false>(source, dest, gain);
        }
        break;
      case GainType::kUnity:
        if (accumulate) {
          ProcessWith<GainType::kUnity, true>(source, dest, gain);
        } else {
          ProcessWith<GainType::kUnity, false>(source, dest, gain);
        }
        break;
      case GainType::kRamping:
        if (accumulate) {
          ProcessWith<GainType::kRamping, true>(source, dest, gain);
        } else {
          ProcessWith<GainType::kRamping, false>(source, dest, gain);
        }
        break;
      default:
        break;
    }
  }

  void SetRateValues(int64_t step_size, uint64_t rate_modulo, uint64_t denominator,
                     uint64_t* source_pos_mod) final {
    position_.SetRateValues(step_size, rate_modulo, denominator, source_pos_mod);
  }

 private:
  static void PopulateFramesToChannelStrip(const void* source_void_ptr,
                                           int64_t next_source_idx_to_copy,
                                           const int64_t frames_needed, ChannelStrip* channel_strip,
                                           int64_t next_cache_idx_to_fill) {
    if constexpr (kTracePositionEvents) {
      TRACE_DURATION("audio", __func__, "next_source_idx_to_copy", next_source_idx_to_copy,
                     "frames_needed", frames_needed, "next_cache_idx_to_fill",
                     next_cache_idx_to_fill);
    }

    const SourceSampleType* source_ptr = static_cast<const SourceSampleType*>(source_void_ptr);
    for (int64_t source_idx = next_source_idx_to_copy;
         source_idx < next_source_idx_to_copy + frames_needed;
         ++source_idx, ++next_cache_idx_to_fill) {
      const SourceSampleType* source_frame = &source_ptr[source_idx * SourceChannelCount];
      for (size_t dest_chan = 0; dest_chan < DestChannelCount; ++dest_chan) {
        (*channel_strip)[dest_chan][next_cache_idx_to_fill] = mapper_.Map(source_frame, dest_chan);
      }
    }
  }

  // Processes `source` into `dest` with gain `Type`.
  template <GainType Type, bool Accumulate>
  void ProcessWith(const Source& source, const Dest& dest, const Gain& gain) {
    int64_t frac_source_offset = source.frame_offset_ptr->raw_value();
    const auto frac_filter_width = pos_filter_length().raw_value() - 1;

    int64_t next_cache_idx_to_fill = 0;
    auto next_source_idx_to_copy = Sampler::Ceiling(frac_source_offset - frac_filter_width);

    // Do we need previously-cached values?
    if (next_source_idx_to_copy < 0) {
      next_cache_idx_to_fill = -next_source_idx_to_copy;
      next_source_idx_to_copy = 0;
    }

    // If we don't have enough source or dest to mix even one frame, get out. Before leaving, if
    // we've reached the end of the source buffer, then cache the last few source frames for the
    // next mix.
    if (!position_.CanFrameBeMixed()) {
      if (position_.IsSourceConsumed()) {
        const auto frames_needed = source.frame_count - next_source_idx_to_copy;
        if (frac_source_offset > 0) {
          working_data_.ShiftBy(Sampler::Ceiling(frac_source_offset));
        }

        // Calculate and store the last few source frames to start of channel_strip, for next time.
        // If muted, this is unnecessary because we've already shifted in zeroes (silence).
        if constexpr (Type != GainType::kSilent) {
          PopulateFramesToChannelStrip(source.samples, next_source_idx_to_copy, frames_needed,
                                       &working_data_, next_cache_idx_to_fill);
        }
      }
      return;
    }

    if constexpr (Type != media_audio::GainType::kSilent) {
      auto frac_source_offset_to_cache =
          Sampler::Ceiling(frac_source_offset - frac_filter_width) * kFracOneFrame;
      auto frames_needed = std::min(source.frame_count - next_source_idx_to_copy,
                                    kDataCacheLength - next_cache_idx_to_fill);

      // Bring in as much as a channel strip of source data (while channel/format-converting).
      PopulateFramesToChannelStrip(source.samples, next_source_idx_to_copy, frames_needed,
                                   &working_data_, next_cache_idx_to_fill);

      float scale = gain.scale;
      int64_t dest_ramp_start = position_.dest_offset();  // only used when ramping
      while (position_.CanFrameBeMixed()) {
        next_source_idx_to_copy += frames_needed;

        int64_t frac_cache_offset = frac_source_offset - frac_source_offset_to_cache;
        int64_t frac_interp_fraction = frac_cache_offset & Fixed::Format::FractionalMask;
        auto cache_center_idx = Sampler::Floor(frac_cache_offset);
        FX_CHECK(Sampler::Ceiling(frac_cache_offset - frac_filter_width) >= 0)
            << Sampler::Ceiling(frac_cache_offset - frac_filter_width) << " should be >= 0";
        if constexpr (kTracePositionEvents) {
          TRACE_DURATION("audio", "SincSampler::Process chunk", "next_source_idx_to_copy",
                         next_source_idx_to_copy, "cache_center_idx", cache_center_idx);
        }

        while (position_.CanFrameBeMixed() &&
               frac_cache_offset + frac_filter_width < kFracDataCacheLength) {
          float* dest_frame = position_.CurrentDestFrame();
          if constexpr (Type == media_audio::GainType::kRamping) {
            scale = gain.scale_ramp[position_.dest_offset() - dest_ramp_start];
          }

          for (size_t dest_chan = 0; dest_chan < DestChannelCount; ++dest_chan) {
            const float sample = filter_.ComputeSample(
                frac_interp_fraction, &(working_data_[dest_chan][cache_center_idx]));
            MixSample<Type, Accumulate>(sample, &dest_frame[dest_chan], scale);
          }

          frac_source_offset = position_.AdvanceFrame();

          frac_cache_offset = frac_source_offset - frac_source_offset_to_cache;
          frac_interp_fraction = frac_cache_offset & Fixed::Format::FractionalMask;
          cache_center_idx = Sampler::Floor(frac_cache_offset);
        }

        // idx of the earliest cached frame we must retain == the amount by which we can left-shift.
        const auto num_frames_to_shift = Sampler::Ceiling(frac_cache_offset - frac_filter_width);
        working_data_.ShiftBy(num_frames_to_shift);

        cache_center_idx -= num_frames_to_shift;
        next_cache_idx_to_fill = kDataCacheLength - num_frames_to_shift;

        frac_source_offset_to_cache =
            Sampler::Ceiling(frac_source_offset - frac_filter_width) * kFracOneFrame;
        frames_needed = std::min(source.frame_count - next_source_idx_to_copy,
                                 kDataCacheLength - next_cache_idx_to_fill);

        PopulateFramesToChannelStrip(source.samples, next_source_idx_to_copy, frames_needed,
                                     &working_data_, next_cache_idx_to_fill);
      }
    } else {
      if constexpr (!Accumulate) {
        // Zero fill destination frames.
        const int64_t dest_frame_offset = *dest.frame_offset_ptr;
        std::fill_n(&dest.samples[dest_frame_offset * DestChannelCount],
                    (dest.frame_count - dest_frame_offset) * DestChannelCount, 0.0f);
      }
      auto num_source_frames_skipped = position_.AdvanceToEnd();
      working_data_.ShiftBy(num_source_frames_skipped);
    }

    position_.UpdateOffsets();
  }

  // Our `ChannelStrip` must fit even the widest filter.
  static constexpr int64_t kDataCacheLength = Sampler::Floor(
      SincFilter::kMaxFracSideLength + kFracOneFrame + SincFilter::kMaxFracSideLength);
  static constexpr int64_t kFracDataCacheLength = kDataCacheLength << Fixed::Format::FractionalBits;

  static inline ChannelMapper<SourceSampleType, SourceChannelCount, DestChannelCount> mapper_;

  const int32_t source_frame_rate_;
  const int32_t dest_frame_rate_;

  PositionManager position_;
  ChannelStrip working_data_;
  SincFilter filter_;
};

// Helper functions to expand the combinations of possible `SincSamplerImpl` configurations.
template <typename SourceSampleType, size_t SourceChannelCount, size_t DestChannelCount>
std::shared_ptr<Sampler> CreateWith(const Format& source_format, const Format& dest_format) {
  return std::make_shared<SincSamplerImpl<SourceSampleType, SourceChannelCount, DestChannelCount>>(
      static_cast<int32_t>(source_format.frames_per_second()),
      static_cast<int32_t>(dest_format.frames_per_second()));
}

template <typename SourceSampleType, size_t SourceChannelCount>
std::shared_ptr<Sampler> CreateWith(const Format& source_format, const Format& dest_format) {
  switch (dest_format.channels()) {
    case 1:
      return CreateWith<SourceSampleType, SourceChannelCount, 1>(source_format, dest_format);
    case 2:
      return CreateWith<SourceSampleType, SourceChannelCount, 2>(source_format, dest_format);
    case 3:
      if constexpr (SourceChannelCount <= 3) {
        return CreateWith<SourceSampleType, SourceChannelCount, 3>(source_format, dest_format);
      }
      break;
    case 4:
      if constexpr (SourceChannelCount != 3) {
        return CreateWith<SourceSampleType, SourceChannelCount, 4>(source_format, dest_format);
      }
      break;
    default:
      break;
  }
  FX_LOGS(WARNING) << "SincSampler does not support this channelization: " << SourceChannelCount
                   << " -> " << dest_format.channels();
  return nullptr;
}

template <typename SourceSampleType>
std::shared_ptr<Sampler> CreateWith(const Format& source_format, const Format& dest_format) {
  switch (source_format.channels()) {
    case 1:
      return CreateWith<SourceSampleType, 1>(source_format, dest_format);
    case 2:
      return CreateWith<SourceSampleType, 2>(source_format, dest_format);
    case 3:
      return CreateWith<SourceSampleType, 3>(source_format, dest_format);
    case 4:
      return CreateWith<SourceSampleType, 4>(source_format, dest_format);
    default:
      FX_LOGS(WARNING) << "SincSampler does not support this channelization: "
                       << source_format.channels() << " -> " << dest_format.channels();
      return nullptr;
  }
}

}  // namespace

std::shared_ptr<Sampler> SincSampler::Create(const Format& source_format,
                                             const Format& dest_format) {
  TRACE_DURATION("audio", "SincSampler::Create");

  if (dest_format.sample_format() != fuchsia_mediastreams::wire::AudioSampleFormat::kFloat) {
    FX_LOGS(WARNING) << "SincSampler does not support this dest sample format: "
                     << static_cast<uint32_t>(dest_format.sample_format());
    return nullptr;
  }

  switch (source_format.sample_format()) {
    case fuchsia_mediastreams::wire::AudioSampleFormat::kUnsigned8:
      return CreateWith<uint8_t>(source_format, dest_format);
    case fuchsia_mediastreams::wire::AudioSampleFormat::kSigned16:
      return CreateWith<int16_t>(source_format, dest_format);
    case fuchsia_mediastreams::wire::AudioSampleFormat::kSigned24In32:
      return CreateWith<int32_t>(source_format, dest_format);
    case fuchsia_mediastreams::wire::AudioSampleFormat::kFloat:
      return CreateWith<float>(source_format, dest_format);
    default:
      FX_LOGS(WARNING) << "SincSampler does not support this source sample format: "
                       << static_cast<uint32_t>(source_format.sample_format());
      return nullptr;
  }
}

}  // namespace media_audio
