// This file is part of the 64k demo project. // It tests the SilentBackend for audio testing without hardware. // Verifies audio.cc functionality using silent backend. #include "audio/audio.h" #include "audio/audio_engine.h" #include "audio/backend/silent_backend.h" #include "audio/synth.h" #include #include #if !defined(STRIP_ALL) // Test: SilentBackend initialization and lifecycle void test_silent_backend_lifecycle() { SilentBackend backend; assert(!backend.is_initialized()); assert(!backend.is_started()); backend.init(); assert(backend.is_initialized()); assert(!backend.is_started()); backend.start(); assert(backend.is_initialized()); assert(backend.is_started()); backend.shutdown(); assert(!backend.is_initialized()); assert(!backend.is_started()); printf("SilentBackend lifecycle test PASSED\n"); } // Test: Audio system with SilentBackend void test_audio_with_silent_backend() { SilentBackend backend; audio_set_backend(&backend); audio_init(); assert(backend.is_initialized()); audio_start(); assert(backend.is_started()); audio_shutdown(); assert(!backend.is_initialized()); printf("Audio with SilentBackend test PASSED\n"); } // Test: Peak control in SilentBackend void test_silent_backend_peak() { SilentBackend backend; audio_set_backend(&backend); audio_init(); // Default peak should be 0 assert(backend.get_realtime_peak() == 0.0f); assert(audio_get_realtime_peak() == 0.0f); // Set test peak backend.set_peak(0.75f); assert(backend.get_realtime_peak() == 0.75f); assert(audio_get_realtime_peak() == 0.75f); // Reset backend.set_peak(0.0f); assert(backend.get_realtime_peak() == 0.0f); audio_shutdown(); printf("SilentBackend peak control test PASSED\n"); } // Test: Frame and voice tracking void test_silent_backend_tracking() { SilentBackend backend; audio_set_backend(&backend); AudioEngine engine; engine.init(); // Initial state assert(backend.get_frames_rendered() == 0); assert(backend.get_voice_trigger_count() == 0); // Create a dummy spectrogram float data[DCT_SIZE * 2] = {0}; Spectrogram spec = {data, data, 2}; int id = synth_register_spectrogram(&spec); // Trigger a voice synth_trigger_voice(id, 0.8f, 0.0f); assert(backend.get_voice_trigger_count() == 1); // Render audio (calls on_frames_rendered) audio_render_ahead(0.0f, 0.1f); // Render ~0.1 seconds assert(backend.get_frames_rendered() > 0); // Reset stats backend.reset_stats(); assert(backend.get_frames_rendered() == 0); assert(backend.get_voice_trigger_count() == 0); engine.shutdown(); audio_shutdown(); printf("SilentBackend tracking test PASSED\n"); } // Test: Playback time with SilentBackend void test_audio_playback_time() { SilentBackend backend; audio_set_backend(&backend); AudioEngine engine; engine.init(); audio_start(); // Initial playback time should be 0 float t0 = audio_get_playback_time(); assert(t0 == 0.0f); // Render some audio audio_render_ahead(0.5f, 0.1f); // Advance music time to 0.5s // Playback time should advance based on frames rendered // Note: audio_get_playback_time() tracks cumulative frames consumed float t1 = audio_get_playback_time(); assert(t1 >= 0.0f); // Should have advanced // Render more audio_render_ahead(1.0f, 0.5f); float t2 = audio_get_playback_time(); assert(t2 >= t1); // Should continue advancing engine.shutdown(); audio_shutdown(); printf("Audio playback time test PASSED\n"); } // Test: Buffer management with partial writes void test_audio_buffer_partial_writes() { SilentBackend backend; audio_set_backend(&backend); AudioEngine engine; engine.init(); audio_start(); // Fill buffer multiple times to test wraparound // Note: With SilentBackend, frames_rendered won't increase because // there's no audio callback consuming from the ring buffer for (int i = 0; i < 10; ++i) { audio_render_ahead((float)i * 0.1f, 0.1f); } // Buffer should have handled multiple writes correctly (no crash) // We can't check frames_rendered with SilentBackend since there's // no audio callback to consume from the ring buffer audio_update(); // Should not crash engine.shutdown(); audio_shutdown(); printf("Audio buffer partial writes test PASSED\n"); } // Test: audio_update() with SilentBackend void test_audio_update() { SilentBackend backend; audio_set_backend(&backend); AudioEngine engine; engine.init(); audio_start(); // audio_update() should be callable without crashing audio_update(); audio_update(); audio_update(); engine.shutdown(); audio_shutdown(); printf("Audio update test PASSED\n"); } #endif /* !defined(STRIP_ALL) */ int main() { #if !defined(STRIP_ALL) printf("Running SilentBackend tests...\n"); test_silent_backend_lifecycle(); test_audio_with_silent_backend(); test_silent_backend_peak(); test_silent_backend_tracking(); test_audio_playback_time(); test_audio_buffer_partial_writes(); test_audio_update(); printf("All SilentBackend tests PASSED\n"); return 0; #else printf("SilentBackend tests skipped (STRIP_ALL enabled)\n"); return 0; #endif /* !defined(STRIP_ALL) */ }