// Copyright 2018 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 <lib/media/audio/effects/audio_effects.h>

#include <cmath>

#include <fbl/algorithm.h>

#include "src/media/audio/examples/effects/delay_effect.h"
#include "src/media/audio/examples/effects/effect_base.h"
#include "src/media/audio/examples/effects/rechannel_effect.h"
#include "src/media/audio/examples/effects/swap_effect.h"

namespace {

// Returns information about this type of effect
bool example_audio_effects_get_info(uint32_t effect_id, fuchsia_audio_effects_description* desc) {
  if (desc == nullptr) {
    return false;
  }

  return media::audio_effects_example::EffectBase::GetInfo(effect_id, desc);
}

// Returns a fuchsia_audio_effects_handle_t representing active instance of ‘effect_id’ (0 if
// fail). If channels_in==out, effect must process in-place.
fuchsia_audio_effects_handle_t example_audio_effects_create(uint32_t effect_id, uint32_t frame_rate,
                                                            uint16_t channels_in,
                                                            uint16_t channels_out,
                                                            const char* config,
                                                            size_t config_length) {
  media::audio_effects_example::EffectBase* effect =
      media::audio_effects_example::EffectBase::Create(effect_id, frame_rate, channels_in,
                                                       channels_out, {config, config_length});
  if (effect == nullptr) {
    return FUCHSIA_AUDIO_EFFECTS_INVALID_HANDLE;
  }

  return effect;
}

bool example_audio_effects_update_configuration(fuchsia_audio_effects_handle_t effects_handle,
                                                const char* config, size_t config_length) {
  if (effects_handle == FUCHSIA_AUDIO_EFFECTS_INVALID_HANDLE) {
    return false;
  }

  auto effect = reinterpret_cast<media::audio_effects_example::EffectBase*>(effects_handle);
  return effect->UpdateConfiguration({config, config_length});
}

// Deletes this active effect.
bool example_audio_effects_delete(fuchsia_audio_effects_handle_t effects_handle) {
  if (effects_handle == FUCHSIA_AUDIO_EFFECTS_INVALID_HANDLE) {
    return false;
  }

  auto effect = reinterpret_cast<media::audio_effects_example::EffectBase*>(effects_handle);
  delete effect;

  return true;
}

// Returns various parameters for active effect, including the channelization,
// the number of frames of group delay, and optionally the ideal number of
// frames that the system provides the effect for each call
bool example_audio_effects_get_parameters(fuchsia_audio_effects_handle_t effects_handle,
                                          fuchsia_audio_effects_parameters* effects_params) {
  if (effects_handle == FUCHSIA_AUDIO_EFFECTS_INVALID_HANDLE || effects_params == nullptr) {
    return false;
  }

  auto effect = reinterpret_cast<media::audio_effects_example::EffectBase*>(effects_handle);
  return effect->GetParameters(effects_params);
}

// Synchronously processes the buffer of ‘num_frames’ audio data, in-place
bool example_audio_effects_process_inplace(fuchsia_audio_effects_handle_t effects_handle,
                                           uint32_t num_frames, float* audio_buff_in_out) {
  if (effects_handle == FUCHSIA_AUDIO_EFFECTS_INVALID_HANDLE || audio_buff_in_out == nullptr) {
    return false;
  }
  if (num_frames == 0) {
    return true;
  }

  auto effect = reinterpret_cast<media::audio_effects_example::EffectBase*>(effects_handle);
  return effect->ProcessInplace(num_frames, audio_buff_in_out);
}

// Synchronously processes ‘num_frames’ from audio_buff_in to audio_buff_out.
bool example_audio_effects_process(fuchsia_audio_effects_handle_t effects_handle,
                                   uint32_t num_frames, const float* audio_buff_in,
                                   float** audio_buff_out) {
  if (effects_handle == FUCHSIA_AUDIO_EFFECTS_INVALID_HANDLE || audio_buff_in == nullptr ||
      audio_buff_out == nullptr) {
    return false;
  }
  if (num_frames == 0) {
    return true;
  }

  auto effect = reinterpret_cast<media::audio_effects_example::EffectBase*>(effects_handle);
  return effect->Process(num_frames, audio_buff_in, audio_buff_out);
}

// Flushes any cached state, but retains settings, on this active effect.
bool example_audio_effects_flush(fuchsia_audio_effects_handle_t effects_handle) {
  if (effects_handle == FUCHSIA_AUDIO_EFFECTS_INVALID_HANDLE) {
    return false;
  }

  auto effect = reinterpret_cast<media::audio_effects_example::EffectBase*>(effects_handle);
  return effect->Flush();
}

void example_audio_effects_set_stream_info(fuchsia_audio_effects_handle_t effects_handle,
                                           const fuchsia_audio_effects_stream_info* stream_info) {}
}  // namespace

DECLARE_FUCHSIA_AUDIO_EFFECTS_MODULE_V1{
    media::audio_effects_example::Effect::Count,
    &example_audio_effects_get_info,
    &example_audio_effects_create,
    &example_audio_effects_update_configuration,
    &example_audio_effects_delete,
    &example_audio_effects_get_parameters,
    &example_audio_effects_process_inplace,
    &example_audio_effects_process,
    &example_audio_effects_flush,
    &example_audio_effects_set_stream_info,
};
