/*
 *  Copyright (c) 2012 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 "modules/audio_processing/gain_control_impl.h"

#include <cstdint>
#include <optional>

#include "api/audio/audio_processing.h"
#include "modules/audio_processing/agc/legacy/gain_control.h"
#include "modules/audio_processing/audio_buffer.h"
#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {

typedef void Handle;

namespace {
int16_t MapSetting(GainControl::Mode mode) {
  switch (mode) {
    case GainControl::kAdaptiveAnalog:
      return kAgcModeAdaptiveAnalog;
    case GainControl::kAdaptiveDigital:
      return kAgcModeAdaptiveDigital;
    case GainControl::kFixedDigital:
      return kAgcModeFixedDigital;
  }
  RTC_DCHECK_NOTREACHED();
  return -1;
}

// Applies the sub-frame `gains` to all the bands in `out` and clamps the output
// in the signed 16 bit range.
void ApplyDigitalGain(const int32_t gains[11],
                      size_t num_bands,
                      float* const* out) {
  constexpr float kScaling = 1.f / 65536.f;
  constexpr int kNumSubSections = 16;
  constexpr float kOneByNumSubSections = 1.f / kNumSubSections;

  float gains_scaled[11];
  for (int k = 0; k < 11; ++k) {
    gains_scaled[k] = gains[k] * kScaling;
  }

  for (size_t b = 0; b < num_bands; ++b) {
    float* out_band = out[b];
    for (int k = 0, sample = 0; k < 10; ++k) {
      const float delta =
          (gains_scaled[k + 1] - gains_scaled[k]) * kOneByNumSubSections;
      float gain = gains_scaled[k];
      for (int n = 0; n < kNumSubSections; ++n, ++sample) {
        RTC_DCHECK_EQ(k * kNumSubSections + n, sample);
        out_band[sample] *= gain;
        out_band[sample] =
            std::min(32767.f, std::max(-32768.f, out_band[sample]));
        gain += delta;
      }
    }
  }
}

}  // namespace

struct GainControlImpl::MonoAgcState {
  MonoAgcState() {
    state = WebRtcAgc_Create();
    RTC_CHECK(state);
  }

  ~MonoAgcState() {
    RTC_DCHECK(state);
    WebRtcAgc_Free(state);
  }

  MonoAgcState(const MonoAgcState&) = delete;
  MonoAgcState& operator=(const MonoAgcState&) = delete;
  int32_t gains[11];
  Handle* state;
};

int GainControlImpl::instance_counter_ = 0;

GainControlImpl::GainControlImpl()
    : data_dumper_(new ApmDataDumper(instance_counter_)),
      mode_(kAdaptiveAnalog),
      minimum_capture_level_(0),
      maximum_capture_level_(255),
      limiter_enabled_(true),
      target_level_dbfs_(3),
      compression_gain_db_(9),
      analog_capture_level_(0),
      was_analog_level_set_(false),
      stream_is_saturated_(false) {}

GainControlImpl::~GainControlImpl() = default;

void GainControlImpl::ProcessRenderAudio(
    rtc::ArrayView<const int16_t> packed_render_audio) {
  for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
    WebRtcAgc_AddFarend(mono_agcs_[ch]->state, packed_render_audio.data(),
                        packed_render_audio.size());
  }
}

void GainControlImpl::PackRenderAudioBuffer(
    const AudioBuffer& audio,
    std::vector<int16_t>* packed_buffer) {
  RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
  std::array<int16_t, AudioBuffer::kMaxSplitFrameLength>
      mixed_16_kHz_render_data;
  rtc::ArrayView<const int16_t> mixed_16_kHz_render(
      mixed_16_kHz_render_data.data(), audio.num_frames_per_band());
  if (audio.num_channels() == 1) {
    FloatS16ToS16(audio.split_bands_const(0)[kBand0To8kHz],
                  audio.num_frames_per_band(), mixed_16_kHz_render_data.data());
  } else {
    const int num_channels = static_cast<int>(audio.num_channels());
    for (size_t i = 0; i < audio.num_frames_per_band(); ++i) {
      int32_t sum = 0;
      for (int ch = 0; ch < num_channels; ++ch) {
        sum += FloatS16ToS16(audio.split_channels_const(kBand0To8kHz)[ch][i]);
      }
      mixed_16_kHz_render_data[i] = sum / num_channels;
    }
  }

  packed_buffer->clear();
  packed_buffer->insert(
      packed_buffer->end(), mixed_16_kHz_render.data(),
      (mixed_16_kHz_render.data() + audio.num_frames_per_band()));
}

int GainControlImpl::AnalyzeCaptureAudio(const AudioBuffer& audio) {
  RTC_DCHECK(num_proc_channels_);
  RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
  RTC_DCHECK_EQ(audio.num_channels(), *num_proc_channels_);
  RTC_DCHECK_LE(*num_proc_channels_, mono_agcs_.size());

  int16_t split_band_data[AudioBuffer::kMaxNumBands]
                         [AudioBuffer::kMaxSplitFrameLength];
  int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
      split_band_data[0], split_band_data[1], split_band_data[2]};

  if (mode_ == kAdaptiveAnalog) {
    for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
      capture_levels_[ch] = analog_capture_level_;

      audio.ExportSplitChannelData(ch, split_bands);

      int err =
          WebRtcAgc_AddMic(mono_agcs_[ch]->state, split_bands,
                           audio.num_bands(), audio.num_frames_per_band());

      if (err != AudioProcessing::kNoError) {
        return AudioProcessing::kUnspecifiedError;
      }
    }
  } else if (mode_ == kAdaptiveDigital) {
    for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
      int32_t capture_level_out = 0;

      audio.ExportSplitChannelData(ch, split_bands);

      int err =
          WebRtcAgc_VirtualMic(mono_agcs_[ch]->state, split_bands,
                               audio.num_bands(), audio.num_frames_per_band(),
                               analog_capture_level_, &capture_level_out);

      capture_levels_[ch] = capture_level_out;

      if (err != AudioProcessing::kNoError) {
        return AudioProcessing::kUnspecifiedError;
      }
    }
  }

  return AudioProcessing::kNoError;
}

int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
                                         bool stream_has_echo) {
  if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
    return AudioProcessing::kStreamParameterNotSetError;
  }

  RTC_DCHECK(num_proc_channels_);
  RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
                audio->num_frames_per_band());
  RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);

  stream_is_saturated_ = false;
  bool error_reported = false;
  for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
    int16_t split_band_data[AudioBuffer::kMaxNumBands]
                           [AudioBuffer::kMaxSplitFrameLength];
    int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
        split_band_data[0], split_band_data[1], split_band_data[2]};
    audio->ExportSplitChannelData(ch, split_bands);

    // The call to stream_has_echo() is ok from a deadlock perspective
    // as the capture lock is allready held.
    int32_t new_capture_level = 0;
    uint8_t saturation_warning = 0;
    int err_analyze = WebRtcAgc_Analyze(
        mono_agcs_[ch]->state, split_bands, audio->num_bands(),
        audio->num_frames_per_band(), capture_levels_[ch], &new_capture_level,
        stream_has_echo, &saturation_warning, mono_agcs_[ch]->gains);
    capture_levels_[ch] = new_capture_level;

    error_reported = error_reported || err_analyze != AudioProcessing::kNoError;

    stream_is_saturated_ = stream_is_saturated_ || saturation_warning == 1;
  }

  // Choose the minimun gain for application
  size_t index_to_apply = 0;
  for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
    if (mono_agcs_[index_to_apply]->gains[10] < mono_agcs_[ch]->gains[10]) {
      index_to_apply = ch;
    }
  }

  for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
    ApplyDigitalGain(mono_agcs_[index_to_apply]->gains, audio->num_bands(),
                     audio->split_bands(ch));
  }

  RTC_DCHECK_LT(0ul, *num_proc_channels_);
  if (mode_ == kAdaptiveAnalog) {
    // Take the analog level to be the minimum accross all channels.
    analog_capture_level_ = capture_levels_[0];
    for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
      analog_capture_level_ =
          std::min(analog_capture_level_, capture_levels_[ch]);
    }
  }

  if (error_reported) {
    return AudioProcessing::kUnspecifiedError;
  }

  was_analog_level_set_ = false;

  return AudioProcessing::kNoError;
}

// TODO(ajm): ensure this is called under kAdaptiveAnalog.
int GainControlImpl::set_stream_analog_level(int level) {
  data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);

  was_analog_level_set_ = true;
  if (level < minimum_capture_level_ || level > maximum_capture_level_) {
    return AudioProcessing::kBadParameterError;
  }
  analog_capture_level_ = level;

  return AudioProcessing::kNoError;
}

int GainControlImpl::stream_analog_level() const {
  data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
                        &analog_capture_level_);
  return analog_capture_level_;
}

int GainControlImpl::set_mode(Mode mode) {
  if (MapSetting(mode) == -1) {
    return AudioProcessing::kBadParameterError;
  }

  mode_ = mode;
  RTC_DCHECK(num_proc_channels_);
  RTC_DCHECK(sample_rate_hz_);
  Initialize(*num_proc_channels_, *sample_rate_hz_);
  return AudioProcessing::kNoError;
}

int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
  if (minimum < 0 || maximum > 65535 || maximum < minimum) {
    return AudioProcessing::kBadParameterError;
  }

  minimum_capture_level_ = minimum;
  maximum_capture_level_ = maximum;

  RTC_DCHECK(num_proc_channels_);
  RTC_DCHECK(sample_rate_hz_);
  Initialize(*num_proc_channels_, *sample_rate_hz_);
  return AudioProcessing::kNoError;
}

int GainControlImpl::set_target_level_dbfs(int level) {
  if (level > 31 || level < 0) {
    return AudioProcessing::kBadParameterError;
  }
  target_level_dbfs_ = level;
  return Configure();
}

int GainControlImpl::set_compression_gain_db(int gain) {
  if (gain < 0 || gain > 90) {
    RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << gain << ") failed.";
    return AudioProcessing::kBadParameterError;
  }
  compression_gain_db_ = gain;
  return Configure();
}

int GainControlImpl::enable_limiter(bool enable) {
  limiter_enabled_ = enable;
  return Configure();
}

void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
  data_dumper_->InitiateNewSetOfRecordings();

  RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000 ||
             sample_rate_hz == 48000);

  num_proc_channels_ = num_proc_channels;
  sample_rate_hz_ = sample_rate_hz;

  mono_agcs_.resize(*num_proc_channels_);
  capture_levels_.resize(*num_proc_channels_);
  for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
    if (!mono_agcs_[ch]) {
      mono_agcs_[ch].reset(new MonoAgcState());
    }

    int error = WebRtcAgc_Init(mono_agcs_[ch]->state, minimum_capture_level_,
                               maximum_capture_level_, MapSetting(mode_),
                               *sample_rate_hz_);
    RTC_DCHECK_EQ(error, 0);
    capture_levels_[ch] = analog_capture_level_;
  }

  Configure();
}

int GainControlImpl::Configure() {
  WebRtcAgcConfig config;
  // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
  //            change the interface.
  // RTC_DCHECK_LE(target_level_dbfs_, 0);
  // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
  config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
  config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
  config.limiterEnable = limiter_enabled_;

  int error = AudioProcessing::kNoError;
  for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
    int error_ch = WebRtcAgc_set_config(mono_agcs_[ch]->state, config);
    if (error_ch != AudioProcessing::kNoError) {
      error = error_ch;
    }
  }
  return error;
}
}  // namespace webrtc
