2024-06-24 07:58:31 +00:00
|
|
|
#if defined(STFU_MAIN) && !defined(STFU_TROJKA)
|
|
|
|
#define STFU_TROJKA
|
|
|
|
|
|
|
|
#include "../../config.h"
|
2024-06-29 15:15:06 +00:00
|
|
|
#include "../../envelope.c"
|
|
|
|
#include "../../phaser.c"
|
2024-06-24 07:58:31 +00:00
|
|
|
|
|
|
|
#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];
|
2024-06-24 13:28:19 +00:00
|
|
|
float gains[STFU_TROJKA_OP_COUNT]; // todo: Combine with indices?
|
2024-06-24 07:58:31 +00:00
|
|
|
float freq_scales[STFU_TROJKA_OP_COUNT];
|
2024-06-24 13:28:19 +00:00
|
|
|
float indices[STFU_TROJKA_OP_COUNT - 1]; /* 1 to 100 */
|
2024-06-24 07:58:31 +00:00
|
|
|
float key_frequency;
|
|
|
|
float feedback_gain; // todo: Separate gain for channels?
|
|
|
|
float left_feedback, right_feedback;
|
|
|
|
};
|
|
|
|
|
2024-06-29 15:15:06 +00:00
|
|
|
static struct stfu_trojka stfu_sample_trojka(struct stfu_trojka synth,
|
|
|
|
float buffer[static 2]) {
|
2024-06-24 07:58:31 +00:00
|
|
|
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]);
|
|
|
|
}
|
|
|
|
|
2024-06-29 15:15:06 +00:00
|
|
|
float left_modulator_stack =
|
|
|
|
synth.envelopes[1].v * synth.indices[1] *
|
|
|
|
sinf(synth.phasers[1].v + synth.envelopes[0].v * synth.indices[0] *
|
|
|
|
sinf(synth.phasers[0].v)) +
|
|
|
|
synth.left_feedback * synth.feedback_gain;
|
2024-06-24 13:28:19 +00:00
|
|
|
float right_modulator_stack = left_modulator_stack;
|
2024-06-24 07:58:31 +00:00
|
|
|
|
|
|
|
synth.left_feedback = left_modulator_stack;
|
|
|
|
synth.right_feedback = right_modulator_stack;
|
|
|
|
|
2024-06-29 15:15:06 +00:00
|
|
|
float left =
|
|
|
|
synth.envelopes[2].v * sinf(synth.phasers[2].v + left_modulator_stack);
|
2024-06-24 07:58:31 +00:00
|
|
|
float right =
|
|
|
|
synth.envelopes[2].v * sinf(synth.phasers[2].v + right_modulator_stack);
|
|
|
|
|
|
|
|
buffer[0] = left;
|
|
|
|
buffer[1] = right;
|
|
|
|
|
|
|
|
return synth;
|
|
|
|
}
|
|
|
|
|
2024-06-29 15:15:06 +00:00
|
|
|
static struct stfu_trojka stfu_press_trojka(struct stfu_trojka synth,
|
|
|
|
float key_frequency) {
|
2024-06-24 07:58:31 +00:00
|
|
|
for (int i = 0; i < STFU_TROJKA_OP_COUNT; ++i) {
|
2024-06-29 15:15:06 +00:00
|
|
|
synth.phasers[i] = stfu_set_phaser_frequency(
|
|
|
|
synth.phasers[i], key_frequency * synth.freq_scales[i]);
|
2024-06-24 07:58:31 +00:00
|
|
|
synth.envelopes[i] = stfu_trigger_envelope(synth.envelopes[i]);
|
|
|
|
}
|
|
|
|
|
2024-06-29 15:15:06 +00:00
|
|
|
return synth;
|
2024-06-24 07:58:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|