#include #include "daisysp.h" #include "state.h" #include "const.h" #include "vco.h" #include "synth.h" using namespace daisysp; static state_t* state = NULL; Oscillator osc; Svf filter; AdEnv vco_env; AdEnv filter_env; float clock_phase = 0.0f; bool clock_trig = false; uint32_t amen_phase_fp = 0; float amen_length = 0.0f; static inline auto vco_mode_to_daisy(vco_mode_t mode) { switch (mode) { case VCO_SQUARE: return daisysp::Oscillator::WAVE_SQUARE; case VCO_TRIANGLE: return daisysp::Oscillator::WAVE_TRI; case VCO_SAW: return daisysp::Oscillator::WAVE_SAW; case VCO_SINE: default: return daisysp::Oscillator::WAVE_SIN; } } #include "amenbreak.h" float amenbreak() { amen_phase_fp += state->amen_inc_fp; uint32_t idx0 = (amen_phase_fp >> 16) % amen_sample_count; uint32_t idx1 = (idx0 + 1) % amen_sample_count; float frac = (float)(amen_phase_fp & 0xFFFF) * 0.0000152588f; const float INV_INT16 = 0.00003051757f; float s0 = amen_samples[idx0] * INV_INT16; float s1 = amen_samples[idx1] * INV_INT16; return s0 + frac * (s1 - s0); } void synth_init(state_t* _state) { state = _state; osc.Init(SAMPLE_RATE); filter.Init(SAMPLE_RATE); vco_env.Init(SAMPLE_RATE); vco_env.SetMin(0.0f); vco_env.SetMax(VCO_VOLUME_MAX); filter_env.Init(SAMPLE_RATE); filter_env.SetMin(0.0f); filter_env.SetMax(FILTER_FREQ_MAX); clock_phase = 0.0f; clock_trig = false; amen_phase_fp = 0; } float get_sample(void) { if (state == NULL) return 0.0f; bool clock_trig = false; clock_phase += state->clock_inc; if (clock_phase >= 1.0f) { clock_phase -= 1.0f; clock_trig = true; } if (clock_trig) { vco_env.Trigger(); filter_env.Trigger(); } vco_env.SetTime(ADENV_SEG_ATTACK, state->env1_attack); vco_env.SetTime(ADENV_SEG_DECAY, state->env1_decay); filter_env.SetTime(ADENV_SEG_ATTACK, state->env2_attack); filter_env.SetTime(ADENV_SEG_DECAY, state->env2_decay); float vco_env_out = vco_env.Process(); float filter_env_out = filter_env.Process(); osc.SetFreq(state->vco_freq); osc.SetWaveform(vco_mode_to_daisy(state->vco_mode)); osc.SetAmp(1.0f); float vco_out = osc.Process(); float cutoff = state->filter_freq + filter_env_out; if (cutoff > 16000.0f) cutoff = 16000.0f; filter.SetFreq(cutoff); filter.SetRes(state->filter_resonance); filter.Process(vco_out); float vca_out = filter.Low() * vco_env_out * state->vco_volume; float amen_out = state->amen_enabled ? amenbreak() : 0.0f; float mix = vca_out + amen_out; if (mix > 1.0f) return 1.0f; if (mix < -1.0f) return -1.0f; return mix; }