#include #define SOKOL_IMPL #define SOKOL_GLCORE #include "sokol_app.h" #include "sokol_audio.h" #include "sokol_log.h" #include "../config.h" #include "../oscillators.c" #include "../phaser.c" static struct stfu_sinewave sine0; static struct stfu_phaser phaser0; static struct stfu_phaser phaser1; 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); buffer[2 * i + 0] = sinf(phaser0.v + sinf(phaser1.v)); buffer[2 * i + 1] = 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); } 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); phaser1 = stfu_set_phaser_frequency(phaser1, key_frequency * 0.25); 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, }; }