/*
  ==============================================================================

	shifter_voice.cpp
	Created: 25 Oct 2025 2:09:42pm
	Author:  mickl

  ==============================================================================
*/

#include "shifter_voice.h"


static inline float mtof(float m)
{
	return powf(2, (m - 69.0f) / 12.0f) * 440.0f;
}


void ShifterVoice::Init(float sample_rate) {
	sample_rate_ = sample_rate;
	portamento_.Init(sample_rate_, 0.05f); //default portamento time
	amplitude_envelope_.Init(sample_rate_);
	amplitude_envelope_.SetAttackTime(0.2f);
	amplitude_envelope_.SetDecayTime(0.1f);	
	amplitude_envelope_.SetReleaseTime(.05f);
	onoff_ = false;
	overflow_ = false;
	current_midi = 60;
	current_period_ = sample_rate_ / mtof((float)current_midi);
	current_amplitude = 0.0f;
	period_counter = 0.0f;
	panning = 0.5f;
	//on reset, make sure envelope is not running
	while (amplitude_envelope_.IsRunning()) {
		amplitude_envelope_.Process(false);
	}
}


bool ShifterVoice::IsActive() { return amplitude_envelope_.IsRunning(); }

void ShifterVoice::Trigger(int midi_note) {
	current_midi = midi_note;
	// Retrigger envelope
	amplitude_envelope_.Retrigger(false);
	onoff_ = true;
	panning = rand() / (float)RAND_MAX;
}

void ShifterVoice::Release() {
	onoff_ = false;
}

void ShifterVoice::Process() {
	current_amplitude = amplitude_envelope_.Process(onoff_);
	current_period_ = sample_rate_ / mtof(portamento_.Process((float)current_midi));
	period_counter++;
	overflow_ = period_counter >= current_period_;
	if (overflow_) {
		period_counter -= current_period_;
	}
}

float ShifterVoice::CurrentAmplitude() {
	return current_amplitude;
}

float ShifterVoice::CurrentPeriod() {
	return current_period_;
}

bool ShifterVoice::PeriodOverflow() {
	return overflow_;
}

void ShifterVoice::SetPortamentoTime(float time) {
	portamento_.SetHtime(time);
}

void ShifterVoice::SetAdsrTimes(float attack, float decay, float release) {
	amplitude_envelope_.SetAttackTime(attack);
	amplitude_envelope_.SetDecayTime(decay);
	amplitude_envelope_.SetReleaseTime(release);
	amplitude_envelope_.SetSustainLevel(1.0);
}

float ShifterVoice::GetPanning(int channel) const {
	switch (channel) {
	default:
	case 0:
		return panning < .5 ? 1.0 : 2.0f - (panning * 2.0f);
	case 1:
		return panning > .5 ? 1.0 : panning * 2.0f;
	}
}