/*
* play.h
* DIN Is Noise is copyright (c) 2006-2024 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/


#ifndef PLAY
#define PLAY

#include "note.h"
#include "curve_mixer.h"

//
// renders a tone 
//

struct solver;

struct play : set_mixer {

  // pitch
  //
  solver* sol; // solver linked to waveform
  float x; // current x on the waveform; x usually goes from 0 to 1. 0 = waveform start, 1 = waveform end ie 1 cycle.
  float dx; // change of x every sample; determines how fast the waveform is sampled and hence frequency of the tone (equivalent to variable step in note.h)
  float* pdx; // array of dx [interpolated from last to present for smooth frequency change]

  // volume
  //
  float vol; // current volume
  float* pvol; // array of volumes [interpolated from last to present for smooth volume change]

  // for calculation of pdx and pvol
  //
  float da; // delta alpha
  int n; // buffer size
  int n_1; // n-1

	// for mixing waveforms
	curve_mixer mixer;
	void set_mix (multi_curve& crv, const std::string& nam);

  play (solver* s);
  play ();
  play (const play&);
  ~play ();
  void alloc ();
  void realloc ();

  void init ();

	inline void set_wave (solver* s) { sol = s;}
  inline void set_step (float xd) {dx = xd;}
  inline void set_volume (float v) {vol = v;}
  inline void set (float xd, float l, float r) {dx = xd; vol = l;}

  void interpolate_buffer (float* buf, float s, float e);
  void fill_pitch (float xd);
  void fill_volume (float v);
  void set_interpolated_pitch (float xd);
  void set_interpolated_pitch (float xd, int check);
  void set_interpolated_volume (float v);
  void set_interpolated_volume (float v, int check);

  void set_interpolated_pitch_volume (float xd, float v) {
    set_interpolated_pitch (xd);
    set_interpolated_volume (v);
  }

  void set_interpolated_pitch_volume (float xd, float v, int check) {
    set_interpolated_pitch (xd, check);
    set_interpolated_volume (v, check);
  }

  inline void operator() (float* out, int n, float* wav, float vol) {
    // no modulation audio output
    for (int i = 0; i < n; ++i) out[i] += (vol * wav[i]);
  }

  inline void operator() (float* out, int n, float* wav, float* vola) {
    // no modulation audio output with volume array
    for (int i = 0; i < n; ++i) out[i] += (vola[i] * wav[i]);
  }

  void operator() (float* out, int n, float* wav, float* am, float vol) {
    // AM modulation in audio output
    for (int i = 0; i < n; ++i) out[i] += ((vol + am[i]) * wav[i]);
  }

	void gen_wav_and_mix (float* wav, int n);
	void gen_wav_fm (solver& s, float& xx, float* wav, float* fm, int n); 
  void gen_wav_am (float* out, float* wav, float* am, int n);
	void gen_wav_fm_am_mix (float* out, int n);
	void gen_wav_mix (float* out, float vol, int n);
	void gen_wav_mix (float* out, float* vol, int n);
	void master (float* left, float* right, float* wav, int n, float* vol);
	void master (float* left, float* right, float* wav, int n, float vol);

};

#endif
