Commit Graph
13 Commits
Author SHA1 Message Date
Dean 532f3e7b89 Merge pull request #6216 from eljackjoestar-cmd/fix/audioout2-completed-grain-backlog
fix(audio): retain completed AudioOut2 grains until pushed
2026-10-18 02:06:50 +13:00
fdfawef324andClaude Opus 5.5 2321f1ac7f fix(libSceAudioOut): count completed AudioOut2 grains in the queue level
sceAudioOut2ContextGetQueueLevel left out the grains that
sceAudioOut2ContextAdvance completed and no push had consumed yet. While
pushes filled the 40 ms cushion the level stayed at 0, so a title that
renders as many grains as the level leaves room for and pushes them on
another thread rendered a full queue again after each push. PPSA23226's
Wwise sink does that and stopped once more than 16 completed grains
awaited a push.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 12:36:14 -04:00
eljackjoestar-cmd 6575aa217d fix(audio): retain completed AudioOut2 grains until pushed 2026-10-15 13:06:45 +04:00
toxinexx e7219e4bc4 fix(libSceAudioOut): park guest audio calls at exit before the port tables are destroyed
The library registered no shutdown callback, so a guest mixer thread kept calling sceAudioOut2ContextPush while exit ran the static destructors and mixed from the freed port table (#5864). Exports that read the port tables or output audio now hold a guard: once exit starts they park the thread with LibcAwaitExit_nid_postfix, and the shutdown callback waits for the calls already inside. A push waiting for a grain from sceAudioOut2ContextAdvance also wakes on the shutdown token, so the callback does not wait for an advance that is parked.
2026-10-14 20:43:01 +02:00
eljackjoestar-cmd bb4ec482d2 fix(audio): preserve completed AudioOut2 grains across threads 2026-10-14 19:18:32 +04:00
Joel Fernandes dcfabcc579 feat(pad): bridge controller audio haptics to motor rumble 2026-10-14 13:45:00 +02:00
PrintOrb c35572ec18 fix(audioout): serialize shared SDL audio initialization 2026-10-12 15:54:46 -05:00
popcoder565andClaude Opus 5.5 b2cde4a0f2 fix(audio): pace blocking audio calls with a high-resolution timer
On Windows, nanosleep and this_thread::sleep_for/sleep_until go
through winpthreads, which ends a wait on a 15.6 ms GetTickCount64
step. Blocking sceAudioOutOutput and sceAudioOut2ContextPush calls
returned in bursts about every 16 ms, a blocking sceAudio3dPortPush
ran at about 68 % of real time, and sceAudioInInput without a device
woke anywhere from 1 ms to 31 ms apart. They now sleep with
PreciseSleepUs or the new PreciseSleepUntil.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:31:57 +02:00
MerijnandClaude Opus 5.5 9a8a85ebd0 test(audioout): cover AudioOut2 grain timing with the SDL disk driver
Address review: read a grain's buffers at the next push without spinning
under the context lock, keep the no-device model mixing at push time,
size the pad queue from the unplayed main grains again, use generic
names in comments and TechnicalDebt, and add audio_out2_timing (next-push
read, queue level beyond the cushion, priming after running dry).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:20:27 +02:00
MerijnandClaude Opus 5.5 f81425ec8e fix(audioout2): read grains at the next push and play them behind a cushion
A push mixed the ports' buffers at once and queued the mix on SDL, and
the queue level left out a 40 ms cushion that the SDL queue rarely
exceeded, so titles saw an empty queue. PPSA12544's FMOD output fills a
256-frame buffer after pushing it, reuses it two pushes later, and its
mixer thread can still be writing a buffer when the next push follows
within microseconds: a grain boundary broke about every 5 ms (an audible
crackle).

A push now records the buffers the ports point at and reads the previous
grain at the next push, 100 us after it. The mixed frames are played by
the SDL device callback, which waits for a 40 ms cushion before it plays
(again after running dry), and the queue level counts the unplayed
grains beyond that cushion. Recording the four buffers at every push
showed 27% of boundaries broken when read at the push, 59% when read two
pushes later and none when read at the next push; the title's output
went from 4-9% to none of its grain boundaries broken over 6,000 loud
grains.

AI-assisted: yes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 10:45:27 +02:00
Dean Galvin dee927ea76 feat(audio): play the DualSense speaker and vibration ports on its USB sound card
A title can open AudioOut2 ports of type 0x3 (the controller's speaker)
and 0x6 (its two voice-coil actuators) next to its bed and object ports.
Both were folded into the TV mix, so the haptics came out of the PC
speakers as low thumps and the controller got nothing.

A USB DualSense is also a 4-channel 48 kHz sound card: channels 1-2 feed
the speaker and headset jack, channels 3-4 the left and right actuators.
When SDL lists such a card, a context with these ports opens it and
queues a grain on it with every push: the speaker port on channels 1-2
(a mono port duplicated) and the vibration port's left and right
channels on 3-4, at the port volumes and clamped. Both ports then leave
the main mix. The card's queue gets the main queue's silence cushion when
it runs dry and drops grains that run more than two grains beyond the
main queue, so the controller keeps pace with the TV. An unplugged card
is released (its ports return to the main mix) and looked for again
every 2 s. Without a card nothing changes, and other port types and
channel counts keep their routing.

SDL2's PulseAudio backend labels a 4-channel stream FL FR FC LFE instead
of quad, and the sound server then folds channels 3-4 into the speaker.
Under that backend the card is opened as 5.1 with FC and LFE silent and
the actuators on the back pair, which lands on the card's RL/RR.
2026-10-01 01:24:12 +13:00
devilismyfriendandClaude Fable 5.1 91557ebade feat(audio): AudioOut2 SDL output queue, ATRAC9 decoder in libSceAjm.native
- AudioOut2: one SDL device per context; the hardware grain queue level
  is derived from the SDL queued bytes so the title's poll-and-push loop
  runs at real time; ports are mixed per push with 7.1 folded to stereo.
- libSceAjm.native: instance and batch APIs; ATRAC9 decoding with
  variable-size frames inside superframes, padding, gapless parameters
  and handle re-creation on re-initialisation.
- AudioOut v1: sceAudioOutOutput(handle, NULL) drains instead of
  throwing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-25 16:27:49 -07:00
boykopovar 5d7bee9a1f refactor(libs): organize sceAuodioOut lib with cmakelists 2026-09-12 16:16:41 +03:00