#include "kknd.h" /* ========================================================================= * audio.c - Procedural sound effects via SDL audio queue (no asset files). * ========================================================================= */ static SDL_AudioDeviceID g_dev = 0; static int g_audio_ok = 0; int audio_init(void) { SDL_AudioSpec want, have; memset(&want, 0, sizeof want); want.freq = 22050; want.format = AUDIO_S16SYS; want.channels = 1; want.samples = 1024; g_dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0); if (g_dev == 0) { return 0; } g_audio_ok = 1; SDL_PauseAudioDevice(g_dev, 0); return 1; } void audio_shutdown(void) { if (g_dev) SDL_CloseAudioDevice(g_dev); g_dev = 0; g_audio_ok = 0; } static void queue_tone(float freq, float dur, float vol, int kind) { if (!g_audio_ok) return; int n = (int)(22050 * dur); int16_t *buf = (int16_t *)calloc((size_t)n, sizeof(int16_t)); for (int i = 0; i < n; i++) { float t = (float)i / 22050.0f; float env = (kind == 0) ? (1.0f - t / dur) : 1.0f; float s = sinf(2*3.14159f*freq*t); if (kind == 1) s = (sinf(2*3.14159f*freq*t) + 0.3f*sinf(2*3.14159f*freq*2*t)); if (kind == 2) s = (sinf(2*3.14159f*freq*t) * (1.0f - t/dur)) ; buf[i] = (int16_t)(s * vol * 32767 * env); } SDL_QueueAudio(g_dev, buf, (Uint32)(n * sizeof(int16_t))); free(buf); } void audio_sfx(int id) { switch (id) { case 0: queue_tone(440, 0.08f, 0.25f, 0); break; /* move */ case 1: queue_tone(220, 0.06f, 0.30f, 1); break; /* shoot */ case 2: queue_tone(90, 0.35f, 0.45f, 2); break; /* boom */ case 3: queue_tone(660, 0.10f, 0.30f, 0); break; /* build */ case 4: queue_tone(880, 0.05f, 0.25f, 0); break; /* select */ case 5: queue_tone(140, 0.12f, 0.35f, 1); break; /* error */ default: break; } } void audio_music_start(void) { /* procedural drone; intentionally silent by default */ } void audio_music_stop(void) { /* no-op */ } /* simple looping wasteland bassline (procedural, no asset files) */ static float g_music_t = 0; static int g_music_step = 0; static const float g_bass[8] = { 110.0f, 0, 146.8f, 0, 130.8f, 0, 98.0f, 0 }; static const float g_mel[8] = { 0, 329.6f, 0, 392.0f, 0, 293.7f, 0, 261.6f }; void audio_music_tick(float dt) { if (!g_audio_ok) return; g_music_t += dt; const float step_dur = 0.40f; if (g_music_t < step_dur) return; g_music_t -= step_dur; int s = g_music_step % 8; if (g_bass[s] > 0) queue_tone(g_bass[s], step_dur * 0.95f, 0.10f, 2); if (g_mel[s] > 0) queue_tone(g_mel[s], step_dur * 0.55f, 0.045f, 0); g_music_step++; }