SYNTH!!!111!!!1!!1!1!1!!1!1
This commit is contained in:
parent
66ea7d41f6
commit
0daca6f46b
@ -27,7 +27,7 @@ pico_sdk_init()
|
||||
|
||||
file(GLOB_RECURSE DAISYSP_SOURCES "${CMAKE_CURRENT_LIST_DIR}/daisysp/**/*.cpp")
|
||||
|
||||
add_executable(sint-gauntlet ${DAISYSP_SOURCES} main.c buttons.c mux.c pwm.c vco.c)
|
||||
add_executable(sint-gauntlet ${DAISYSP_SOURCES} main.c buttons.c mux.c pwm.c synth.cc)
|
||||
|
||||
pico_set_program_name(sint-gauntlet "sint-gauntlet")
|
||||
pico_set_program_version(sint-gauntlet "0.1")
|
||||
|
||||
3
main.c
3
main.c
@ -8,15 +8,16 @@
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/pwm.h"
|
||||
#include "hardware/adc.h"
|
||||
#include "mux.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "buttons.h"
|
||||
#include "synth.h"
|
||||
#include "const.h"
|
||||
#include "macro.h"
|
||||
#include "state.h"
|
||||
#include "pwm.h"
|
||||
#include "mux.h"
|
||||
|
||||
state_t state;
|
||||
|
||||
|
||||
118
synth.cc
118
synth.cc
@ -1,6 +1,124 @@
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include "state.h"
|
||||
#include "const.h"
|
||||
#include "daisysp.h"
|
||||
#include "vco.h"
|
||||
#include "dsp.h"
|
||||
|
||||
#include "synth.h"
|
||||
|
||||
using namespace daisysp;
|
||||
|
||||
Oscillator osc;
|
||||
Svf filter;
|
||||
AdEnv vco_env;
|
||||
AdEnv filter_env;
|
||||
|
||||
// TODO: Reverb
|
||||
|
||||
float clock_phase = 0.0f;
|
||||
bool clock_trig = false;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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, (midi - 69.0f) / temp);
|
||||
}
|
||||
|
||||
static inline float low_pass(float in, float* z, float coeff) {
|
||||
*z += coeff * (in - *z);
|
||||
return *z;
|
||||
}
|
||||
|
||||
void synth_init(void) {
|
||||
osc.Init(SAMPLE_RATE);
|
||||
osc.SetWaveform(vco_mode_to_daisy(VCO_SINE));
|
||||
osc.SetFreq(440.0f);
|
||||
osc.SetAmp(1.0f);
|
||||
|
||||
filter.Init(SAMPLE_RATE);
|
||||
filter.SetFreq(2000.0f);
|
||||
filter.SetRes(0.0f);
|
||||
|
||||
vco_env.Init(SAMPLE_RATE);
|
||||
vco_env.SetTime(ADENV_SEG_ATTACK, 0.01f);
|
||||
vco_env.SetTime(ADENV_SEG_DECAY, 0.5f);
|
||||
vco_env.SetMin(0.0f);
|
||||
vco_env.SetMax(1.0f);
|
||||
|
||||
filter_env.Init(SAMPLE_RATE);
|
||||
filter_env.SetTime(ADENV_SEG_ATTACK, 0.01f);
|
||||
filter_env.SetTime(ADENV_SEG_DECAY, 0.5f);
|
||||
filter_env.SetMin(0.0f);
|
||||
filter_env.SetMax(1.0f);
|
||||
|
||||
clock_phase = 0.0f;
|
||||
clock_trig = false;
|
||||
}
|
||||
|
||||
float get_sample(void) {
|
||||
float bps = state.clock_bpm / 60.0f;
|
||||
float clock_inc = bps / SAMPLE_RATE;
|
||||
clock_phase += clock_inc;
|
||||
clock_trig = false;
|
||||
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, 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));
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
filter.SetFreq(mod_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 mix = vca_out;
|
||||
mix = fclamp(mix, -1.0f, 1.0f);
|
||||
|
||||
return mix;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
8
synth.h
8
synth.h
@ -1,4 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
float get_sample(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
15
vco.c
15
vco.c
@ -1,15 +0,0 @@
|
||||
#include "const.h"
|
||||
#include "state.h"
|
||||
|
||||
#include "vco.h"
|
||||
|
||||
float phase = 0.0f;
|
||||
float vco(void) {
|
||||
float phase_inc = (state.vco_freq * 1760) / SAMPLE_RATE;
|
||||
phase += phase_inc;
|
||||
|
||||
if (phase >= 1.0f) phase -= 1.0f;
|
||||
|
||||
return (phase * 2.0f) - 1.0f;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user