Maybe works?
This commit is contained in:
@@ -1,34 +1,25 @@
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "daisysp.h"
|
||||
#include "state.h"
|
||||
#include "const.h"
|
||||
#include "vco.h"
|
||||
#include "dsp.h"
|
||||
|
||||
#include "synth.h"
|
||||
|
||||
using namespace daisysp;
|
||||
|
||||
static state_t* state;
|
||||
static state_t* state = NULL;
|
||||
|
||||
Oscillator osc;
|
||||
Svf filter;
|
||||
AdEnv vco_env;
|
||||
AdEnv filter_env;
|
||||
|
||||
DelayLine<float, COMB0_SIZE> comb0;
|
||||
DelayLine<float, COMB1_SIZE> comb1;
|
||||
DelayLine<float, COMB2_SIZE> comb2;
|
||||
DelayLine<float, COMB3_SIZE> comb3;
|
||||
DelayLine<float, AP0_SIZE> ap0;
|
||||
DelayLine<float, AP1_SIZE> ap1;
|
||||
|
||||
float clock_phase = 0.0f;
|
||||
bool clock_trig = false;
|
||||
|
||||
float amen_phase = 0.0f;
|
||||
uint32_t amen_phase_fp = 0;
|
||||
float amen_length = 0.0f;
|
||||
|
||||
static inline auto vco_mode_to_daisy(vco_mode_t mode) {
|
||||
@@ -41,86 +32,45 @@ static inline auto vco_mode_to_daisy(vco_mode_t mode) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline float pot_to_freq(float v, float min, float max) { return min * powf(max / min, v); }
|
||||
|
||||
static inline float pot_to_time(float v, float min, float max) { return min * powf(max / min, v); }
|
||||
|
||||
static inline float quantize(float freq, float temp) {
|
||||
float midi = temp * log2f(freq / 440.0f) + 69.0f;
|
||||
float note = roundf(midi);
|
||||
return 440.0f * powf(2.0f, (note - 69.0f) / temp);
|
||||
}
|
||||
|
||||
static inline float low_pass(float in, float* z, float coeff) {
|
||||
*z += coeff * (in - *z);
|
||||
return *z;
|
||||
}
|
||||
|
||||
float reverb(float in, float amount) {
|
||||
static float damp0 = 0.0f, damp1 = 0.0f, damp2 = 0.0f, damp3 = 0.0f;
|
||||
float feedback = 0.84f;
|
||||
float damp = 0.3f;
|
||||
|
||||
float c0 = comb0.Read(); low_pass(in + c0 * feedback, &damp0, damp); comb0.Write(damp0);
|
||||
float c1 = comb1.Read(); low_pass(in + c1 * feedback, &damp1, damp); comb1.Write(damp1);
|
||||
float c2 = comb2.Read(); low_pass(in + c2 * feedback, &damp2, damp); comb2.Write(damp2);
|
||||
float c3 = comb3.Read(); low_pass(in + c3 * feedback, &damp3, damp); comb3.Write(damp3);
|
||||
|
||||
float wet = (c0 + c1 + c2 + c3) * 0.25f;
|
||||
|
||||
const float g = 0.7f;
|
||||
float a0r = ap0.Read();
|
||||
float a0in = wet + (-g * a0r);
|
||||
ap0.Write(a0in);
|
||||
wet = a0r + g * a0in;
|
||||
|
||||
float a1r = ap1.Read();
|
||||
float a1in = wet + (-g * a1r);
|
||||
ap1.Write(a1in);
|
||||
wet = a1r + g * a1in;
|
||||
|
||||
return in + amount * (wet - in);
|
||||
}
|
||||
|
||||
#include "amenbreak.h"
|
||||
|
||||
float amenbreak(float beat_samples, float playback_rate) {
|
||||
amen_length = beat_samples * 4.0f * AMEN_BARS;
|
||||
|
||||
uint32_t idx0 = (uint32_t)amen_phase % amen_sample_count;
|
||||
uint32_t idx1 = (idx0 + 1) % amen_sample_count;
|
||||
float frac = amen_phase - floorf(amen_phase);
|
||||
float s0 = amen_samples[idx0] * (1.0f / 32768.0f);
|
||||
float s1 = amen_samples[idx1] * (1.0f / 32768.0f);
|
||||
float amen_out = s0 + frac * (s1 - s0);
|
||||
|
||||
amen_phase += playback_rate;
|
||||
if (amen_phase >= amen_length) amen_phase -= amen_length;
|
||||
return amen_out;
|
||||
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) {
|
||||
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);
|
||||
vco_env.SetMax(FILTER_FREQ_MAX);
|
||||
vco_env.SetMin(0.0f);
|
||||
vco_env.SetMax(VCO_VOLUME_MAX);
|
||||
filter_env.Init(SAMPLE_RATE);
|
||||
filter_env.SetMin(0);
|
||||
filter_env.SetMin(0.0f);
|
||||
filter_env.SetMax(FILTER_FREQ_MAX);
|
||||
clock_phase = 0.0f;
|
||||
clock_trig = false;
|
||||
amen_phase = 0.0f;
|
||||
amen_phase_fp = 0;
|
||||
}
|
||||
|
||||
float get_sample(void) {
|
||||
float bpm = BPM_MIN + state->clock_bpm * (BPM_MAX - BPM_MIN);
|
||||
float beat_samples = SAMPLE_RATE * 60.0f / bpm;
|
||||
float playback_rate = bpm / AMEN_BPM;
|
||||
if (state == NULL) return 0.0f;
|
||||
|
||||
float clock_inc = bpm / 60.0f / SAMPLE_RATE;
|
||||
clock_phase += clock_inc;
|
||||
clock_trig = false;
|
||||
bool clock_trig = false;
|
||||
|
||||
clock_phase += state->clock_inc;
|
||||
if (clock_phase >= 1.0f) {
|
||||
clock_phase -= 1.0f;
|
||||
clock_trig = true;
|
||||
@@ -131,38 +81,32 @@ float get_sample(void) {
|
||||
filter_env.Trigger();
|
||||
}
|
||||
|
||||
vco_env.SetTime(ADENV_SEG_ATTACK, pot_to_time(state->env1_attack, ENV_ATTACK_MIN, ENV_ATTACK_MAX));
|
||||
vco_env.SetTime(ADENV_SEG_DECAY, pot_to_time(state->env1_release, ENV_RELEASE_MIN, ENV_RELEASE_MAX));
|
||||
filter_env.SetTime(ADENV_SEG_ATTACK, pot_to_time(state->env2_attack, ENV_ATTACK_MIN, ENV_ATTACK_MAX));
|
||||
filter_env.SetTime(ADENV_SEG_DECAY, pot_to_time(state->env2_release, ENV_RELEASE_MIN, ENV_RELEASE_MAX));
|
||||
|
||||
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();
|
||||
|
||||
float vco_freq = pot_to_freq(state->vco_freq, VCO_FREQ_MIN, VCO_FREQ_MAX);
|
||||
if (state->quant_enabled) vco_freq = quantize(vco_freq, 12.0f);
|
||||
|
||||
osc.SetFreq(vco_freq);
|
||||
static int n = VCO_SINE;
|
||||
osc.SetWaveform(vco_mode_to_daisy((vco_mode_t)(n++ % 4)));
|
||||
osc.SetFreq(state->vco_freq);
|
||||
osc.SetWaveform(vco_mode_to_daisy(state->vco_mode));
|
||||
osc.SetAmp(1.0f);
|
||||
float vco_out = osc.Process();
|
||||
|
||||
float base_cutoff = pot_to_freq(state->filter_freq, FILTER_FREQ_MIN, FILTER_FREQ_MAX);
|
||||
filter.SetFreq(base_cutoff + filter_env_out);
|
||||
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 filtered = filter.Low();
|
||||
|
||||
float vca_out = filtered * vco_env_out * state->vco_volume;
|
||||
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;
|
||||
|
||||
float reverb_out = reverb(vca_out, state->reverb_amount);
|
||||
|
||||
float amen_out = 0.0f;
|
||||
if (state->amen_enabled) amen_out = amenbreak(beat_samples, playback_rate);
|
||||
|
||||
float mix = reverb_out + amen_out;
|
||||
mix = fclamp(mix, -1.0f, 1.0f);
|
||||
if (mix > 1.0f) return 1.0f;
|
||||
if (mix < -1.0f) return -1.0f;
|
||||
|
||||
return mix;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user