Finished hopefully

This commit is contained in:
Tom-on64 2026-04-25 09:07:02 +02:00
parent 23a0cbee6f
commit 774980200c
6 changed files with 72 additions and 39 deletions

View File

@ -4,22 +4,21 @@
#include <pico/types.h> #include <pico/types.h>
#include "hardware/gpio.h" #include "hardware/gpio.h"
void handle_vco_change(void) { void check_button_change(uint pin, bool* btn_state) {
static bool btn_prev = false; static bool btn_prev[32] = { false };
bool btn_now = gpio_get(pin);
if (btn_now && !btn_prev[pin]) *btn_state = !*btn_state;
btn_prev[pin] = btn_now;
}
bool btn_now = gpio_get(VCO_BUTTON); void update_buttons() {
if (btn_now && !btn_prev) { check_button_change(QUANT_BUTTON, &state.quant_enabled);
check_button_change(AMEN_BUTTON, &state.amen_enabled);
bool vco_change;
check_button_change(VCO_BUTTON, &vco_change);
if (vco_change) {
if (state.vco_mode == VCO_SAW) state.vco_mode = VCO_SINE; if (state.vco_mode == VCO_SAW) state.vco_mode = VCO_SINE;
otherwise state.vco_mode++; otherwise state.vco_mode++;
} }
} }
void update_button(uint pin, bool *button_state) {
if(gpio_get(pin) != *button_state) *button_state = !*button_state;
}
void update_buttons() {
update_button(QUANT_BUTTON, &state.quant_enabled);
update_button(AMEN_BUTTON, &state.amen_enabled);
handle_vco_change();
}

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <pico/types.h> #include <pico/types.h>
void handle_vco_change(uint gpio, uint32_t events);
void update_button(uint pin, bool *button_state);
void update_buttons(); void update_buttons();

View File

@ -37,6 +37,8 @@
#define REVERB_AMOUNT_MIN 0.0f #define REVERB_AMOUNT_MIN 0.0f
#define REVERB_AMOUNT_MAX 1.0f #define REVERB_AMOUNT_MAX 1.0f
#define AMEN_BPM 85.0f
#define AMEN_BARS 4.0f
#define otherwise else #define otherwise else

2
main.c
View File

@ -77,6 +77,6 @@ __attribute__((noreturn))
int main() { int main() {
init_all(); init_all();
multicore_launch_core1(core1_main); multicore_launch_core1(core1_main);
while (1) {} while (1);
} }

View File

