/*=============================================================================
   Copyright (c) 2014-2024 Joel de Guzman. All rights reserved.
   Copyright (c) 2024 AshRa al-Baschir, Shr3D Industries. All rights reserved.

   Distributed under the MIT License [ https://opensource.org/licenses/MIT ]
=============================================================================*/

#ifndef HEXFIN_H
#define HEXFIN_H

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

struct hx_zero_crossing_info
{
  float crossing0;
  float crossing1;
  float peak;
  int leading_edge;
  int trailing_edge;
  float width;
};

struct hx_ring_buffer
{
  size_t capacity;
  size_t mask;
  size_t pos;
  struct hx_zero_crossing_info* data;
};

struct hx_bit_set
{
  size_t num_bits;
  size_t size;
  uint64_t* data;
};

struct hx_bitstream_acf
{
  size_t mid_array;
};

struct hx_peak_envelope_follower
{
  float release;
  float y;
};

struct hx_one_pole_lowpass
{
  float a;
  float y;
};

struct hx_compressor
{
  double threshold;
  float slope;
};

struct hx_median3
{
  float b;
  float c;
  float median;
};

struct hexfin_context
{
  float sample_rate;
  float lowest_frequency;
  float highest_frequency;

  float hysteresis;
  unsigned int window_size;
  struct hx_ring_buffer info;
  size_t min_period;
  int range;
  struct hx_bit_set bits;
  float weight;
  size_t mid_point;
  float period_diff_threshold;

  float frequency_current;
  float frequency;
  struct hx_median3 median;
  struct hx_median3 predicted_median;

  struct hx_peak_envelope_follower env;
  struct hx_one_pole_lowpass lp;
  struct hx_one_pole_lowpass lp2;

  struct hx_compressor comp;
  float clip_max;

  float onset_threshold;
  float release_threshold;
  float threshold;

  bool loudEnough;

  float prev;
  bool state;
  size_t num_edges;
  size_t frame;
  bool ready;
  float peak_update;
  float peak;
  size_t edge_mark;
  size_t predict_edge_mark;
  float predicted_period;

  float fundamental_period;
  float fundamental_periodicity;
  size_t frames_after_shift;

  float volume;
};

struct hexfin_context hexfin_create_context(float sample_rate, float lowest_possible_frequency, float highest_possible_frequency);
void hexfin_destroy_context(struct hexfin_context* ctx);

float hexfin_processBlock(struct hexfin_context* ctx, const float* inBlock, int blockSize, float sample_rate, float lowest_frequency, float highest_frequency);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

#endif // HEXFIN_H
