• src/doors/syncdoom/i_termsound.c src/doors/syncduke/Game/src/actors.c

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Sat Jul 4 20:14:28 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/2a84663b40f5bfa854195657
    Modified Files:
    src/doors/syncdoom/i_termsound.c src/doors/syncduke/Game/src/actors.c config.c duke3d.h sounds.c src/doors/syncduke/syncduke_stubs.c src/doors/termgfx/audio_mgr.c audio_mgr.h
    Log Message:
    doors: terminal-audio fidelity overhaul (SFX latency, ambiences, voices)

    One-shot SFX (termgfx, both doors):
    - The SFX channels are now a voice-stealing pool: flush the target channel
    before queuing so each holds at most one live sound. Un-flushed channel
    FIFOs backed up during firefights (30-45 SFX/sec into 8 channels) and
    played gunshots out seconds late -- audio "continued after the fight".
    - Channel choice is busy-aware: each queue records when its sample ends
    (exact PCM geometry for Doom lumps and VOC transcodes, WAV byte-rate
    otherwise) and new sounds take a finished channel, stealing the one
    closest to done only when all are live. Blind rotation truncated any
    long sample (rocket launch, chopper flyby) as soon as 8 later sounds
    arrived inside its play time; DOS mixed 32 voices and never hit this.
    - SyncDOOM coalesces same-sfx re-triggers within 40ms (SyncDuke's FX path
    already had a burst window); near-simultaneous duplicates are inaudible
    but each still cost a Load+Queue on the shared socket.
    - Both dispatch paths log a one-time warning when a sound sample is
    missing from the loaded GRP (content diagnosis, e.g. shareware).

    Looping ambiences (termgfx + the Duke engine's missing-callback seams --
    our headless shim has no audiolib voice-DONE callback, which the engine's
    sound bookkeeping silently relied on):
    - Queue loops ACTIVE (full volume) and set the real level via A;Volume:
    a positional ambience first heard at its radius edge is queued at
    volume 0, and SyncTERM never un-mutes such a voice (the E1L1 fire bin
    was permanently silent) -- works around that SyncTERM bug.
    - A full loop pool no longer steals a channel: loop_start reports failure
    and the MUSICANDSFX handler leaves the sprite un-triggered to retry
    when a channel frees, instead of stopping a loop the engine still
    thinks is playing (ambiences went permanently silent mid-session).
    - FX_StopAllSounds (menu, save-load, death) bumps a generation; the
    ambient handler re-arms once per generation -- zeroing the stale
    ambient play-counts globally, then each sprite's own trigger -- so a
    looping ambience resumes on return to the game (the projector stayed
    silent after ESC/menu or loading a save). The zeroing is deliberately
    once-per-generation: several sprites can share one lotag (E1L1 has 4x
    wind), and a per-sprite reset wiped a just-restarted loop's count,
    leaving it playing but untracked (never panned or attenuated).
    - stopenvsound now removes the exact SoundOwner entry it stopped;
    routing it through TestCallBack removed the first MUSICANDSFX owner it
    found, desyncing the owner list whenever sprites share a lotag, so an
    ambience refused to restart on radius re-entry.
    - Continuous soundm&2 ambiences (FIRE_CRACKLE, WIND_AMBIENCE, ...) now
    LOOP: DOS kept them going by re-firing one-shots from the DONE
    callback; looping the sample gives the same continuous result and puts
    them in the per-frame FX_Pan3D update, so they attenuate and pan with
    player movement like the original.
    - Multi-instance ambiences restored (up to 4, as DOS's SoundOwner[][4]):
    the single-instance guard now only covers true &1 loops, so a distant
    wind sprite can't hold the one instance and block a nearby one.
    - The ambient ON/OFF radius gate gets +1024 hysteresis so a tight-radius
    source (the cinema projector, ht=2000) doesn't flicker on/off as the
    player shifts around at its edge.

    Live-validated over SyncTERM: gunshot timing, rocket/chopper full length, projector/fire-bin/rooftop-wind ambiences (continuous + pan + attenuate + menu/save-load resume), and Duke's kill quips.

    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net