/*
 *  Copyright (c) 2022 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 <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "api/audio/audio_processing.h"
#include "api/audio/builtin_audio_processing_builder.h"
#include "api/environment/environment_factory.h"
#include "api/scoped_refptr.h"
#include "rtc_base/checks.h"
#include "test/fuzzers/fuzz_data_helper.h"

namespace webrtc {
namespace {
constexpr int kMaxNumChannels = 2;
// APM supported max rate is 384000 Hz, using a limit slightly above lets the
// fuzzer exercise the handling of too high rates.
constexpr int kMaxSampleRateHz = 400000;
constexpr int kMaxSamplesPerChannel = kMaxSampleRateHz / 100;

void GenerateFloatFrame(FuzzDataHelper& fuzz_data,
                        int input_rate,
                        int num_channels,
                        float* const* float_frames) {
  const int samples_per_input_channel =
      AudioProcessing::GetFrameSize(input_rate);
  RTC_DCHECK_LE(samples_per_input_channel, kMaxSamplesPerChannel);
  for (int i = 0; i < num_channels; ++i) {
    float channel_value = fuzz_data.Read<float>();
    std::fill(float_frames[i], float_frames[i] + samples_per_input_channel,
              channel_value);
  }
}

void GenerateFixedFrame(FuzzDataHelper& fuzz_data,
                        int input_rate,
                        int num_channels,
                        int16_t* fixed_frames) {
  const int samples_per_input_channel =
      AudioProcessing::GetFrameSize(input_rate);
  RTC_DCHECK_LE(samples_per_input_channel, kMaxSamplesPerChannel);
  // Write interleaved samples.
  for (int ch = 0; ch < num_channels; ++ch) {
    const int16_t channel_value = fuzz_data.ReadOrDefaultValue<int16_t>(0);
    for (int i = ch; i < samples_per_input_channel * num_channels;
         i += num_channels) {
      fixed_frames[i] = channel_value;
    }
  }
}

// No-op processor used to influence APM input/output pipeline decisions based
// on what submodules are present.
class NoopCustomProcessing : public CustomProcessing {
 public:
  NoopCustomProcessing() {}
  ~NoopCustomProcessing() override {}
  void Initialize(int sample_rate_hz, int num_channels) override {}
  void Process(AudioBuffer* audio) override {}
  std::string ToString() const override { return ""; }
  void SetRuntimeSetting(AudioProcessing::RuntimeSetting setting) override {}
};
}  // namespace

// This fuzzer is directed at fuzzing unexpected input and output sample rates
// of APM. For example, the sample rate 22050 Hz is processed by APM in frames
// of floor(22050/100) = 220 samples. This is not exactly 10 ms of audio
// content, and may break assumptions commonly made on the APM frame size.
void FuzzOneInput(FuzzDataHelper fuzz_data) {
  if (fuzz_data.size() > 100) {
    return;
  }

  std::unique_ptr<CustomProcessing> capture_processor =
      fuzz_data.ReadOrDefaultValue(true)
          ? std::make_unique<NoopCustomProcessing>()
          : nullptr;
  std::unique_ptr<CustomProcessing> render_processor =
      fuzz_data.ReadOrDefaultValue(true)
          ? std::make_unique<NoopCustomProcessing>()
          : nullptr;
  scoped_refptr<AudioProcessing> apm =
      BuiltinAudioProcessingBuilder()
          .SetConfig({.pipeline = {.multi_channel_render = true,
                                   .multi_channel_capture = true}})
          .SetCapturePostProcessing(std::move(capture_processor))
          .SetRenderPreProcessing(std::move(render_processor))
          .Build(CreateEnvironment());
  RTC_DCHECK(apm);

  std::array<int16_t, kMaxSamplesPerChannel * kMaxNumChannels> fixed_frame;
  std::array<std::array<float, kMaxSamplesPerChannel>, kMaxNumChannels>
      float_frames;
  std::array<float*, kMaxNumChannels> float_frame_ptrs;
  for (int i = 0; i < kMaxNumChannels; ++i) {
    float_frame_ptrs[i] = float_frames[i].data();
  }
  float* const* ptr_to_float_frames = &float_frame_ptrs[0];

  // Choose whether to fuzz the float or int16_t interfaces of APM.
  const bool is_float = fuzz_data.ReadOrDefaultValue(true);

  // We may run out of fuzz data in the middle of a loop iteration. In
  // that case, default values will be used for the rest of that
  // iteration.
  while (fuzz_data.CanReadBytes(1)) {
    // Decide input/output rate for this iteration.
    const int input_rate = static_cast<int>(
        fuzz_data.ReadOrDefaultValue<size_t>(8000) % kMaxSampleRateHz);
    const int output_rate = static_cast<int>(
        fuzz_data.ReadOrDefaultValue<size_t>(8000) % kMaxSampleRateHz);
    const int num_channels = fuzz_data.ReadOrDefaultValue(true) ? 2 : 1;

    // Since render and capture calls have slightly different reinitialization
    // procedures, we let the fuzzer choose the order.
    const bool is_capture = fuzz_data.ReadOrDefaultValue(true);

    int apm_return_code = AudioProcessing::Error::kNoError;
    if (is_float) {
      GenerateFloatFrame(fuzz_data, input_rate, num_channels,
                         ptr_to_float_frames);

      if (is_capture) {
        apm_return_code = apm->ProcessStream(
            ptr_to_float_frames, StreamConfig(input_rate, num_channels),
            StreamConfig(output_rate, num_channels), ptr_to_float_frames);
      } else {
        apm_return_code = apm->ProcessReverseStream(
            ptr_to_float_frames, StreamConfig(input_rate, num_channels),
            StreamConfig(output_rate, num_channels), ptr_to_float_frames);
      }
    } else {
      GenerateFixedFrame(fuzz_data, input_rate, num_channels,
                         fixed_frame.data());

      if (is_capture) {
        apm_return_code = apm->ProcessStream(
            fixed_frame.data(), StreamConfig(input_rate, num_channels),
            StreamConfig(output_rate, num_channels), fixed_frame.data());
      } else {
        apm_return_code = apm->ProcessReverseStream(
            fixed_frame.data(), StreamConfig(input_rate, num_channels),
            StreamConfig(output_rate, num_channels), fixed_frame.data());
      }
    }
    // APM may flag an error on unsupported audio formats, but should not crash.
    RTC_DCHECK(apm_return_code == AudioProcessing::kNoError ||
               apm_return_code == AudioProcessing::kBadSampleRateError);
  }
}

}  // namespace webrtc
