From 561dece0287293235bfc06016dd64a2d2a7ee0d3 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Mon, 24 Jun 2024 10:58:31 +0300 Subject: [PATCH] windows build, separation of synth code, 3-op now, modulator feedback --- Source/Instruments/Trojka/readme.md | 2 + Source/Instruments/Trojka/trojka.c | 56 +++++++++++++++++ Source/Maker/Build/stfu-maker.exe | Bin 0 -> 154112 bytes Source/Maker/Build/windows-clang.bat | 1 + Source/Maker/main.c | 86 +++++++++------------------ Source/config.h | 27 ++++++++- Source/envelope.c | 8 ++- Source/interp.c | 4 ++ Source/oscillators.c | 7 ++- Source/phaser.c | 5 ++ Source/timer.c | 5 ++ 11 files changed, 139 insertions(+), 62 deletions(-) create mode 100644 Source/Instruments/Trojka/readme.md create mode 100644 Source/Instruments/Trojka/trojka.c create mode 100644 Source/Maker/Build/stfu-maker.exe create mode 100644 Source/Maker/Build/windows-clang.bat diff --git a/Source/Instruments/Trojka/readme.md b/Source/Instruments/Trojka/readme.md new file mode 100644 index 0000000..82ff5e0 --- /dev/null +++ b/Source/Instruments/Trojka/readme.md @@ -0,0 +1,2 @@ +# Trojka +3-op minimalist FM synth to the mega! diff --git a/Source/Instruments/Trojka/trojka.c b/Source/Instruments/Trojka/trojka.c new file mode 100644 index 0000000..fda1bc7 --- /dev/null +++ b/Source/Instruments/Trojka/trojka.c @@ -0,0 +1,56 @@ +#if defined(STFU_MAIN) && !defined(STFU_TROJKA) +#define STFU_TROJKA + +#include "../../phaser.c" +#include "../../envelope.c" +#include "../../config.h" + +#define STFU_TROJKA_OP_COUNT 3 + +/* https://multimed.org/student/eim/en/04-FM.pdf */ + +// todo: A few more algorithm configurations. +// todo: Other oscillators. + +struct stfu_trojka { + struct stfu_phaser phasers[STFU_TROJKA_OP_COUNT]; + struct stfu_envelope envelopes[STFU_TROJKA_OP_COUNT]; + float gains[STFU_TROJKA_OP_COUNT]; + float freq_scales[STFU_TROJKA_OP_COUNT]; + float key_frequency; + float feedback_gain; // todo: Separate gain for channels? + float left_feedback, right_feedback; +}; + +static struct stfu_trojka stfu_sample_trojka(struct stfu_trojka synth, float buffer[static 2]) { + for (int i = 0; i < STFU_TROJKA_OP_COUNT; ++i) { + synth.phasers[i] = stfu_pump_phaser(synth.phasers[i]); + synth.envelopes[i] = stfu_pump_envelope(synth.envelopes[i]); + } + + float left_modulator_stack = synth.envelopes[1].v * sinf(synth.phasers[1].v + synth.envelopes[0].v * sinf(synth.phasers[0].v)) + synth.left_feedback * synth.feedback_gain; + float right_modulator_stack = synth.envelopes[1].v * sinf(synth.phasers[1].v + synth.envelopes[0].v * sinf(synth.phasers[0].v)) + synth.right_feedback * synth.feedback_gain; + + synth.left_feedback = left_modulator_stack; + synth.right_feedback = right_modulator_stack; + + float left = synth.envelopes[2].v * sinf(synth.phasers[2].v + left_modulator_stack); + float right = + synth.envelopes[2].v * sinf(synth.phasers[2].v + right_modulator_stack); + + buffer[0] = left; + buffer[1] = right; + + return synth; +} + +static struct stfu_trojka stfu_press_trojka(struct stfu_trojka synth, float key_frequency) { + for (int i = 0; i < STFU_TROJKA_OP_COUNT; ++i) { + synth.phasers[i] = stfu_set_phaser_frequency(synth.phasers[i], key_frequency * synth.freq_scales[i]); + synth.envelopes[i] = stfu_trigger_envelope(synth.envelopes[i]); + } + + return synth; +} + +#endif diff --git a/Source/Maker/Build/stfu-maker.exe b/Source/Maker/Build/stfu-maker.exe new file mode 100644 index 0000000000000000000000000000000000000000..1ab8eb787b8c1fe621719e5ee1ff93fb9d4e7467 GIT binary patch literal 154112 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 #define SOKOL_IMPL -#define SOKOL_GLCORE #include "sokol_app.h" #include "sokol_audio.h" #include "sokol_log.h" +#define STFU_MAIN #include "../config.h" #include "../envelope.c" -// #include "../interp.c" #include "../oscillators.c" #include "../phaser.c" -static struct stfu_sinewave sine0; -static struct stfu_phaser phaser0; -static struct stfu_phaser phaser1; -static struct stfu_phaser phaser2; -static struct stfu_envelope envelope; +#include "../Instruments/Trojka/trojka.c" -static float key_frequency = STFU_C4_FREQUENCY; +static struct stfu_trojka synth = {0}; +// todo: Separate to playback.c, generic for Player and Maker #define CROSSFADE_RING_RANGE \ (STFU_CROSSFADE_BUFFER_FRAMES * STFU_AUDIO_CHANNEL_COUNT) static float crossfade_ring[CROSSFADE_RING_RANGE] = {0}; static size_t crossfade_ring_needle = 0; static unsigned int crossfade_frames_left = 0; -static void sample(float buffer[static 2]) { - phaser0 = stfu_pump_phaser(phaser0); - phaser1 = stfu_pump_phaser(phaser1); - phaser2 = stfu_pump_phaser(phaser2); - envelope = stfu_pump_envelope(envelope); - - float left = envelope.v * sinf(phaser2.v + sinf(phaser0.v + sinf(phaser1.v))); - float right = - envelope.v * sinf(phaser2.v + sinf(phaser0.v + sinf(phaser1.v))); - - buffer[0] = left; - buffer[1] = right; -} - static void stream(float *buffer, int num_frames, int num_channels) { /* Fade away */ for (size_t i = 0; crossfade_frames_left > 0; @@ -58,7 +40,7 @@ static void stream(float *buffer, int num_frames, int num_channels) { buffer[0] = crossfade_ring[crossfade_ring_needle % CROSSFADE_RING_RANGE]; buffer[1] = crossfade_ring[(crossfade_ring_needle + 1) % CROSSFADE_RING_RANGE]; - sample(&crossfade_ring[crossfade_ring_needle % CROSSFADE_RING_RANGE]); + synth = stfu_sample_trojka(synth, &crossfade_ring[crossfade_ring_needle % CROSSFADE_RING_RANGE]); buffer = &buffer[2]; crossfade_ring_needle += 2; } @@ -71,15 +53,19 @@ static void init(void) { // .stream_cb = stream, }); - // sine0 = stfu_init_sinewave(STFU_A4_FREQUENCY / 2.0f, 0.0f, 0.8f); - phaser0 = stfu_init_phaser(key_frequency); - phaser1 = stfu_init_phaser(key_frequency * 0.25); - phaser2 = stfu_init_phaser(key_frequency * 2.0); - envelope = stfu_init_envelope( - (struct stfu_envelope_point[]){[0] = {.dur = 0.02, .vol = 1.0}, - [1] = {.dur = 0.5, .vol = 0.33}, - [2] = {.dur = 1.0, .vol = 0}}, - 3); + synth.phasers[0] = stfu_init_phaser(220); + synth.phasers[1] = stfu_init_phaser(220 * 0.25); + synth.phasers[2] = stfu_init_phaser(220 * 2.0); + synth.feedback_gain = 0.25; + for (int i = 0; i < STFU_TROJKA_OP_COUNT; ++i) { + synth.envelopes[i] = stfu_init_envelope( + (struct stfu_envelope_point[]){[0] = {.dur = 0.02, .vol = 1.0}, + [1] = {.dur = 0.5, .vol = 0.33}, + [2] = {.dur = 1.0, .vol = 0}}, + 3); + synth.gains[i] = 1.0; + synth.freq_scales[i] = 1.0; + } } static void cleanup(void) { saudio_shutdown(); } @@ -92,53 +78,38 @@ static void event(const sapp_event *e) { switch (e->key_code) { case SAPP_KEYCODE_Z: - key_frequency = STFU_C4_FREQUENCY; - break; + synth = stfu_press_trojka(synth, STFU_SCALE[0]); case SAPP_KEYCODE_X: - key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[1]); break; case SAPP_KEYCODE_C: - key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * - STFU_NOTE_UPSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[2]); break; case SAPP_KEYCODE_V: - key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * - STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[3]); break; case SAPP_KEYCODE_B: - key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * - STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR * - STFU_NOTE_UPSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[4]); break; case SAPP_KEYCODE_N: - key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * - STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR * - STFU_NOTE_DOWNSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[5]); break; case SAPP_KEYCODE_M: - key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * - STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[6]); break; case SAPP_KEYCODE_COMMA: - key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * - STFU_NOTE_DOWNSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[7]); break; case SAPP_KEYCODE_PERIOD: - key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR; + synth = stfu_press_trojka(synth, STFU_SCALE[8]); break; case SAPP_KEYCODE_SLASH: - key_frequency = STFU_A4_FREQUENCY; + synth = stfu_press_trojka(synth, STFU_SCALE[9]); break; default: break; } - phaser0 = stfu_set_phaser_frequency(phaser0, key_frequency); - phaser1 = stfu_set_phaser_frequency(phaser1, key_frequency * 0.25); - phaser2 = stfu_set_phaser_frequency(phaser2, key_frequency * 2.0); - envelope = stfu_trigger_envelope(envelope); - crossfade_frames_left = STFU_CROSSFADE_BUFFER_FRAMES; - break; } default: @@ -172,5 +143,6 @@ sapp_desc sokol_main(int argc, char *argv[]) { .gl_major_version = 2, .gl_minor_version = 0, // .swap_interval = 0, + .window_title = "stfu-maker", }; } diff --git a/Source/config.h b/Source/config.h index 84344e9..60af47c 100644 --- a/Source/config.h +++ b/Source/config.h @@ -1,3 +1,5 @@ +#if !defined(STFU_CONFIG) +#define STFU_CONFIG /* Determines output framerate, in times per second. */ #define STFU_AUDIO_FRAME_RATE 44100 @@ -10,6 +12,27 @@ /* Introduces delayed buffering for purposes of crossfading channels when notes * are retriggered, needed for filtering clicks */ -#define STFU_CROSSFADE_BUFFER_FRAMES 64 +#define STFU_CROSSFADE_BUFFER_FRAMES 32 -// todo: Array of precomputed note frequencies? +static const float STFU_SCALE[12] = { + STFU_C4_FREQUENCY, + STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR, + STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * + STFU_NOTE_UPSCALE_FACTOR, + STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * + STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR, + STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * + STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR * + STFU_NOTE_UPSCALE_FACTOR, + STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * + STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR * + STFU_NOTE_DOWNSCALE_FACTOR, + STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * + STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR, + STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * + STFU_NOTE_DOWNSCALE_FACTOR, + STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR, + STFU_A4_FREQUENCY, +}; + +#endif diff --git a/Source/envelope.c b/Source/envelope.c index 1c05c87..699d31e 100644 --- a/Source/envelope.c +++ b/Source/envelope.c @@ -1,3 +1,6 @@ +#if defined(STFU_MAIN) && !defined(STFU_ENVELOPE) +#define STFU_ENVELOPE + #include #include @@ -29,12 +32,13 @@ struct stfu_envelope { } struct stfu_envelope stfu_pump_envelope(struct stfu_envelope envelope) { - envelope.p += 1.0f / STFU_AUDIO_FRAME_RATE; float d = stfu_get_envelope_duration(envelope); if (envelope.p >= d) /* Needs retriggering after that point */ return envelope; + envelope.p += 1.0f / STFU_AUDIO_FRAME_RATE; + float p = 0.0f; for (uint8_t i = 0;; ++i) { float ends = p + envelope.pnts[i].dur; @@ -63,3 +67,5 @@ struct stfu_envelope stfu_trigger_envelope(struct stfu_envelope envelope) { envelope.v = 0.0f; return envelope; } + +#endif diff --git a/Source/interp.c b/Source/interp.c index dbe170a..2f81df7 100644 --- a/Source/interp.c +++ b/Source/interp.c @@ -1,4 +1,8 @@ +#if defined(STFU_MAIN) && !defined(STFU_INTERP) +#define STFU_INTERP float stfu_linear_interpolate(float x0, float y0, float x1, float y1, float n) { return (y0 * (x1 - n) + y1 * (n - x0)) / (x1 - x0); } + +#endif diff --git a/Source/oscillators.c b/Source/oscillators.c index 2fb2e4b..19f8726 100644 --- a/Source/oscillators.c +++ b/Source/oscillators.c @@ -1,10 +1,11 @@ +#if defined(STFU_MAIN) && !defined(STFU_OSCILLATORS) +#define STFU_OSCILLATORS + #include #include #include "config.h" -/* https://multimed.org/student/eim/en/04-FM.pdf */ - /* Intended to be executed offline with values then embedded in the binary. * By having usage of glibc sin and cos functions strictly offline it's easier * to have it freestanding @@ -76,3 +77,5 @@ struct stfu_sawtooth stfu_pump_sawtooth(struct stfu_sawtooth wave) { wave.v -= wave.a * 2.f; return wave; } + +#endif diff --git a/Source/phaser.c b/Source/phaser.c index 036c157..b4c0b7f 100644 --- a/Source/phaser.c +++ b/Source/phaser.c @@ -1,3 +1,6 @@ +#if defined(STFU_MAIN) && !defined(STFU_PHASER) +#define STFU_PHASER + #include #include "config.h" @@ -29,3 +32,5 @@ struct stfu_phaser stfu_set_phaser_frequency(struct stfu_phaser phaser, phaser.a = 2 * ((float)M_PI / (float)STFU_AUDIO_FRAME_RATE) * frequency; return phaser; } + +#endif diff --git a/Source/timer.c b/Source/timer.c index 78d609a..2111145 100644 --- a/Source/timer.c +++ b/Source/timer.c @@ -1,3 +1,6 @@ +#if defined(STFU_MAIN) && !defined(STFU_TIMER) +#define STFU_TIMER + #include #include "config.h" @@ -18,3 +21,5 @@ struct stfu_timer stfu_pump_timer(struct stfu_timer wave) { wave.v -= 1000; return wave; } + +#endif