// 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 <limits>

#include "src/media/audio/audio_core/mixer/constants.h"
#include "src/media/audio/lib/processing/channel_strip.h"
#include "src/media/audio/lib/processing/filter.h"
#include "src/media/audio/lib/processing/position_manager.h"
#include "src/media/audio/lib/processing/sampler.h"

namespace media::audio::mixer {

using ::media_audio::ChannelStrip;
using ::media_audio::PositionManager;
using ::media_audio::SincFilter;

template <int32_t DestChanCount, typename SourceSampleType, int32_t SourceChanCount>
class SincSamplerImpl : public SincSampler {
 public:
  SincSamplerImpl(int32_t source_frame_rate, int32_t dest_frame_rate, Gain::Limits gain_limits)
      : SincSampler(
            // TODO(fxbug.dev/72561): Convert Mixer and the rest of audio_core to a filter_width
            // definition that includes [0] in its count (as SincFilter::Length does).
            SincFilter::Length(source_frame_rate, dest_frame_rate) - Fixed::FromRaw(1),
            // Sinc filters are symmetric (pos == neg, for coefficient values)
            SincFilter::Length(source_frame_rate, dest_frame_rate) - Fixed::FromRaw(1),
            gain_limits),
        frac_filter_length_(SincFilter::Length(source_frame_rate, dest_frame_rate).raw_value()),
        source_rate_(source_frame_rate),
        dest_rate_(dest_frame_rate),
        position_(SourceChanCount, DestChanCount, frac_filter_length_, frac_filter_length_),
        working_data_(DestChanCount, kDataCacheLength),
        // SincFilter holds one side of coefficients; we invert position to calc the negative side.
        filter_(source_rate_, dest_rate_, frac_filter_length_) {
    FX_CHECK(pos_filter_width() == neg_filter_width())
        << "SincSampler assumes a symmetric filter, pos_filter_width (" << ffl::String::DecRational
        << pos_filter_width() << ") != neg_filter_width (" << neg_filter_width() << ")";
    // SincFilter draws from range [ceil(frac_pos - neg_width), floor(frac_pos + pos_width)].
    // Including the center, SincFilter can require floor(neg_width + one + pos_width) samples.
    // Be careful: this is not (necessarily) the same as floor(neg_width) + one + floor(pos_width)
    const int64_t kCacheFramesNeeded =
        Floor(neg_filter_width().raw_value() + kFracFrame + pos_filter_width().raw_value());
    // We set our data cache length to the maximum filter width that might ever be needed.
    FX_CHECK(kDataCacheLength >= kCacheFramesNeeded)
        << "Data cache (len " << kDataCacheLength << ") must be at least " << kCacheFramesNeeded
        << " long to support SRC ratio " << source_frame_rate << "/" << dest_frame_rate;
  }

  void 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) override;

  // TODO(fxbug.dev/45074): This is for tests only and can be removed once filter creation is eager.
  virtual void EagerlyPrepare() override { filter_.EagerlyPrepare(); }

 private:
  // As an optimization, we work with raw fixed-point values internally, but we pass Fixed types
  // through our public interfaces (to MixStage etc.) for source position/filter width/step size.
  static constexpr int64_t kFracFrame = kOneFrame.raw_value();

  static constexpr int64_t Ceiling(int64_t frac_position) {
    return ((frac_position - 1) >> Fixed::Format::FractionalBits) + 1;
  }
  static constexpr int64_t Floor(int64_t frac_position) {
    return frac_position >> Fixed::Format::FractionalBits;
  }

  // Our ChannelStrip must fit even the widest filter, and Filter::ComputeSample requires
  // floor(neg_width + 1 + pos_width) samples at minimum (incl 1 full sample for the center).
  static constexpr int64_t kDataCacheLength =
      Floor(SincFilter::kMaxFracSideLength + kFracFrame + SincFilter::kMaxFracSideLength);

  static constexpr int64_t kDataCacheFracLength = kDataCacheLength << Fixed::Format::FractionalBits;

  template <media_audio::GainType GainType, bool DoAccumulate>
  inline void 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);

  static inline 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);

  const int64_t frac_filter_length_;
  const int32_t source_rate_;
  const int32_t dest_rate_;

  PositionManager position_;
  ChannelStrip working_data_;
  SincFilter filter_;
};

