sint-gauntlet/synth.cc
2026-04-30 09:32:14 +02:00

114 lines
2.6 KiB
C++

#include <stdint.h>
#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;
}