Skip to content

feat(libSceNgs2.native): reverb rack following the PS4 libSceNgs2 reverb - #2336

Merged
oneandonlydean merged 5 commits into
boykopovar:mainfrom
JAB-dev:feat/ngs2-reverb-rack
Oct 9, 2026
Merged

oneandonlydean merged 5 commits into
boykopovar:mainfrom
JAB-dev:feat/ngs2-reverb-rack

Conversation

@JAB-dev

@JAB-dev JAB-dev commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Replaces #960, which was closed pending a reference. The reverb now follows the PS4 firmware 11.00 libSceNgs2.sprx, read from its code and checked against its output (see the reference section). #1384 is a draft with an approximate reverb that is waiting for the same kind of reference.

What

sceNgs2RackCreate throws for rack id 0x2001 (reverb). This adds the rack, with the reverb the console library renders.

  • Options: SceNgs2ReverbRackOption (rack option, max_channels, reverb_size). The defaults come from KytyPS5: 8 channels and reverb_size 1.
  • Voice params:
    • 0x20010000 setup takes input and output channel counts and flags. It accepts 1, 2, 6 or 8 channels; other counts are invalid arguments. Non-zero flags and differing input and output counts throw.
    • 0x20010001 takes SceNgs2ReverbI3DL2Param (88 bytes). The layout of both params, and of the voice state, matches shadPS4's ngs2_reverb.h. Values are clamped to the library's ranges, as it does; NaN throws.
    • sceNgs2VoiceGetState returns the common voice state.
  • Rendering, as in the library:
    • The input is mixed to mono with the library's fixed gains (0.707 for stereo, 0.316 for 5.1, 0.267 for 7.1), without the LFE channel.
    • A 14400-sample buffer feeds four reflection taps placed by the reflection pattern tables (16 patterns), plus a late feed.
    • Sixteen damped comb filters with a pre-emphasis stage; their lengths follow density.
    • Each output channel takes a signed selection of the combs, then runs four allpasses driven by diffusion.
    • A two-pole room HF filter at hf_reference, then the wet and dry levels. The LFE channel passes dry.
    • New params crossfade over one grain, and wet and dry levels ramp. Until the title sends I3DL2 params, the setup defaults leave the wet output almost silent.
  • The points the PR was closed for:
    • The Freeverb-style approximation is gone.
    • density and reflection_pattern are used.
    • Before any I3DL2 param, the voice renders the library's setup defaults; it no longer passes its input through.
    • Only the default reverb_size of 1 is handled, with its 14400-sample buffer; other sizes throw.
  • Not implemented: the library's half-rate mode, channel conversion, and system sample rates below about 7.5 kHz, where an allpass would have no samples. All three throw, and TechnicalDebt records them.

Reference

  • PS4 firmware 11.00 libSceNgs2.sprx, dumped and decrypted from a console. It was loaded on Windows with a small test loader and called directly; neither the loader nor the library is part of this PR. The reverb was read from its disassembly, and the test values are its output.
  • Against that library, the output matches to float rounding (110 to 180 dB SNR). That covers presets, every reflection pattern, short and long delays, 1, 2, 6 and 8 channels, noise input, 11.025 to 48 kHz and parameter changes during playback.
  • PS5 firmware 10.06 libSceNgs2.sprx (the module titles import as libSceNgs2): its readable ELF headers match the PS4 library: the same .eh_frame_hdr size (3,460 bytes, 431 functions) and code plus read-only data within 1% (321,328 bytes against 323,432). A decrypted PS5 SELF was not used; anyone with a decrypted PS5 libSceNgs2.sprx can help confirm this.
  • A PS5 recording of Animal Well (a public walkthrough): the decay of its jump sound, averaged over 382 jumps there and 72 here, matches within about 0.5 dB for the first 120 ms. Later the background music covers the tail, so that part couldn't be compared.

Tested

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

🤖 Generated with Claude Code

JAB-dev and others added 5 commits October 6, 2026 22:21
Rack 0x2001 is created with its option layout and KytyPS5's defaults, takes
the setup (0x20010000) and I3DL2 (0x20010001) voice params and reports the
common voice state. The voice mixes its inputs and runs a Freeverb-style
approximation driven by the I3DL2 parameters: room and room HF, early
reflections and their delay, late reverb and its pre-delay, decay time and
HF ratio, and diffusion. Out-of-range params throw, param changes keep the
tail, a stop or kill clears it, and the tail ends once it decays below
1e-20. The console's algorithm is unknown; the approximation is recorded in
TechnicalDebt. The test context buffer pool grows to 64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reverb was a Freeverb-style approximation. It now follows the PS4
firmware 11.00 libSceNgs2.sprx, read and checked against its output: the
input mixed to mono with the library's fixed gains, a 14400-sample buffer
with four reflection taps from the reflection pattern tables and a late
feed, sixteen damped comb filters with a pre-emphasis stage, a signed
selection of combs and four allpasses per output channel, a two-pole room
HF filter, and the library's parameter clamps, crossfades and setup
defaults. The test values are the PS4 library's own output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he reverb does not handle

A reverb_size other than the default was accepted and ignored, and below
about 7.5 kHz an allpass length went negative and wrapped to a 16 GB buffer.

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

Kikoarl commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Tested on Linux (CachyOS x86_64, Intel RPL-S iGPU / Mesa 26.3.0-devel / Vulkan 1.4.363, GCC 16.2.1) at 473ca04b:

  • Build: Built cleanly in RAM (/tmp/anyps5_build) with zero warnings/errors.
  • Conventions: python3 tools/check_conventions.py --base origin/main --head HEAD -> PASS (0 errors).
  • Verification: Verified reverb rack DSP implementation in libSceNgs2.native. All audio pipeline tests pass cleanly.

LGTM!

@oneandonlydean
oneandonlydean merged commit 9ee4972 into boykopovar:main Oct 9, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants