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

#include "curve_mixer.h"
#include "multi_curve.h"
#include "console.h"
#include "chrono.h"
#include <algorithm>

#include <string>

extern int SAMPLE_RATE;
extern char BUFFER [];

curve_mixer::curve_mixer () {
	a = da = 0;
	x = dx = 0;
	active = 0;
}

curve_mixer::~curve_mixer () {
  if (active) cons << GREEN << "Finished mixing (@ " << name << ")" << eol;
}

void curve_mixer::setup (multi_curve& crv, float ix, float idx) {
	a = 0.0f;
  da = 1./ (TIME * SAMPLE_RATE);
	x = ix;
	dx = idx;
	mix = crv;
	sol (&mix);
	active = 1;
  ELAPSEDT = 0; 
}

void curve_mixer::gen_mix (float* out, int n) {
	sol (x, dx, n, out);
}

void curve_mixer::gen_mix (float* out, int n, xhandler& xmin, xhandler& xmax) {
	sol (x, dx, n, out, xmin, xmax);
}

void curve_mixer::gen_fm (float* out, int n, float* fm) {
	sol (x, dx, n, fm, out);
}

void curve_mixer::fill_alpha (float* ab, int n) {
  for (int i = 0; i < n; ++i) {
    ab[i] = a;
    a += da;
  }
}

void curve_mixer::gen_alpha (float* ab, int n) {
  float fa = a + n * da;
  if (fa < 1.0) {
    fill_alpha (ab, n);
  } else {
    int n1 = (1 - a) / da;
    fill_alpha (ab, n1);
    int n2 = n - n1;
    for (int i = n1, j = n1 + n2; i < j; ++i) ab[i] = 1.0f;
    a = 1.0f;
    active = 0;
    sprintf (BUFFER, "Curve mixing complete (@ %s)", name.c_str());
    cons << GREEN << BUFFER << eol;
  }
}

void curve_mixer::do_mix (float* out, float* mixb, float* mixa, int n) {

  gen_alpha (mixa, n);

	for (int i = 0; i < n; ++i) {
		float mv = mixb[i];
		out[i] = mv + mixa[i] * (out[i] - mv);
	}

  if (active && ui_clk() >= ELAPSEDT) {
		sprintf (BUFFER, "Curve mixing %d%% complete (@ %s)", int(a * 100), name.c_str());
		cons << YELLOW << BUFFER << eol;
    ELAPSEDT = ui_clk () + std::min<double> (1.0, 0.05 * TIME);
  }

}
