#include "audio/audio.h" #include "audio/synth.h" #include "gpu/gpu.h" #include "platform.h" #include "util/math.h" #include #include #define DEMO_BPM 120.0f #define SECONDS_PER_BEAT (60.0f / DEMO_BPM) #define SPEC_FRAMES 16 static float g_spec_buffer_a[SPEC_FRAMES * DCT_SIZE]; static float g_spec_buffer_b[SPEC_FRAMES * DCT_SIZE]; void generate_tone(float *buffer, float freq) { memset(buffer, 0, SPEC_FRAMES * DCT_SIZE * sizeof(float)); for (int frame = 0; frame < SPEC_FRAMES; ++frame) { float *spec_frame = buffer + frame * DCT_SIZE; float amplitude = powf(1.0f - (float)frame / SPEC_FRAMES, 2.0f); int bin = (int)(freq / (32000.0f / 2.0f) * DCT_SIZE); if (bin > 0 && bin < DCT_SIZE) { spec_frame[bin] = amplitude; } } } int main(int argc, char **argv) { bool fullscreen_enabled = false; #ifndef STRIP_ALL for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--fullscreen") == 0) { fullscreen_enabled = true; break; } } #else (void)argc; (void)argv; fullscreen_enabled = true; #endif platform_init_window(fullscreen_enabled); gpu_init(platform_get_window()); audio_init(); generate_tone(g_spec_buffer_a, 440.0f); // A4 generate_tone(g_spec_buffer_b, 0.0f); // A5 const Spectrogram spec = {g_spec_buffer_a, g_spec_buffer_b, SPEC_FRAMES}; int tone_id = synth_register_spectrogram(&spec); double last_beat_time = 0.0; int beat_count = 0; while (!platform_should_close()) { platform_poll(); double current_time = platform_get_time(); if (current_time - last_beat_time > SECONDS_PER_BEAT) { const float pan = (beat_count & 1) ? -.8 : .8; synth_trigger_voice(tone_id, 0.8f, pan); last_beat_time = current_time; beat_count++; if (beat_count % 4 == 0) { // Time to update the sound! float *back_buffer = synth_begin_update(tone_id); if (back_buffer) { generate_tone(back_buffer, (beat_count % 8) == 4 ? 220.0f : 480.f); // A3 synth_commit_update(tone_id); } } } gpu_draw(synth_get_output_peak()); audio_update(); } audio_shutdown(); gpu_shutdown(); platform_shutdown(); return 0; }