// Implementation
//
// static
template <int32_t DestChanCount, typename SourceSampleType, int32_t SourceChanCount>
inline void
SincSamplerImpl<DestChanCount, SourceSampleType, SourceChanCount>::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 (kMixerPositionTraceEvents) {
    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);
  }
  using SR = SourceReader<SourceSampleType, SourceChanCount, DestChanCount>;

  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) {
    auto current_source_ptr = source_ptr + (source_idx * SourceChanCount);

    // Do this one dest_chan at a time
    for (size_t dest_chan = 0; dest_chan < DestChanCount; ++dest_chan) {
      (*channel_strip)[dest_chan][next_cache_idx_to_fill] = SR::Read(current_source_ptr, dest_chan);
    }
  }
}

// If upper layers call with GainType MUTED, they must set DoAccumulate=TRUE. They guarantee new
// buffers are cleared before usage; we optimize accordingly.
template <int32_t DestChanCount, typename SourceSampleType, int32_t SourceChanCount>
template <media_audio::GainType GainType, bool DoAccumulate>
inline void SincSamplerImpl<DestChanCount, SourceSampleType, SourceChanCount>::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) {
  TRACE_DURATION("audio", "SincSamplerImpl::MixInternal", "source_rate", source_rate_, "dest_rate",
                 dest_rate_, "source_chans", SourceChanCount, "dest_chans", DestChanCount);

  static_assert(GainType != media_audio::GainType::kSilent || DoAccumulate == true,
                "Mixing muted streams without accumulation is explicitly unsupported");

  auto info = &bookkeeping();
  auto frac_source_offset = source_offset_ptr->raw_value();
  const auto frac_neg_width = neg_filter_width().raw_value();
  position_.SetSourceValues(source_void_ptr, source_frames, source_offset_ptr);
  position_.SetDestValues(dest_ptr, dest_frames, dest_offset_ptr);
  position_.SetRateValues(info->step_size.raw_value(), info->rate_modulo(), info->denominator(),
                          &info->source_pos_modulo);

  int64_t next_cache_idx_to_fill = 0;
  auto next_source_idx_to_copy = Ceiling(frac_source_offset - frac_neg_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_frames - next_source_idx_to_copy;
      if (frac_source_offset > 0) {
        working_data_.ShiftBy(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 (GainType != media_audio::GainType::kSilent) {
        PopulateFramesToChannelStrip(source_void_ptr, next_source_idx_to_copy, frames_needed,
                                     &working_data_, next_cache_idx_to_fill);
      }
    }
    return;
  }

  if constexpr (GainType != media_audio::GainType::kSilent) {
    Gain::AScale amplitude_scale;
    int64_t dest_ramp_start;  // only used when ramping
    if constexpr (GainType != media_audio::GainType::kRamping) {
      amplitude_scale = info->gain.GetGainScale();
    } else {
      dest_ramp_start = position_.dest_offset();
    }

    auto frac_source_offset_to_cache = Ceiling(frac_source_offset - frac_neg_width) * kFracFrame;
    auto frames_needed = std::min(source_frames - 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_void_ptr, next_source_idx_to_copy, frames_needed,
                                 &working_data_, next_cache_idx_to_fill);

    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 = Floor(frac_cache_offset);
      FX_CHECK(Ceiling(frac_cache_offset - frac_neg_width) >= 0)
          << Ceiling(frac_cache_offset - frac_neg_width) << " should be >= 0";
      if (kMixerPositionTraceEvents) {
        TRACE_DURATION("audio", "SincSampler::Mix chunk", "next_source_idx_to_copy",
                       next_source_idx_to_copy, "cache_center_idx", cache_center_idx);
      }

      while (position_.CanFrameBeMixed() &&
             frac_cache_offset + pos_filter_width().raw_value() < kDataCacheFracLength) {
        auto dest_frame = position_.CurrentDestFrame();
        if constexpr (GainType == media_audio::GainType::kRamping) {
          amplitude_scale = info->scale_arr[position_.dest_offset() - dest_ramp_start];
        }

        for (size_t dest_chan = 0; dest_chan < DestChanCount; ++dest_chan) {
          float sample = filter_.ComputeSample(frac_interp_fraction,
                                               &(working_data_[dest_chan][cache_center_idx]));
          media_audio::MixSample<GainType, DoAccumulate>(sample, &dest_frame[dest_chan],
                                                         amplitude_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 = Floor(frac_cache_offset);
      }

      // idx of the earliest cached frame we must retain == the amount by which we can left-shift
      auto num_frames_to_shift = Ceiling(frac_cache_offset - frac_neg_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 = Ceiling(frac_source_offset - frac_neg_width) * kFracFrame;
      frames_needed = std::min(source_frames - next_source_idx_to_copy,
                               kDataCacheLength - next_cache_idx_to_fill);

      PopulateFramesToChannelStrip(source_void_ptr, next_source_idx_to_copy, frames_needed,
                                   &working_data_, next_cache_idx_to_fill);
    }
  } else {
    auto num_source_frames_skipped = position_.AdvanceToEnd();
    working_data_.ShiftBy(num_source_frames_skipped);
  }

  position_.UpdateOffsets();
}

template <int32_t DestChanCount, typename SourceSampleType, int32_t SourceChanCount>
void SincSamplerImpl<DestChanCount, SourceSampleType, SourceChanCount>::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) {
  auto info = &bookkeeping();

  // CheckPositions expects a frac_pos_filter_length param that _includes_ [0], so we use
  // frac_filter_length_ instead of pos_filter_width().
  // TODO(fxbug.dev/72561): Convert Mixer class (and audio_core all-up) to define filter width as
  // including the center in its count (as PositionManager and Filter::Length do). Any distinction
  // between filter length/filter width would go away. We would use pos_filter_width() here.
  PositionManager::CheckPositions(dest_frames, dest_offset_ptr, source_frames,
                                  source_offset_ptr->raw_value(), frac_filter_length_,
                                  info->step_size.raw_value(), info->rate_modulo(),
                                  info->denominator(), info->source_pos_modulo);

  if (info->gain.IsUnity()) {
    return accumulate ? Mix<media_audio::GainType::kUnity, true>(dest_ptr, dest_frames,
                                                                 dest_offset_ptr, source_void_ptr,
                                                                 source_frames, source_offset_ptr)
                      : Mix<media_audio::GainType::kUnity, false>(dest_ptr, dest_frames,
                                                                  dest_offset_ptr, source_void_ptr,
                                                                  source_frames, source_offset_ptr);
  }

  if (info->gain.IsSilent()) {
    return Mix<media_audio::GainType::kSilent, true>(
        dest_ptr, dest_frames, dest_offset_ptr, source_void_ptr, source_frames, source_offset_ptr);
  }

  if (info->gain.IsRamping()) {
    const auto max_frames = Mixer::Bookkeeping::kScaleArrLen + *dest_offset_ptr;
    if (dest_frames > max_frames) {
      dest_frames = max_frames;
    }

    return accumulate ? Mix<media_audio::GainType::kRamping, true>(dest_ptr, dest_frames,
                                                                   dest_offset_ptr, source_void_ptr,
                                                                   source_frames, source_offset_ptr)
                      : Mix<media_audio::GainType::kRamping, false>(
                            dest_ptr, dest_frames, dest_offset_ptr, source_void_ptr, source_frames,
                            source_offset_ptr);
  }

  return accumulate ? Mix<media_audio::GainType::kNonUnity, true>(dest_ptr, dest_frames,
                                                                  dest_offset_ptr, source_void_ptr,
                                                                  source_frames, source_offset_ptr)
                    : Mix<media_audio::GainType::kNonUnity, false>(
                          dest_ptr, dest_frames, dest_offset_ptr, source_void_ptr, source_frames,
                          source_offset_ptr);
}

// Templates used to expand  the different combinations of possible SincSampler configurations.
template <int32_t DestChanCount, typename SourceSampleType, int32_t SourceChanCount>
static inline std::unique_ptr<Mixer> SelectSSM(const fuchsia::media::AudioStreamType& source_format,
                                               const fuchsia::media::AudioStreamType& dest_format,
                                               Gain::Limits gain_limits) {
  return std::make_unique<SincSamplerImpl<DestChanCount, SourceSampleType, SourceChanCount>>(
      source_format.frames_per_second, dest_format.frames_per_second, gain_limits);
}

template <int32_t DestChanCount, typename SourceSampleType>
static inline std::unique_ptr<Mixer> SelectSSM(const fuchsia::media::AudioStreamType& source_format,
                                               const fuchsia::media::AudioStreamType& dest_format,
                                               Gain::Limits gain_limits) {
  TRACE_DURATION("audio", "SelectSSM(dChan,sType)");

  switch (source_format.channels) {
    case 1:
      if constexpr (DestChanCount <= 4) {
        return SelectSSM<DestChanCount, SourceSampleType, 1>(source_format, dest_format,
                                                             gain_limits);
      }
      break;
    case 2:
      if constexpr (DestChanCount <= 4) {
        return SelectSSM<DestChanCount, SourceSampleType, 2>(source_format, dest_format,
                                                             gain_limits);
      }
      break;
    case 3:
      // Unlike other samplers, we handle 3:3 here since there is no NxN sinc sampler variant.
      if constexpr (DestChanCount <= 3) {
        return SelectSSM<DestChanCount, SourceSampleType, 3>(source_format, dest_format,
                                                             gain_limits);
      }
      break;
    case 4:
      // Unlike other samplers, we handle 4:4 here since there is no NxN sinc sampler variant.
      // Like other samplers, to mix 4-channel sources to Mono or Stereo destinations, we mix
      // (average) multiple source channels to each destination channel. Given a 4-channel source
      // (call it A|B|C|D), the Stereo output channel-mix would be [avg(A,C), avg(B,D)] and the Mono
      // output channel-mix would be [avg(A,B,C,D)].
      //
      // Audio formats do not include info needed to filter frequencies or 3D-locate channels.
      // TODO(fxbug.dev/13679): enable the mixer to rechannelize in a more sophisticated way.
      // TODO(fxbug.dev/13682): account for frequency range (e.g. "4-channel" stereo woofer+tweeter)
      if constexpr (DestChanCount <= 2 || DestChanCount == 4) {
        return SelectSSM<DestChanCount, SourceSampleType, 4>(source_format, dest_format,
                                                             gain_limits);
      }
      break;
    default:
      break;
  }
  FX_LOGS(WARNING) << "SincSampler does not support this channelization: " << source_format.channels
                   << " -> " << dest_format.channels;
  return nullptr;
}

template <int32_t DestChanCount>
static inline std::unique_ptr<Mixer> SelectSSM(const fuchsia::media::AudioStreamType& source_format,
                                               const fuchsia::media::AudioStreamType& dest_format,
                                               Gain::Limits gain_limits) {
  TRACE_DURATION("audio", "SelectSSM(dChan)");

  switch (source_format.sample_format) {
    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
      return SelectSSM<DestChanCount, uint8_t>(source_format, dest_format, gain_limits);
    case fuchsia::media::AudioSampleFormat::SIGNED_16:
      return SelectSSM<DestChanCount, int16_t>(source_format, dest_format, gain_limits);
    case fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32:
      return SelectSSM<DestChanCount, int32_t>(source_format, dest_format, gain_limits);
    case fuchsia::media::AudioSampleFormat::FLOAT:
      return SelectSSM<DestChanCount, float>(source_format, dest_format, gain_limits);
    default:
      FX_LOGS(WARNING) << "SincSampler does not support this sample_format: "
                       << static_cast<int64_t>(source_format.sample_format);
      return nullptr;
  }
}

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");

  if (source_format.channels > 4) {
    FX_LOGS(WARNING) << "SincSampler does not support this channelization: "
                     << source_format.channels << " -> " << dest_format.channels;
    return nullptr;
  }

  switch (dest_format.channels) {
    case 1:
      return SelectSSM<1>(source_format, dest_format, gain_limits);
    case 2:
      return SelectSSM<2>(source_format, dest_format, gain_limits);
    case 3:
      return SelectSSM<3>(source_format, dest_format, gain_limits);
    case 4:
      // For now, to mix Mono and Stereo sources to 4-channel destinations, we duplicate source
      // channels across multiple destinations (Stereo LR becomes LRLR, Mono M becomes MMMM).
      // Audio formats do not include info needed to filter frequencies or 3D-locate channels.
      // TODO(fxbug.dev/13679): enable the mixer to rechannelize in a more sophisticated way.
      // TODO(fxbug.dev/13682): account for frequency range (e.g. a "4-channel" stereo
      // woofer+tweeter).
      return SelectSSM<4>(source_format, dest_format, gain_limits);
    default:
      FX_LOGS(WARNING) << "SincSampler does not support this channelization: "
                       << source_format.channels << " -> " << dest_format.channels;
      return nullptr;
  }
}

}  // namespace media::audio::mixer
