// This file is part of the 64k demo project. // It manages the low-level audio device and high-level audio state. // Implementation uses miniaudio for cross-platform support. #include "audio.h" #include "util/asset_manager.h" #if !defined(DEMO_BUILD_TOOLS) #define MA_NO_FLAC #define MA_NO_ENCODING #define MA_NO_MP3 #define MA_NO_WAV #endif /* !defined(DEMO_BUILD_TOOLS) */ #define MINIAUDIO_IMPLEMENTATION #include "miniaudio.h" #include "synth.h" #include int register_spec_asset(AssetId id) { size_t size; const uint8_t* data = GetAsset(id, &size); if (!data || size < sizeof(SpecHeader)) return -1; const SpecHeader* header = (const SpecHeader*)data; const float* spectral_data = (const float*)(data + sizeof(SpecHeader)); Spectrogram spec; spec.spectral_data_a = spectral_data; spec.spectral_data_b = spectral_data; // No double-buffer for static assets spec.num_frames = header->num_frames; return synth_register_spectrogram(&spec); } static ma_device g_device; void audio_data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) { (void)pInput; float* fOutput = (float*)pOutput; synth_render(fOutput, (int)frameCount); } void audio_init() { synth_init(); ma_device_config config = ma_device_config_init(ma_device_type_playback); config.playback.format = ma_format_f32; config.playback.channels = 2; config.sampleRate = 32000; config.dataCallback = audio_data_callback; if (ma_device_init(NULL, &config, &g_device) != MA_SUCCESS) { printf("Failed to open playback device.\n"); return; } } void audio_start() { if (ma_device_start(&g_device) != MA_SUCCESS) { printf("Failed to start playback device.\n"); ma_device_uninit(&g_device); return; } } #if !defined(STRIP_ALL) void audio_render_silent(float duration_sec) { const int sample_rate = 32000; const int chunk_size = 512; int total_frames = (int)(duration_sec * sample_rate); float buffer[chunk_size * 2]; // Stereo while (total_frames > 0) { int frames_to_render = (total_frames > chunk_size) ? chunk_size : total_frames; synth_render(buffer, frames_to_render); total_frames -= frames_to_render; } } #endif /* !defined(STRIP_ALL) */ void audio_update() { } void audio_shutdown() { ma_device_stop(&g_device); ma_device_uninit(&g_device); synth_shutdown(); }