#if defined(STFU_MAIN) && !defined(STFU_TROJKA) #define STFU_TROJKA #include "../../config.h" #include "../../envelope.c" #include "../../phaser.c" #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]; // todo: Combine with indices? float freq_scales[STFU_TROJKA_OP_COUNT]; float indices[STFU_TROJKA_OP_COUNT - 1]; /* 1 to 100 */ 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 * 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; float right_modulator_stack = left_modulator_stack; 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