diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-07 10:46:43 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-07 10:46:43 +0100 |
| commit | 0f79b532c886f338ab80d506d4b06048e1784056 (patch) | |
| tree | 28639cc355c91e294ced1dd1d3491b822c3e45b8 /src/main.cc | |
| parent | 858f9d5e765bfc8f8f13b38fa0fab790139a0740 (diff) | |
refactor(audio): Remove tempo logic from WavDumpBackend
Fixed design flaw where WavDumpBackend had hardcoded tempo curves
duplicating logic from main.cc. Backend should be passive and just
write audio data, not implement simulation logic.
Changes:
- WavDumpBackend.start() is now non-blocking (was blocking simulation loop)
- Added write_audio() method for passive audio writing
- Removed all tempo scaling logic from backend (lines 62-97)
- Removed tracker_update() and audio_render_ahead() calls from backend
- Removed set_duration() (no longer needed, frontend controls duration)
Frontend (main.cc):
- Added WAV dump mode loop that drives simulation with its own tempo logic
- Reads from ring buffer and calls wav_backend.write_audio()
- Tempo logic stays in one place (no duplication)
- Added ring_buffer.h include for AudioRingBuffer access
Test (test_wav_dump.cc):
- Updated to use frontend-driven approach
- Test manually drives simulation loop
- Calls write_audio() after each frame
- Verifies passive backend behavior
Design:
- Backend: Passive file writer (init/start/write_audio/shutdown)
- Frontend: Active simulation driver (tempo, tracker, rendering)
- Zero duplication of tempo/simulation logic
- Clean separation of concerns
All 27 tests pass.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/main.cc')
| -rw-r--r-- | src/main.cc | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/main.cc b/src/main.cc index 0fb0fb6..a3e4a69 100644 --- a/src/main.cc +++ b/src/main.cc @@ -6,10 +6,12 @@ #include "audio/audio.h" #include "audio/audio_engine.h" #include "audio/gen.h" +#include "audio/ring_buffer.h" #include "audio/synth.h" #include "audio/tracker.h" #if !defined(STRIP_ALL) #include "audio/wav_dump_backend.h" +#include <vector> #endif #include "generated/assets.h" // Include generated asset header #include "gpu/demo_effects.h" // For GetDemoDuration() @@ -163,8 +165,45 @@ int main(int argc, char** argv) { audio_start(); #if !defined(STRIP_ALL) - // In WAV dump mode, audio_start() renders everything and we can exit + // In WAV dump mode, run headless simulation and write audio to file if (dump_wav) { + printf("Running WAV dump simulation...\n"); + + const float demo_duration = GetDemoDuration(); + const float max_duration = (demo_duration > 0.0f) ? demo_duration : 60.0f; + const float update_dt = 1.0f / 60.0f; // 60Hz update rate + const int frames_per_update = (int)(32000 * update_dt); // ~533 frames + const int samples_per_update = frames_per_update * 2; // Stereo + + AudioRingBuffer* ring_buffer = audio_get_ring_buffer(); + std::vector<float> chunk_buffer(samples_per_update); + + double physical_time = 0.0; + while (physical_time < max_duration) { + // Update music time and tracker (using tempo logic from fill_audio_buffer) + fill_audio_buffer(physical_time); + + // Read rendered audio from ring buffer + if (ring_buffer != nullptr) { + ring_buffer->read(chunk_buffer.data(), samples_per_update); + } + + // Write to WAV file + wav_backend.write_audio(chunk_buffer.data(), samples_per_update); + + physical_time += update_dt; + + // Progress indicator every second + if ((int)physical_time % 1 == 0 && physical_time - update_dt < (int)physical_time) { + printf(" Rendering: %.1fs / %.1fs (music: %.1fs, tempo: %.2fx)\r", + physical_time, max_duration, g_music_time, g_tempo_scale); + fflush(stdout); + } + } + + printf("\nWAV dump complete: %.2fs physical, %.2fs music time\n", + physical_time, g_music_time); + audio_shutdown(); gpu_shutdown(); platform_shutdown(&platform_state); |
