diff --git a/Source/Instruments/Trojka/trojka.c b/Source/Instruments/Trojka/trojka.c index fda1bc7..ee2caae 100644 --- a/Source/Instruments/Trojka/trojka.c +++ b/Source/Instruments/Trojka/trojka.c @@ -15,8 +15,9 @@ 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 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; @@ -28,8 +29,8 @@ static struct stfu_trojka stfu_sample_trojka(struct stfu_trojka synth, float buf 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; + 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; diff --git a/Source/Maker/Build/stfu-maker.exe b/Source/Maker/Build/stfu-maker.exe index 1ab8eb7..6a8aa9a 100644 Binary files a/Source/Maker/Build/stfu-maker.exe and b/Source/Maker/Build/stfu-maker.exe differ diff --git a/Source/Maker/main.c b/Source/Maker/main.c index e196977..d116fc8 100644 --- a/Source/Maker/main.c +++ b/Source/Maker/main.c @@ -24,6 +24,9 @@ static float crossfade_ring[CROSSFADE_RING_RANGE] = {0}; static size_t crossfade_ring_needle = 0; static unsigned int crossfade_frames_left = 0; +// 1.0 is with A at 440 +static float octave = 0.5; + static void stream(float *buffer, int num_frames, int num_channels) { /* Fade away */ for (size_t i = 0; crossfade_frames_left > 0; @@ -53,10 +56,15 @@ static void init(void) { // .stream_cb = stream, }); - 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.freq_scales[0] = 1.0; + synth.freq_scales[1] = 0.25; + synth.freq_scales[2] = 2.0; + + synth.indices[0] = 2.0; + synth.indices[1] = 10.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}, @@ -64,7 +72,6 @@ static void init(void) { [2] = {.dur = 1.0, .vol = 0}}, 3); synth.gains[i] = 1.0; - synth.freq_scales[i] = 1.0; } } @@ -76,40 +83,103 @@ static void event(const sapp_event *e) { if (e->key_repeat) break; + bool key_was_pressed = false; + switch (e->key_code) { case SAPP_KEYCODE_Z: - synth = stfu_press_trojka(synth, STFU_SCALE[0]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[0] * octave); + break; case SAPP_KEYCODE_X: - synth = stfu_press_trojka(synth, STFU_SCALE[1]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[1] * octave); break; case SAPP_KEYCODE_C: - synth = stfu_press_trojka(synth, STFU_SCALE[2]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[2] * octave); break; case SAPP_KEYCODE_V: - synth = stfu_press_trojka(synth, STFU_SCALE[3]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[3] * octave); break; case SAPP_KEYCODE_B: - synth = stfu_press_trojka(synth, STFU_SCALE[4]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[4] * octave); break; case SAPP_KEYCODE_N: - synth = stfu_press_trojka(synth, STFU_SCALE[5]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[5] * octave); break; case SAPP_KEYCODE_M: - synth = stfu_press_trojka(synth, STFU_SCALE[6]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[6] * octave); break; case SAPP_KEYCODE_COMMA: - synth = stfu_press_trojka(synth, STFU_SCALE[7]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[7] * octave); break; case SAPP_KEYCODE_PERIOD: - synth = stfu_press_trojka(synth, STFU_SCALE[8]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[8] * octave); break; case SAPP_KEYCODE_SLASH: - synth = stfu_press_trojka(synth, STFU_SCALE[9]); + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[9] * octave); break; + + case SAPP_KEYCODE_A: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[0] * (octave * 2)); + break; + case SAPP_KEYCODE_S: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[1] * (octave * 2)); + break; + case SAPP_KEYCODE_D: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[2] * (octave * 2)); + break; + case SAPP_KEYCODE_F: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[3] * (octave * 2)); + break; + case SAPP_KEYCODE_G: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[4] * (octave * 2)); + break; + case SAPP_KEYCODE_H: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[5] * (octave * 2)); + break; + case SAPP_KEYCODE_J: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[6] * (octave * 2)); + break; + case SAPP_KEYCODE_K: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[7] * (octave * 2)); + break; + case SAPP_KEYCODE_L: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[8] * (octave * 2)); + break; + case SAPP_KEYCODE_SEMICOLON: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[9] * (octave * 2)); + break; + case SAPP_KEYCODE_APOSTROPHE: + key_was_pressed = true; + synth = stfu_press_trojka(synth, STFU_SCALE[10] * (octave * 2)); + break; + default: break; } + if (key_was_pressed) { + crossfade_frames_left = STFU_CROSSFADE_BUFFER_FRAMES; + } + break; } default: diff --git a/Source/config.h b/Source/config.h index 60af47c..2ded0a6 100644 --- a/Source/config.h +++ b/Source/config.h @@ -33,6 +33,8 @@ static const float STFU_SCALE[12] = { STFU_NOTE_DOWNSCALE_FACTOR, STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR, STFU_A4_FREQUENCY, + STFU_A4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR, + STFU_A4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR, }; #endif diff --git a/readme.md b/readme.md index c7270a5..149f671 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ # STFU ! SoundTracker Format Unirepo -Grassroot music format specifically designed for lofi game soundtracks with accent on binary efficiency in its various forms. +Grassroot music format specifically designed for reproducible lofi game soundtracks with accent on binary efficiency in its various forms. - Separation of Maker and Player binaries, with Player being absolutely dependency free. - Samples and instruments are stored outside of tracks in a shared data base allowing reuse.