Clean up audio subsystem duplication, implement seeking and loop regions

- Extract audioStreamGetPanFactors() into the shared layer, replacing
  identical pan-to-LR math duplicated in the PSP and Dolphin backends
  (and dropping a dead clamp - directionality's int8_t range already
  guarantees pan stays in [-1, 1]).
- Implement audioStreamSetPosition() for real (was previously a no-op
  that computed a value and threw it away) and add
  audioStreamSetLoopPoints() to actually drive loopStart/loopTo, which
  were previously dead fields with no setter at all. Both are threaded
  through all three platform backends:
  - PSP: the feeder thread now bounds each pass by the loop segment
    and wraps to loopTo instead of always frame 0, while still filling
    hardware chunks gaplessly.
  - Dolphin: loopTo/loopStart map directly onto ansnd's existing
    loop_start_offset/loop_end_offset, and startFrame onto start_offset.
  - Linux: Buffer() now queues only the current segment, clearing the
    SDL queue on an explicit seek but preserving the existing
    overlap-based gapless loop restart otherwise.
- Linux: skip the mix scratch-buffer entirely at full volume, queuing
  stream->data directly instead of allocating/zeroing/copying into one
  every buffer call for no reason.

Verified no regression in the default (no seek, no loop points) case on
Linux/PPSSPP/Dolphin (-a LLE), and verified seek + loop-region behavior
manually via a temporary engine.c smoke-test tweak (reverted) showing
the expected faster loop cadence and seek-then-loop sequencing.
This commit is contained in:
2026-08-31 17:18:49 -05:00
parent 8049e90853
commit 15bd9fc43c
6 changed files with 252 additions and 58 deletions
+7
View File
@@ -30,6 +30,13 @@ typedef struct {
// a pass; cleared by the thread once it picks it up.
volatile bool_t playRequested;
// Frame offset the next pass should start from - captured synchronously
// from audiostream_t.startFrame by audioStreamPSPBuffer() (which also
// resets that field to 0) rather than read directly by the feeder thread,
// since the thread only wakes up asynchronously and audiostream_t's
// shared field may already have moved on to a different value by then.
size_t startFrame;
// Set by the thread once it has fed the last chunk of a pass.
volatile bool_t finished;
} audiostreampsp_t;