diff options
Diffstat (limited to 'src/audio/audio.cc')
| -rw-r--r-- | src/audio/audio.cc | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/src/audio/audio.cc b/src/audio/audio.cc index d08a2fa..6ee9782 100644 --- a/src/audio/audio.cc +++ b/src/audio/audio.cc @@ -1,16 +1,35 @@ // 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. +// Now uses backend abstraction for testability. #include "audio.h" +#include "audio_backend.h" +#include "miniaudio_backend.h" +#include "synth.h" #include "util/asset_manager.h" #define MINIAUDIO_IMPLEMENTATION #include "miniaudio.h" -#include "synth.h" #include <stdio.h> +// Global backend pointer for audio abstraction +static AudioBackend* g_audio_backend = nullptr; +static MiniaudioBackend g_default_backend; +static bool g_using_default_backend = false; + +#if !defined(STRIP_ALL) +// Allow tests to inject a custom backend +void audio_set_backend(AudioBackend* backend) { + g_audio_backend = backend; +} + +// Get current backend (for tests) +AudioBackend* audio_get_backend() { + return g_audio_backend; +} +#endif /* !defined(STRIP_ALL) */ + int register_spec_asset(AssetId id) { size_t size; const uint8_t* data = GetAsset(id, &size); @@ -28,36 +47,24 @@ int register_spec_asset(AssetId id) { 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; + // Use default backend if none set + if (g_audio_backend == nullptr) { + g_audio_backend = &g_default_backend; + g_using_default_backend = true; } + + g_audio_backend->init(); } void audio_start() { - if (ma_device_start(&g_device) != MA_SUCCESS) { - printf("Failed to start playback device.\n"); - ma_device_uninit(&g_device); + if (g_audio_backend == nullptr) { + printf("Cannot start: audio not initialized.\n"); return; } + g_audio_backend->start(); } #if !defined(STRIP_ALL) @@ -72,6 +79,11 @@ void audio_render_silent(float duration_sec) { (total_frames > chunk_size) ? chunk_size : total_frames; synth_render(buffer, frames_to_render); total_frames -= frames_to_render; + + // Notify backend of frames rendered (for mock tracking) + if (g_audio_backend != nullptr) { + g_audio_backend->on_frames_rendered(frames_to_render); + } } } #endif /* !defined(STRIP_ALL) */ @@ -80,7 +92,14 @@ void audio_update() { } void audio_shutdown() { - ma_device_stop(&g_device); - ma_device_uninit(&g_device); + if (g_audio_backend != nullptr) { + g_audio_backend->shutdown(); + } synth_shutdown(); + + // Clear backend pointer if using default + if (g_using_default_backend) { + g_audio_backend = nullptr; + g_using_default_backend = false; + } } |