@ -46,7 +46,7 @@ static inline float pot_to_time(float v, float min, float max) { return min * po
static inline float quantize(float freq, float temp) { static inline float quantize(float freq, float temp) {
float midi = temp * log2f(freq / 440.0f) + 69.0f; float midi = temp * log2f(freq / 440.0f) + 69.0f;
float note = roundf(midi); float note = roundf(midi);
return 440.0f * powf(2.0f, (midi - 69.0f) / temp); return 440.0f * powf(2.0f, (note - 69.0f) / temp);
} }
static inline float low_pass(float in, float* z, float coeff) { static inline float low_pass(float in, float* z, float coeff) {
@ -55,14 +55,14 @@ static inline float low_pass(float in, float* z, float coeff) {
} }
float reverb(float in, float amount) { float reverb(float in, float amount) {
float damp0 = 0.0f, damp1 = 0.0f, damp2 = 0.0f, damp3 = 0.0f; static float damp0 = 0.0f, damp1 = 0.0f, damp2 = 0.0f, damp3 = 0.0f;
float feedback = 0.84f; float feedback = 0.84f;
float damp = 0.3f; float damp = 0.3f;
float c0 = comb0.Read(); low_pass(in + c0 * feedback, &damp0, damp0); comb0.Write(damp0); float c0 = comb0.Read(); low_pass(in + c0 * feedback, &damp0, damp); comb0.Write(damp0);
float c1 = comb1.Read(); low_pass(in + c1 * feedback, &damp1, damp1); comb1.Write(damp1); float c1 = comb1.Read(); low_pass(in + c1 * feedback, &damp1, damp); comb1.Write(damp1);
float c2 = comb2.Read(); low_pass(in + c2 * feedback, &damp2, damp2); comb2.Write(damp2); float c2 = comb2.Read(); low_pass(in + c2 * feedback, &damp2, damp); comb2.Write(damp2);
float c3 = comb3.Read(); low_pass(in + c3 * feedback, &damp3, damp3); comb3.Write(damp3); float c3 = comb3.Read(); low_pass(in + c3 * feedback, &damp3, damp); comb3.Write(damp3);
float wet = (c0 + c1 + c2 + c3) * 0.25f; float wet = (c0 + c1 + c2 + c3) * 0.25f;
@ -80,11 +80,28 @@ float reverb(float in, float amount) {
return in + amount * (wet - in); 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;
}
void synth_init(void) { void synth_init(void) {
osc.Init(SAMPLE_RATE); osc.Init(SAMPLE_RATE);
osc.SetWaveform(vco_mode_to_daisy(VCO_SINE)); osc.SetWaveform(vco_mode_to_daisy(VCO_SAW));
osc.SetFreq(440.0f); osc.SetFreq(440.0f);
osc.SetAmp(1.0f); osc.SetAmp(2.0f);
filter.Init(SAMPLE_RATE); filter.Init(SAMPLE_RATE);
filter.SetFreq(2000.0f); filter.SetFreq(2000.0f);
@ -92,7 +109,7 @@ void synth_init(void) {
vco_env.Init(SAMPLE_RATE); vco_env.Init(SAMPLE_RATE);
vco_env.SetTime(ADENV_SEG_ATTACK, 0.01f); vco_env.SetTime(ADENV_SEG_ATTACK, 0.01f);
vco_env.SetTime(ADENV_SEG_DECAY, 0.5f); vco_env.SetTime(ADENV_SEG_DECAY, 0.8f);
vco_env.SetMin(0.0f); vco_env.SetMin(0.0f);
vco_env.SetMax(1.0f); vco_env.SetMax(1.0f);
@ -106,11 +123,18 @@ void synth_init(void) {
clock_phase = 0.0f; clock_phase = 0.0f;
clock_trig = false; clock_trig = false;
amen_phase = 0.0f;
state.amen_enabled = true;
state.reverb_amount = 1.0;
} }
float get_sample(void) { float get_sample(void) {
float bps = pot_to_time(state.clock_bpm, BPM_MIN, BPM_MAX) / 60.0f; float bpm = BPM_MIN + state.clock_bpm * (BPM_MAX - BPM_MIN);
float clock_inc = bps / SAMPLE_RATE; float beat_samples = SAMPLE_RATE * 60.0f / bpm;
float playback_rate = bpm / AMEN_BPM;
float clock_inc = bpm / 60.0f / SAMPLE_RATE;
clock_phase += clock_inc; clock_phase += clock_inc;
clock_trig = false; clock_trig = false;
if (clock_phase >= 1.0f) { if (clock_phase >= 1.0f) {
@ -123,10 +147,10 @@ float get_sample(void) {
filter_env.Trigger(); 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_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)); 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_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)); filter_env.SetTime(ADENV_SEG_DECAY, pot_to_time(state.env2_release, ENV_RELEASE_MIN, ENV_RELEASE_MAX));
float vco_env_out = vco_env.Process(); float vco_env_out = vco_env.Process();
float filter_env_out = filter_env.Process(); float filter_env_out = filter_env.Process();
@ -134,9 +158,9 @@ float get_sample(void) {
float vco_freq = pot_to_freq(state.vco_freq, VCO_FREQ_MIN, VCO_FREQ_MAX); 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); if (state.quant_enabled) vco_freq = quantize(vco_freq, 12.0f);
//osc.SetFreq(vco_freq); osc.SetFreq(vco_freq);
//osc.SetWaveform(vco_mode_to_daisy(state.vco_mode)); osc.SetWaveform(vco_mode_to_daisy(state.vco_mode));
//osc.SetAmp(1.0f); osc.SetAmp(1.0f);
float vco_out = osc.Process(); float vco_out = osc.Process();
@ -144,16 +168,19 @@ float get_sample(void) {
float mod_cutoff = base_cutoff + filter_env_out * (FILTER_FREQ_MAX - FILTER_FREQ_MIN); float mod_cutoff = base_cutoff + filter_env_out * (FILTER_FREQ_MAX - FILTER_FREQ_MIN);
mod_cutoff = fclamp(mod_cutoff, FILTER_FREQ_MIN, FILTER_FREQ_MAX); mod_cutoff = fclamp(mod_cutoff, FILTER_FREQ_MIN, FILTER_FREQ_MAX);
//filter.SetFreq(mod_cutoff); filter.SetFreq(mod_cutoff);
//filter.SetRes(state.filter_resonance); filter.SetRes(state.filter_resonance);
filter.Process(vco_out); filter.Process(vco_out);
float filtered = filter.Low(); float filtered = filter.Low();
float vca_out = filtered * vco_env_out * state.vco_volume; float vca_out = filtered * vco_env_out * state.vco_volume;
float reverb_out = reverb(vca_out, state.reverb_amount); float reverb_out = vca_out; //reverb(vca_out, state.reverb_amount);
float mix = reverb_out; 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); mix = fclamp(mix, -1.0f, 1.0f);
return mix; return mix;

View File

@ -1,5 +1,12 @@
#pragma once #pragma once
#define COMB0_SIZE 1103
#define COMB1_SIZE 1361
#define COMB2_SIZE 1499
#define COMB3_SIZE 1693
#define AP0_SIZE 131
#define AP1_SIZE 43
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif