Compare commits

...

47 Commits

Author SHA1 Message Date
PoliEcho 052ac9eb17 fix input pots and amen break 2026-06-06 14:06:29 +02:00
PoliEcho e9564f42eb Turn on onboard led on power on
(causes the synth to work for some reason)
2026-06-05 16:12:42 +02:00
Tom-on bd2ac926b0 Maybe works? 2026-04-30 09:32:14 +02:00
Tom-on a8c231df50 Added input processing to state 2026-04-27 14:16:28 +02:00
Tom-on 787bf50957 Added state processing stage 2026-04-27 12:11:41 +02:00
Tom-on 1fd0a56064 Combined mux.c and buttons.c to input.c 2026-04-26 17:04:37 +02:00
Tom-on 8a55e8e60c Added build script 2026-04-26 16:26:35 +02:00
Tom-on 774980200c Finished hopefully 2026-04-25 09:07:02 +02:00
Tom-on 23a0cbee6f Added amenbreak.h 2026-04-25 06:04:17 +02:00
Tom-on 61e4106443 reverb 2026-04-25 05:57:21 +02:00
Tom-on 17a3a79c44 TOOONEEEEE 2026-04-25 05:40:35 +02:00
Tom-on 09b1a6707a Ye 2026-04-25 03:05:25 +02:00
Tom-on 0daca6f46b SYNTH!!!111!!!1!!1!1!1!!1!1 2026-04-24 19:09:27 +02:00
PoliEcho 66ea7d41f6 add sensable min/max 2026-04-24 18:40:21 +02:00
PoliEcho d5f8876ada fix vco.hh name 2026-04-24 18:37:21 +02:00
Tom-on 57c3d2bc80 state 2026-04-24 18:35:13 +02:00
PoliEcho cbed3f24a1 Merge branch 'master' of https://git.pupes.org/PoliEcho/sint-gauntlet 2026-04-24 18:27:58 +02:00
PoliEcho 5c6a687471 fix analog input 2026-04-24 18:27:29 +02:00
Tom-on b857418795 Merge branch 'master' of https://git.pupes.org/PoliEcho/sint-gauntlet 2026-04-24 18:01:58 +02:00
Tom-on d29f2e8c39 Base synth.c 2026-04-24 18:01:52 +02:00
PoliEcho c515c1e07e remove stdbool.h 2026-04-24 17:37:59 +02:00
PoliEcho daa4fa9564 Merge branch 'master' of https://git.pupes.org/PoliEcho/sint-gauntlet 2026-04-24 17:29:30 +02:00
PoliEcho de4f958b1e upgrade standard 2026-04-24 17:29:28 +02:00
Tom-on 895b0d635c Added pico_multicore to cmake 2026-04-24 17:16:31 +02:00
Tom-on 63ae3f694b Changing main.cc to main.c fixed all my problems 2026-04-24 17:16:11 +02:00
Tom-on 83507f9945 Updated CMakeLists.txt 2026-04-24 17:07:11 +02:00
PoliEcho 5f8ace8de6 move sleep to the end off update loop 2026-04-24 17:03:30 +02:00
PoliEcho 4e70e1458e Merge branch 'master' of https://git.pupes.org/PoliEcho/sint-gauntlet 2026-04-24 17:02:57 +02:00
Tom-on 630faa5a90 Added update_inputs() to main.cc 2026-04-24 17:01:02 +02:00
PoliEcho 500c93a6fd add sleep 2026-04-24 17:00:52 +02:00
Tom-on c71a162d86 forgor main.cc 💀 2026-04-24 16:58:20 +02:00
Tom-on afaa87daec Added PWM 2026-04-24 16:57:53 +02:00
Tom-on e375586804 Made buttons work V2 2026-04-24 16:57:38 +02:00
Tom-on d5933cd060 Made buttons work 2026-04-24 16:30:50 +02:00
PoliEcho 061ca37ad7 add button basics 2026-04-24 16:17:59 +02:00
PoliEcho 65516b2bff hey clanker to fixnul 2026-04-24 15:41:13 +02:00
PoliEcho a5d9b99098 fix AUDIO_OUT 2026-04-24 15:31:59 +02:00
Tom-on 3a24cb235b Merge branch 'master' of https://git.pupes.org/PoliEcho/sint-gauntlet 2026-04-24 15:31:19 +02:00
Tom-on 0c79b141fd Renamed PWM_OUT to AUDIO_OUT :p 2026-04-24 15:31:13 +02:00
PoliEcho f4aa96104f mutiplexors done 2026-04-24 15:22:37 +02:00
PoliEcho 946417b020 Merge branch 'master' of https://git.pupes.org/PoliEcho/sint-gauntlet 2026-04-24 15:15:50 +02:00
Tom-on baf6cdb4cc Renamed AUDIO_OUT to PWM_OUT :p 2026-04-24 15:15:32 +02:00
PoliEcho 9d902924b5 add reseved space because i am lazy 2026-04-24 15:15:28 +02:00
Tom-on db4a1312a9 Added array to state 2026-04-24 15:13:31 +02:00
Tom-on 3ce93a08bf Merge branch 'master' of https://git.pupes.org/PoliEcho/sint-gauntlet 2026-04-24 14:59:55 +02:00
Tom-on 9d87c0748b Added Oscillator 2026-04-24 14:59:52 +02:00
PoliEcho 63b977f937 init_adc 2026-04-24 14:58:29 +02:00
18 changed files with 548 additions and 136 deletions
+7 -17
View File
@@ -1,28 +1,18 @@
{ {
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Cortex Debug", "name": "Cortex Debug (Pico 2W / RP2350)",
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"executable": "${command:cmake.launchTargetPath}", "executable": "${workspaceRoot}/build/sint-gauntlet.elf",
"request": "launch", "request": "launch",
"type": "cortex-debug", "type": "cortex-debug",
"servertype": "openocd", "servertype": "external",
"gdbPath": "gdb-multiarch", "gdbPath": "arm-none-eabi-gdb",
"serverArgs": [ "gdbTarget": "localhost:3333",
"device": "RP2350",
], "svdFile": "${env:PICO_SDK_PATH}/src/rp2350/hardware_regs/rp2350.svd",
"device": "RP2040",
"configFiles": [
"interface/raspberrypi-swd.cfg",
"target/rp2040.cfg"
],
"svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
"runToEntryPoint": "main", "runToEntryPoint": "main",
// Give restart the same functionality as runToEntryPoint - main
"postRestartCommands": [ "postRestartCommands": [
"break main", "break main",
"continue" "continue"
+19 -4
View File
@@ -2,8 +2,8 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 23)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 23)
# Initialise pico_sdk from installed location # Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc) # (note this can come from environment, CMake cache etc)
@@ -25,7 +25,9 @@ pico_sdk_init()
# Add executable. Default name is the project name, version 0.1 # Add executable. Default name is the project name, version 0.1
add_executable(sint-gauntlet main.cc vco.c mux.c) file(GLOB_RECURSE DAISYSP_SOURCES "${CMAKE_CURRENT_LIST_DIR}/daisysp/**/*.cpp")
add_executable(sint-gauntlet ${DAISYSP_SOURCES} main.c input.c state.c pwm.c synth.cc)
pico_set_program_name(sint-gauntlet "sint-gauntlet") pico_set_program_name(sint-gauntlet "sint-gauntlet")
pico_set_program_version(sint-gauntlet "0.1") pico_set_program_version(sint-gauntlet "0.1")
@@ -40,19 +42,32 @@ target_link_libraries(sint-gauntlet
# Add the standard include files to the build # Add the standard include files to the build
target_include_directories(sint-gauntlet PRIVATE target_include_directories(sint-gauntlet PRIVATE
${CMAKE_CURRENT_LIST_DIR}/daisysp ${CMAKE_CURRENT_LIST_DIR}/daisysp
${CMAKE_CURRENT_LIST_DIR}/daisysp/Control
${CMAKE_CURRENT_LIST_DIR}/daisysp/Drums
${CMAKE_CURRENT_LIST_DIR}/daisysp/Dynamics
${CMAKE_CURRENT_LIST_DIR}/daisysp/Effects
${CMAKE_CURRENT_LIST_DIR}/daisysp/Filters
${CMAKE_CURRENT_LIST_DIR}/daisysp/Noise
${CMAKE_CURRENT_LIST_DIR}/daisysp/PhysicalModeling
${CMAKE_CURRENT_LIST_DIR}/daisysp/Sampling
${CMAKE_CURRENT_LIST_DIR}/daisysp/Synthesis
${CMAKE_CURRENT_LIST_DIR}/daisysp/Utility
${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required ${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
) )
# Add any user requested libraries # Add any user requested libraries
target_link_libraries(sint-gauntlet target_link_libraries(sint-gauntlet
pico_stdlib
pico_cyw43_arch_none
hardware_pio hardware_pio
hardware_interp hardware_interp
hardware_timer hardware_timer
hardware_clocks hardware_clocks
hardware_sync
hardware_pwm hardware_pwm
hardware_adc hardware_adc
pico_multicore
) )
pico_add_extra_outputs(sint-gauntlet) pico_add_extra_outputs(sint-gauntlet)
+4
View File
File diff suppressed because one or more lines are too long
Executable
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
DISK_ID=usb-RPI_RP2350_DD85828F2371B53B-0:0
#DISK_ID=usb-RPI_RP2350_6F361FE334DD320F-0:0
TARGET=sint-gauntlet.uf2
cd ./build
cmake ..
make -j
sudo mount "/dev/disk/by-id/$DISK_ID-part1" /mnt
sudo cp $TARGET /mnt
sync
+32 -7
View File
@@ -1,18 +1,43 @@
#pragma once #pragma once
#define MUX0 26
#define MUX1 27
#define MUX_S0 2 #define MUX_S0 2
#define MUX_S1 3 #define MUX_S1 3
#define MUX_S2 4 #define MUX_S2 4
#define MUX0 26 #define BUTTON_BASE 6
#define MUX1 27 #define BUTTON_COUNT 4
#define VCO_BUTTON 6 #define AUDIO_OUT 0
#define QUANT_BUTTON 7
#define AMEN_BUTTON 8
#define AUDIO_OUTPUT 0
#define STATUS_LED 1 #define STATUS_LED 1
#define SAMPLE_RATE 44100.0f #define SAMPLE_RATE 44100.0f
#define BPM_MIN 30.0f
#define BPM_MAX 300.0f
#define VCO_FREQ_MIN 40.0f
#define VCO_FREQ_MAX 3200.0f
#define VCO_VOLUME_MIN 0.0f
#define VCO_VOLUME_MAX 1.0f
#define FILTER_FREQ_MIN 20.0f
#define FILTER_FREQ_MAX 20000.0f
#define FILTER_RES_MIN 0.0f
#define FILTER_RES_MAX 1.0f
#define ENV_ATTACK_MIN 0.001f // 1ms
#define ENV_ATTACK_MAX 10.0f // 10s
#define ENV_RELEASE_MIN 0.001f // 1ms
#define ENV_RELEASE_MAX 10.0f // 10s
#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
+72
View File
@@ -0,0 +1,72 @@
#include <hardware/adc.h>
#include <hardware/gpio.h>
#include <math.h>
#include <pico/stdlib.h>
#include <pico/time.h>
#include <stdint.h>
#include <sys/types.h>
#include "const.h"
#include "input.h"
bool is_toggle[BUTTON_COUNT] = {false};
bool btn_prev[BUTTON_COUNT] = {false};
void set_mux_addr(uint8_t addr) {
gpio_put(MUX_S0, addr & 1);
gpio_put(MUX_S1, (addr >> 1) & 1);
gpio_put(MUX_S2, (addr >> 2) & 1);
}
void update_pot(input_t *input) {
static volatile uint function_call_counter = 0;
function_call_counter++;
static uint8_t i = 0;
for (; i < 2; i++, adc_select_input(i)) {
{
static uint8_t j = 0;
for (; j < 8;) {
set_mux_addr(j);
sleep_ms(5); // Let multiplexers multiplex (5ms smallest reliable delay)
float old_val = input->pots[j + i * 8];
float new_val = (float)adc_read() / 4096.0f;
if (!(new_val > 0.99f) && (fabs(new_val - old_val) >= 0.01f)) {
input->pots[j + i * 8] = new_val;
}
j++;
return;
}
j = 0;
}
}
i = 0;
adc_select_input(i);
sleep_ms(5);
update_pot(input); // dont skip the tick
}
void update_inputs(input_t *input) {
// Pots
update_pot(input);
__asm__("nop");
// Buttons
for (uint8_t i = 0; i < BUTTON_COUNT; i++) {
bool btn_curr = gpio_get(BUTTON_BASE + i);
if (btn_curr == true && btn_prev[i] == false) {
if (is_toggle[i])
input->buttons[i] = !input->buttons[i];
}
if (!is_toggle[i])
input->buttons[i] = btn_curr;
btn_prev[i] = btn_curr;
}
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <sys/types.h>
typedef struct {
float pots[16];
bool buttons[4];
} input_t;
extern bool is_toggle[4];
static inline void set_toggle_button(uint8_t index, bool toggle) { is_toggle[index] = toggle; }
void update_inputs(input_t* input);
+130
View File
@@ -0,0 +1,130 @@
#include "pico/cyw43_arch.h"
#include <arm_acle.h>
#include <hardware/irq.h>
#include <hardware/sync.h>
#include <pico/stdio.h>
#include <pico/time.h>
#include <stdint.h>
#include <stdio.h>
#include <stdnoreturn.h>
#include <sys/types.h>
#include "hardware/gpio.h"
#include "hardware/pwm.h"
#include "hardware/adc.h"
#include "pico/multicore.h"
#include "pico/stdlib.h"
#include "const.h"
#include "macro.h"
#include "input.h"
#include "state.h"
#include "synth.h"
#include "pwm.h"
input_t input;
state_t state;
void core0_init(void) {
// PWM bullshit
gpio_set_function(AUDIO_OUT, GPIO_FUNC_PWM);
uint slice = pwm_gpio_to_slice_num(AUDIO_OUT);
pwm_config cfg = pwm_get_default_config();
pwm_config_set_wrap(&cfg, 3400);
pwm_init(slice, &cfg, true);
pwm_clear_irq(slice);
pwm_set_irq_enabled(slice, true);
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm_isr);
irq_set_enabled(PWM_IRQ_WRAP, true);
puts("PWM Initialized.");
// Synth
synth_init(&state);
puts("Synth Initialized.");
}
void core1_init(void) {
// GPIO
const uint8_t out_gpio[] = { MUX_S0, MUX_S1, MUX_S2, STATUS_LED };
const uint8_t adc_gpio[] = {MUX0,MUX1};
for (uint8_t i = 0; i < ARRAY_LENGTH(out_gpio); i++) {
gpio_init(out_gpio[i]);
gpio_set_dir(out_gpio[i], true);
}
for (uint8_t i = 0; i < BUTTON_COUNT; i++) {
gpio_init(BUTTON_BASE + i);
gpio_set_dir(BUTTON_BASE + 1, false);
}
adc_init();
adc_gpio_init(MUX0);
adc_gpio_init(MUX1);
puts("GPIO Initialized.");
// Input
set_toggle_button(0, true);
set_toggle_button(1, false);
set_toggle_button(2, true);
}
void debug_print(void) {
printf("\x1b[H\x1b[J");
printf("0: %f, 1: %f, 2: %f, 3: %f, 4: %f, 5: %f, 6: %f, 7: %f\n",
input.pots[0], input.pots[1], input.pots[2], input.pots[3],
input.pots[4], input.pots[5], input.pots[6], input.pots[7]);
printf(
"vco_freq: %f\n"
"vco_volume: %f\n"
"filter_freq: %f\n"
"filter_resonance: %f\n"
"clock_bpm: %f\n"
"env1_attack: %f\n"
"env1_decay: %f\n"
"env2_attack: %f\n"
"env2_decay: %f\n"
"reverb_amount: %f\n",
state.vco_freq,
state.vco_volume,
state.filter_freq,
state.filter_resonance,
state.clock_bpm,
state.env1_attack,
state.env1_decay,
state.env2_attack,
state.env2_decay,
state.reverb_amount
);
}
noreturn void core1_loop(void) {
while (1) {
update_inputs(&input);
update_state(&state, &input);
sleep_ms(1);
}
}
noreturn void core0_loop(void) {
while (1) __wfi();
}
int main() {
stdio_init_all();
if (cyw43_arch_init())
return -1;
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1); // sign of life
core1_init();
core0_init();
multicore_launch_core1(core1_loop);
core0_loop();
}
-47
View File
@@ -1,47 +0,0 @@
#include "macro.h"
#include "pico/stdlib.h"
#include <hardware/gpio.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "const.h"
#include "hardware/pwm.h"
#include "hardware/adc.h"
#include "state.h"
#include "daisysp.h"
daisysp::Oscillator osc;
daisysp::Svf filter;
state_t state;
void init_all() {
stdio_init_all();
puts("Starting PIN initialization");
const uint8_t out_gpio[] = {MUX_S0,MUX_S1,MUX_S2, STATUS_LED};
const uint8_t in_gpio[] = {VCO_BUTTON,QUANT_BUTTON,AMEN_BUTTON};
const uint8_t adc_gpio[] = {MUX0,MUX1};
gpio_set_function(AUDIO_OUTPUT, GPIO_FUNC_PWM);
for (uint8_t i=0; i < ARRAY_LENGTH(out_gpio); i++) {
gpio_init(out_gpio[i]);
gpio_set_dir(out_gpio[i], true);
}
for (uint8_t i=0; i < ARRAY_LENGTH(in_gpio); i++) {
gpio_init(in_gpio[i]);
gpio_set_dir(in_gpio[i], false);
}
for (uint8_t i=0; i < ARRAY_LENGTH(adc_gpio); i++) {
adc_gpio_init(adc_gpio[i]);
adc_select_input(i);
}
}
__attribute__((noreturn)) int main() {
init_all();
}
-19
View File
@@ -1,19 +0,0 @@
#include "const.h"
#include <stdint.h>
#include <hardware/gpio.h>
void set_mux_addr(uint8_t addr) {
gpio_put(MUX_S0, addr & 1);
gpio_put(MUX_S1, (addr >> 1) & 1);
gpio_put(MUX_S2, (addr >> 2) & 1);
}
float read_value_from_mux() {
return 0.0f;
}
void update_inputs() {
for(uint8_t i = 0; i < 2; i++) {
}
}
+21
View File
@@ -0,0 +1,21 @@
#include <hardware/pwm.h>
#include <pico/types.h>
#include "const.h"
#include "synth.h"
#include "pwm.h"
void pwm_isr(void) {
static uint slice = -1, chan = -1;
if (slice == -1) slice = pwm_gpio_to_slice_num(AUDIO_OUT);
if (chan == -1) chan = pwm_gpio_to_channel(AUDIO_OUT);
pwm_clear_irq(slice);
float sample = get_sample();
uint16_t level = (uint16_t)((sample + 1.0f) * 0.5f * 3400.0f);
pwm_set_chan_level(slice, chan, level);
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
void pwm_isr(void);
+45
View File
@@ -0,0 +1,45 @@
#include "const.h"
#include "input.h"
#include "state.h"
float quantize(float freq) {
if (freq <= 0.0f) return 0.0f;
float midi = 69.0f + 12.0f * log2f(freq / 440.0f);
return 440.0f * powf(2.0f, (roundf(midi) - 69.0f) / 12.0f);
}
void update_state(state_t* state, input_t* input) {
state->vco_freq = map_exponential(input->pots[0], VCO_FREQ_MIN, VCO_FREQ_MAX);
state->vco_volume = map_exponential(input->pots[1], VCO_VOLUME_MIN, VCO_VOLUME_MAX);
state->filter_freq = map_exponential(input->pots[2], FILTER_FREQ_MIN, FILTER_FREQ_MAX);
state->filter_resonance = map_linear(input->pots[3], FILTER_RES_MIN, FILTER_RES_MAX);
state->clock_bpm = map_linear(input->pots[4], BPM_MIN, BPM_MAX);
state->env1_attack = map_linear(input->pots[5], ENV_ATTACK_MIN, ENV_ATTACK_MAX);
state->env1_decay = map_linear(input->pots[6], ENV_RELEASE_MIN, ENV_RELEASE_MAX);
state->env2_attack = map_linear(input->pots[7], ENV_ATTACK_MIN, ENV_ATTACK_MAX);
state->env2_decay = map_linear(input->pots[8], ENV_RELEASE_MIN, ENV_RELEASE_MAX);
state->reverb_amount = map_linear(input->pots[9], REVERB_AMOUNT_MIN, REVERB_AMOUNT_MAX);
static bool pressed = false;
if (!pressed && input->buttons[0]) {
state->vco_mode = (vco_mode_t)((state->vco_mode + 1) % 4);
pressed = true;
} else pressed = false;
if (input->buttons[1]) {
if (state->vco_freq <= 0.0f) state->vco_freq = 0.0f;
else state->vco_freq = quantize(state->vco_freq);
}
state->amen_enabled = input->buttons[2];
//state->amen_enabled = true;
state->beat_samples = SAMPLE_RATE * 60.0f / state->clock_bpm;
state->playback_rate = state->clock_bpm / AMEN_BPM;
state->clock_inc = state->clock_bpm / 60.0f / SAMPLE_RATE;
state->amen_inc_fp = (uint32_t)(state->playback_rate * 65536.0f);
}
+30 -6
View File
@@ -1,24 +1,48 @@
#pragma once #pragma once
#include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include "input.h"
#include "vco.h" #include "vco.h"
typedef struct { typedef struct {
float clock_bpm; float clock_bpm;
float vco_freq; float vco_freq;
vco_mode_t vco_mode;
float vco_volume; float vco_volume;
bool quant_enabled; vco_mode_t vco_mode;
float filter_freq; float filter_freq;
float filter_resonance; float filter_resonance;
float env1_attack; float env1_attack;
float env1_release; float env1_decay;
float env2_attack; float env2_attack;
float env2_release; float env2_decay;
float reverb_amount; float reverb_amount;
bool quant_enabled;
bool amen_enabled; bool amen_enabled;
float beat_samples;
float playback_rate;
float clock_inc;
uint32_t amen_inc_fp;
} state_t; } state_t;
extern state_t state; static inline float map_linear(float v, float min, float max) {
return min + v * (max - min);
}
static inline float map_exponential(float v, float min, float max) {
if (min == 0.0f) min = 1e-6f;
return min * powf(max / min, v);
}
static inline float map_squared(float v, float min, float max) {
return min + (v * v) * (max - min);
}
static inline float max_constant(float _0, float val, float _1) {
return val;
}
void update_state(state_t* state, input_t* input);
+116
View File
@@ -0,0 +1,116 @@
#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();
// make it emit only continuous tone
// float vco_env_out = 1.0f;
// float filter_env_out = 0.0f;
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;
}
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include "state.h"
#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
extern "C" {
#endif
void synth_init(state_t* state);
float get_sample(void);
#ifdef __cplusplus
}
#endif
-15
View File
@@ -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;
}
-2
View File
@@ -7,5 +7,3 @@ typedef enum {
VCO_SAW = 3, VCO_SAW = 3,
} vco_mode_t; } vco_mode_t;
float vco(void);