BBS:      TELESC.NET.BR
Assunto:  src/conio/cterm.c cterm.h cterm_cterm.c sdl_con.c src/syncterm/ooii.c
De:       Deuc¨
Data:     Tue, 21 Apr 2026 17:31:40 -0700
-----------------------------------------------------------
https://gitlab.synchro.net/main/sbbs/-/commit/897325cdb8ee22b19b9cf91a
Modified Files:
	src/conio/cterm.c cterm.h cterm_cterm.c sdl_con.c src/syncterm/ooii.c ripper.c src/xpdev/xpbeep.c xpbeep.h
Log Message:
xpbeep: node-list FIFO mixer, dB volumes, soft-clip, -12 dB stream base

Replaces the per-stream fixed 1 s S16 ring with a head/tail linked list
of producer-supplied frame buffers.  The caller malloc()s the PCM data
and xp_audio_append() transfers ownership; the channel free()s it once
the mixer has fully consumed the node.  Append is non-blocking in the
steady state  it only waits when the per-node metadata allocation
itself fails and we need the mixer to drop a buf to free memory.  This
unblocks the scene-music use case where queuing an arbitrarily long
playlist must return to the terminal immediately.

Fold xp_audio_append_faded + xp_audio_append into a single entry point
that takes a NULLable xp_audio_opts_t carrying per-entry volume (dB,
summed with the stream base), fade_in/fade_out frames, crossfade, and
loop.  Envelopes live on the node and are evaluated per-sample in the
mixer, which means looping bufs rise from silence exactly once and a
crossfade append starts the overlap immediately  old tail fades out
via an overlay envelope while the new buf fades in, both mixing
concurrently until the overlay expires.  XP_AUDIO_OPTS_INIT presets
unity dB on all fields so = {0} is equivalent.

Rework xp_mixer_pull to accumulate all streams into an int32_t scratch
(grown under mixer_lock, persistent) and apply tanh soft-clipping in a
single narrow pass at the end  replaces the old per-add int16_t
saturate that distorted multi-stream mixes the moment any contribution
pushed the running sum to full scale.  Volumes now compose in dB (per-
entry + stream base  one powf per channel per buf per pull) with 0 dB
as unity.

Lift the -12 dB headroom reduction out of xptone_makewave (both the
U8-wrap noisy path and the double clean path) and apply it as stream
base dB instead: cterm->music_stream and cterm->fx_stream open at
-12 dB, xptone opens its ephemeral stream at -12 dB, sdl_beep bakes
-12 dB into its static wave once at generation.  Synth output keeps
its full 16-bit resolution; OOII/RIP samples now ride at the same
level as tones instead of being 12 dB louder than the rest of the mix.

Add cterm_play_fx/_tone/_u8 on a per-cterm fx_stream (lazy-opened,
distinct from music_stream so MF/MB ANSI-music state doesn't interact
with RIP/OOII SFX).  Migrate ripper.c rv_sound cases (A, BE, BL, M, P,
R) and the ~40 xp_play_sample call sites in ooii.c to the new API;
drop background bool since the persistent fx_stream handles sequencing.

Teach parse_rip_new to forward the 0x0E music terminator to cterm when
the preceding CSI introducer (| unconditional, M when music_enable ==
ENABLED, N when music_enable >= BANSI) actually arms
cterm_accumulate_music.  Previously parse_rip ate all SO/SI bytes as
RIPterm text-window controls, which left the music accumulator stuck
until the connection ended.

xptone chunks and play_music notes switch to per-chunk malloc + append
transfer; ripper rv_sound A/BE/BL/M/P/R go through cterm_play_fx* and
no longer re-open the device per tone.

Co-Authored-By: Claude Opus 4.7 (1M context) 
n
---
  mSynchronetn  hgVertrauen n hHome of Synchronet n gh[vert/cvs/bbs].synchro.net

-----------------------------------------------------------
[Voltar]