https://gitlab.synchro.net/main/sbbs/-/commit/f13692ed01697574f95d9002
Modified Files:
src/doors/syncdoom/i_termmusic.c syncdoom.c src/doors/syncduke/syncduke_plat.c syncduke_stubs.c src/doors/termgfx/audio_mgr.c audio_mgr.h
Log Message:
doors: async music transcode (render off the game thread)
A first-play (cold-miss) track had to render MIDI->OPL PCM (~seconds) then encode
OGG inline, freezing the game during the level load (5-9s observed). termgfx now
offloads that to a worker thread: the door SUBMITs the raw MIDI/MUS bytes and POLLs each frame; the game keeps running and the track fades in when ready. Cache
hits still play instantly on the main thread.
- termgfx (audio_mgr.c/.h): termgfx_audio_music_async_submit/_poll. The worker
renders + encodes + writes the disk cache + pre-builds the C;S upload APC, so
the main thread only memcpy-stages ready-to-send bytes (out_flush drains them
over frames) and starts the loop. Latest-wins supersede via a generation token;
worker created lazily, joined on destroy. POSIX threads; Windows keeps the
synchronous path (no regression).
- SyncDuke: PlayMusic -> submit (syncduke_stubs.c), poll in _handle_events
(syncduke_plat.c). SyncDOOM: term_emit -> submit (i_termmusic.c), poll in
DG_DrawFrame (syncdoom.c).
Live: a ~7s SyncDOOM render and a ~5s SyncDuke render each ran fully in the background at sustained fps with no frame-stall, and the worker populated the disk
cache so replays are instant. Standalone harness (submit/ship, supersede, clean destroy) passes; helgrind clean (0 races).
Co-Authored-By: Claude Opus 4.8 <
noreply@anthropic.com>
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net