Compare commits
4 Commits
09b1a6707a
...
774980200c
| Author | SHA1 | Date | |
|---|---|---|---|
| 774980200c | |||
| 23a0cbee6f | |||
| 61e4106443 | |||
| 17a3a79c44 |
4
amenbreak.h
Normal file
4
amenbreak.h
Normal file
File diff suppressed because one or more lines are too long
27
buttons.c
27
buttons.c
@ -4,22 +4,21 @@
|
||||
#include <pico/types.h>
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
void handle_vco_change(void) {
|
||||
static bool btn_prev = false;
|
||||
void check_button_change(uint pin, bool* btn_state) {
|
||||
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);
|
||||
if (btn_now && !btn_prev) {
|
||||
void update_buttons() {
|
||||
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;
|
||||
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();
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
#include <pico/types.h>
|
||||
|
||||
void handle_vco_change(uint gpio, uint32_t events);
|
||||
void update_button(uint pin, bool *button_state);
|
||||
void update_buttons();
|
||||
|
||||
|
||||
2
const.h
2
const.h
@ -37,6 +37,8 @@
|
||||
#define REVERB_AMOUNT_MIN 0.0f
|
||||
#define REVERB_AMOUNT_MAX 1.0f
|
||||
|
||||
#define AMEN_BPM 85.0f
|
||||
#define AMEN_BARS 4.0f
|
||||
|
||||
#define otherwise else
|
||||
|
||||
|
||||
5
main.c
5
main.c
@ -68,8 +68,7 @@ void core1_main(void) {
|
||||
while (1) {
|
||||
update_buttons();
|
||||
update_inputs();
|
||||
//printf("vco_mode: %d, quant_enabled: %d amen_enabled: %d\n", state.vco_mode,state.quant_enabled,state.amen_enabled);
|
||||
//printf("clock_bpm: %f\n",state.clock_bpm);
|
||||
printf("Sample: %f\n", state.dbg_sample);
|
||||
sleep_ms(1);
|
||||
}
|
||||
}
|
||||
@ -78,6 +77,6 @@ __attribute__((noreturn))
|
||||
int main() {
|
||||
init_all();
|
||||
multicore_launch_core1(core1_main);
|
||||
while (1) {}
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
4
pwm.c
4
pwm.c
@ -1,8 +1,8 @@
|
||||
#include <hardware/pwm.h>
|
||||
#include <pico/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "const.h"
|
||||
#include "state.h"
|
||||
#include "synth.h"
|
||||
|
||||
#include "pwm.h"
|
||||
@ -15,7 +15,7 @@ void pwm_isr(void) {
|
||||
pwm_clear_irq(slice);
|
||||
|
||||
float sample = get_sample();
|
||||
printf("sample: %f\n", sample);
|
||||
state.dbg_sample = sample;
|
||||
|
||||
uint16_t level = (uint16_t)((sample + 1.0f) * 0.5f * 3400.0f);
|
||||
pwm_set_chan_level(slice, chan, level);
|
||||
|
||||
2
state.h
2
state.h
@ -23,6 +23,8 @@ typedef struct {
|
||||
vco_mode_t vco_mode;
|
||||
bool quant_enabled;
|
||||
bool amen_enabled;
|
||||
|
||||
float dbg_sample;
|
||||
} state_t;
|
||||
|
||||
extern state_t state;
|
||||
|
||||
86
synth.cc
86
synth.cc
@ -1,8 +1,9 @@
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "daisysp.h"
|
||||
#include "state.h"
|
||||
#include "const.h"
|
||||
#include "daisysp.h"
|
||||
#include "vco.h"
|
||||
#include "dsp.h"
|
||||
|
||||
@ -15,11 +16,19 @@ Svf filter;
|
||||
AdEnv vco_env;
|
||||
AdEnv filter_env;
|
||||
|
||||
// TODO: Reverb
|
||||
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;
|
||||
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;
|
||||
@ -37,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) {
|
||||
float midi = temp * log2f(freq / 440.0f) + 69.0f;
|
||||
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) {
|
||||
@ -45,11 +54,54 @@ static inline float low_pass(float in, float* z, float coeff) {
|
||||
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;
|
||||
}
|
||||
|
||||
void synth_init(void) {
|
||||
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.SetAmp(1.0f);
|
||||
osc.SetAmp(2.0f);
|
||||
|
||||
filter.Init(SAMPLE_RATE);
|
||||
filter.SetFreq(2000.0f);
|
||||
@ -57,7 +109,7 @@ void synth_init(void) {
|
||||
|
||||
vco_env.Init(SAMPLE_RATE);
|
||||
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.SetMax(1.0f);
|
||||
|
||||
@ -67,17 +119,22 @@ void synth_init(void) {
|
||||
filter_env.SetMin(0.0f);
|
||||
filter_env.SetMax(1.0f);
|
||||
|
||||
state.clock_bpm = 0.2f;
|
||||
|
||||
clock_phase = 0.0f;
|
||||
clock_trig = false;
|
||||
|
||||
amen_phase = 0.0f;
|
||||
state.amen_enabled = true;
|
||||
state.reverb_amount = 1.0;
|
||||
}
|
||||
|
||||
float get_sample(void) {
|
||||
return osc.Process();
|
||||
}
|
||||
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;
|
||||
|
||||
float _get_sample(void) {
|
||||
float bps = state.clock_bpm / 60.0f;
|
||||
float clock_inc = bps / SAMPLE_RATE;
|
||||
float clock_inc = bpm / 60.0f / SAMPLE_RATE;
|
||||
clock_phase += clock_inc;
|
||||
clock_trig = false;
|
||||
if (clock_phase >= 1.0f) {
|
||||
@ -118,7 +175,12 @@ float _get_sample(void) {
|
||||
|
||||
float vca_out = filtered * vco_env_out * state.vco_volume;
|
||||
|
||||
float mix = vca_out;
|
||||
float reverb_out = vca_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);
|
||||
|
||||
return mix;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user