/*
* noiser.cc
* 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/
*/

#include "noiser.h"
#include "keyboard_keyboard.h"
#include "audio.h"
#include "console.h"

noiser::noiser () {
	warp (&interp);
	last_vol = 0.0f;
	set_spread (0.0f);
	set_value (0);
  //setcur = setnext = 1;
}

void noiser::set_value (float v) {
  value.cur = v;
	value.next = random_value ();
	value.delta = value.next - value.cur;
	alpha.val = 0.0f;
}

void noiser::calc_delta_alpha () {
	if (samples.due < 3) alpha.delta = 1; else alpha.delta = 1.0f / (samples.due - 1);
}

void noiser::set_samples (float sn) {
  samples.next = sn;
  samples.duei = samples.due = int (sn);
  samples.derr = samples.next - samples.duei;
  calc_delta_alpha ();
}

void noiser::set_spread (float s) {
	spread = s;
	random_value.set (-spread, spread);
}

void noiser::operator() (float* L, float* R, int n, float* vola) {
	for (int i = 0; i < n; ++i) { 
		alpha.val += alpha.delta; 
		alpha.warp = warp (alpha.val); 
		float no = value.cur + alpha.warp * value.delta; 
		float vno = vola[i] * no;
		L[i] += vno;
		R[i] += vno;
		if (++samples.cur < samples.due); else {
			set_value (no);
			samples.cur = 0;
			samples.err += samples.derr;
			if (samples.err < 1.0f) {
				samples.due = samples.duei;
			} else {
				samples.due = samples.duei + 1;
				samples.err = 1.0f - samples.err;
			}
			calc_delta_alpha ();
		}
	}
}

void noiser::operator() (float* L, float* R, int n, float vol) {
  /*if (setcur) {
    value.cur = aout.fdr2[0];
    value.next = aout.fdr2[samples.due-1];
    value.delta = value.next - value.cur;
    alpha.val = 0.0f;
    calc_delta_alpha ();
    setcur = 0;
  }
  if (setnext) {
    value.cur = value.next;
    value.next = L[nextoff];
    value.delta = value.next - value.cur;
    alpha.val = 0.0f;
    setnext = 0;
    nextoff = 0;
  }*/
	float v = last_vol;
	float dv = (vol - last_vol) * 1.0f / n; 
	for (int i = 0; i < n; ++i) { 
		alpha.val += alpha.delta; 
		alpha.warp = warp (alpha.val); 
		float no = value.cur + alpha.warp * value.delta; 
		v += dv;
		float vno = v * no;
		/*L[i] *= alpha.warp; //no; //alpha.warp;
    R[i] = L[i];*/

    L[i] += vno;
    R[i] = L[i];

		if (++samples.cur < samples.due); else {
      set_value (no);
			samples.cur = 0;
			samples.err += samples.derr;
			if (samples.err < 1.0f) {
				samples.due = samples.duei;
			} else {
				samples.due = samples.duei + 1;
				samples.err = 1.0f - samples.err;
        calc_delta_alpha ();
			}
      /*int nex = i + samples.due;
      if (nex >= n) {
        nextoff = nex - n;
        value.cur = value.next;
        value.next = aout.fdr1 [nextoff];
      } else {
        value.cur = value.next;
        value.next = aout.fdr2[nex];
      }
      value.delta = value.next - value.cur;*/
      alpha.val = 0.0f;
		}
	}
	last_vol = vol;
}

ofstream& operator<< (ofstream& o, noiser& n) {
	extern const char spc;
	o << n.spread << spc << n.samples.next;
	return o;
}
