#include #define SOKOL_IMPL #define SOKOL_GLCORE #include "sokol_app.h" #include "sokol_audio.h" #include "sokol_log.h" #include "../config.h" #include "../envelope.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; static float key_frequency = STFU_C4_FREQUENCY; static void stream(float *buffer, int num_frames, int num_channels) { for (int i = 0; i < num_frames; ++i) { // sine0 = stfu_pump_sinewave(sine0); // Carrier phaser0 = stfu_pump_phaser(phaser0); phaser1 = stfu_pump_phaser(phaser1); phaser2 = stfu_pump_phaser(phaser2); envelope = stfu_pump_envelope(envelope); buffer[2 * i + 0] = envelope.v * sinf(phaser2.v + sinf(phaser0.v + sinf(phaser1.v))); buffer[2 * i + 1] = envelope.v * sinf(phaser2.v + sinf(phaser0.v + sinf(phaser1.v))); } } static void init(void) { saudio_setup(&(saudio_desc){ .sample_rate = STFU_AUDIO_FRAME_RATE, .num_channels = STFU_AUDIO_CHANNEL_COUNT, // .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.5, .vol = 0.33}, [1] = {.dur = 1.0, .vol = 0}}, 2); } static void cleanup(void) { saudio_shutdown(); } static void event(const sapp_event *e) { switch (e->type) { case SAPP_EVENTTYPE_KEY_DOWN: { if (e->key_repeat) break; switch (e->key_code) { case SAPP_KEYCODE_Z: key_frequency = STFU_C4_FREQUENCY; break; case SAPP_KEYCODE_X: key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR; break; case SAPP_KEYCODE_C: key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR; break; case SAPP_KEYCODE_V: key_frequency = STFU_C4_FREQUENCY * STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR * STFU_NOTE_UPSCALE_FACTOR; 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; 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; break; case SAPP_KEYCODE_M: key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR; break; case SAPP_KEYCODE_COMMA: key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR * STFU_NOTE_DOWNSCALE_FACTOR; break; case SAPP_KEYCODE_PERIOD: key_frequency = STFU_A4_FREQUENCY * STFU_NOTE_DOWNSCALE_FACTOR; break; case SAPP_KEYCODE_SLASH: key_frequency = STFU_A4_FREQUENCY; break; default: break; } phaser0 = stfu_set_phaser_frequency(phaser0, key_frequency * 0.25); phaser1 = stfu_set_phaser_frequency(phaser1, key_frequency * 0.125); phaser2 = stfu_set_phaser_frequency(phaser2, key_frequency); envelope = stfu_trigger_envelope(envelope); break; } default: break; } } static void frame(void) { int frames = (int)(sapp_frame_duration() * (float)STFU_AUDIO_FRAME_RATE); int expected = saudio_expect(); frames = frames > expected ? expected : frames; // todo: Prevent drifting apart. static float buffer[STFU_AUDIO_FRAME_RATE * STFU_AUDIO_CHANNEL_COUNT]; while (frames > 0) { int now = frames > STFU_AUDIO_FRAME_RATE ? STFU_AUDIO_FRAME_RATE : frames; stream(buffer, now, STFU_AUDIO_CHANNEL_COUNT); saudio_push(buffer, now); frames -= now; } } sapp_desc sokol_main(int argc, char *argv[]) { return (sapp_desc){ .width = 640, .height = 480, .init_cb = init, .frame_cb = frame, .cleanup_cb = cleanup, .event_cb = event, .logger.func = slog_func, .gl_major_version = 2, .gl_minor_version = 0, // .swap_interval = 0, }; }