Skip to content

fix(libSceAudioOut): report the front left speaker at +30 degrees, as the console does - #6871

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
hugodearaujo:fix/audioout2-speaker-angles
Oct 19, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
hugodearaujo:fix/audioout2-speaker-angles

Conversation

@hugodearaujo

Copy link
Copy Markdown
Contributor

What

A PS5 reports, in sceAudioOut2GetSpeakerInfo, the front left speaker at +30 degrees and the front right one at -30 (the azimuth grows to the left), and -360 for the azimuth and the elevation of every slot without a speaker. Here the front pair was the other way round, at -30 and +30, and the 14 unused slots held 0 and 0, the front centre direction.

This PR reports the stereo pair the way the console orients it and puts -360 in the unused slots. The type stays 0 and the available bits stay 0x3. On the console the type followed the HDMI device type, 0 for TV, 1 for AV amplifier and 2 for sound bar, which SharpProspero names television, AV receiver and sound bar, and the available bits followed the channels.

Title

ASTRO BOT (PPSA21567, my own dump) calls sceAudioOut2GetSpeakerInfo with flags 0 about 93 times a second (18,379 calls in a 197 s run from launch through the title screen, the save selection and the galaxy map) and reads the two front angles (#4317).

I measured no difference in those scenes: in one run with each pair of angles through the same scripted input (a local build that switched them with an environment variable), with SDL's disk audio driver capturing the mix, the left/right balance was the same, a mean (L - R) / (L + R) per second of +0.004 with the old angles and +0.003 with the new ones. This emulator applies only the PCM data and volume attributes of a port (ids 0 and 1) and ignores the others.

Measured

PS5, firmware 13.60, from a homebrew payload process that calls the system's own libSceAudioOut through dlopen/dlsym, after sceAudioOut2Initialize, in every HDMI device type and channel setting the console offered. Only the AV amplifier type lets the channel count be chosen; the TV and sound bar types keep it fixed.

setting type available_bits front left, right centre surround left, right other slots
TV 0 0x3F (30, 0), (-30, 0) (0, 0) (110, 0), (-110, 0) (-360, -360)
AV amplifier, 2 channels 1 0x3 (30, 0), (-30, 0) (-360, -360) (-360, -360) (-360, -360)
AV amplifier, 5.1 1 0x3F (30, 0), (-30, 0) (0, 0) (110, 0), (-110, 0) (-360, -360)
AV amplifier, 7.1 1 0x3 (30, 0), (-30, 0) (-360, -360) (-360, -360) (-360, -360)
sound bar 2 0x3F (30, 0), (-30, 0) (0, 0) (110, 0), (-110, 0) (-360, -360)

The other slots include slot 3, the LFE, in the 5.1 layouts. flags was 0 throughout. 7.1 reported 2 channels on this console's HDMI chain, so the 7.1 layout itself is not measured. Flags 1 gave the same as flags 0. Flags 2, 4 and 0x80000000 returned 0x80268001, a null pointer 0x8026800C, and a call before sceAudioOut2Initialize 0x80268006; those error paths are unchanged and listed in TechnicalDebt, together with the port states the same payload read.

Probe output (PS5 firmware 13.60, payload process)
--- a payload reading the speaker info every second while the settings changed (AV amplifier 2 channels, then TV, AV amplifier 5.1, AV amplifier 7.1, sound bar and AV amplifier 7.1 again)
TD48 SPEAKER WATCH v1|pid=118
AO_INIT|rc=00000000
CHANGE|t=0s|rc=00000000|type=1|available_bits=0x3|flags=0x0|0:(30,0)|1:(-30,0)
CHANGE|t=336s|rc=00000000|type=0|available_bits=0x3f|flags=0x0|0:(30,0)|1:(-30,0)|2:(0,0)|4:(110,0)|5:(-110,0)
CHANGE|t=500s|rc=00000000|type=1|available_bits=0x3|flags=0x0|0:(30,0)|1:(-30,0)
CHANGE|t=506s|rc=00000000|type=1|available_bits=0x3f|flags=0x0|0:(30,0)|1:(-30,0)|2:(0,0)|4:(110,0)|5:(-110,0)
CHANGE|t=521s|rc=00000000|type=1|available_bits=0x3|flags=0x0|0:(30,0)|1:(-30,0)
CHANGE|t=563s|rc=00000000|type=2|available_bits=0x3f|flags=0x0|0:(30,0)|1:(-30,0)|2:(0,0)|4:(110,0)|5:(-110,0)
CHANGE|t=655s|rc=00000000|type=1|available_bits=0x3|flags=0x0|0:(30,0)|1:(-30,0)
--- AV amplifier, 2 channels, separate run
AO_INIT|rc=00000000
AO_SPEAKER|flags=0|rc=00000000
AOSPK=010000000300000000000000000000001e000000e2ff000098fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe (80 bytes written; the 80 guard bytes after them still a5)
DECODED|type=1|available_bits=0x3|0:(30,0)|1:(-30,0)|2:(-360,-360)|3:(-360,-360)|4:(-360,-360)|5:(-360,-360)|6:(-360,-360)|7:(-360,-360)|8:(-360,-360)|9:(-360,-360)|10:(-360,-360)|11:(-360,-360)|12:(-360,-360)|13:(-360,-360)|14:(-360,-360)|15:(-360,-360)
AO_SPEAKER|flags=1|rc=00000000
AOSPK=010000000300000000000000000000001e000000e2ff000098fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe (80 bytes written; the 80 guard bytes after them still a5)
DECODED|type=1|available_bits=0x3|0:(30,0)|1:(-30,0)|2:(-360,-360)|3:(-360,-360)|4:(-360,-360)|5:(-360,-360)|6:(-360,-360)|7:(-360,-360)|8:(-360,-360)|9:(-360,-360)|10:(-360,-360)|11:(-360,-360)|12:(-360,-360)|13:(-360,-360)|14:(-360,-360)|15:(-360,-360)
--- sound bar (5.1), separate run
AO_INIT|rc=00000000
AO_SPEAKER|flags=00000000|rc=00000000
AOSPK=020000003f00000000000000000000001e000000e2ff00000000000098fe98fe6e00000092ff000098fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe (80 bytes written; the 80 guard bytes after them still a5)
AO_SPEAKER|flags=00000001|rc=00000000
AOSPK=020000003f00000000000000000000001e000000e2ff00000000000098fe98fe6e00000092ff000098fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe98fe (80 bytes written; the 80 guard bytes after them still a5)
AO_SPEAKER|flags=00000002|rc=80268001
AOSPK=(all 160 bytes still a5: nothing written)
AO_SPEAKER|flags=00000004|rc=80268001
AOSPK=(all 160 bytes still a5: nothing written)
AO_SPEAKER|flags=80000000|rc=80268001
AOSPK=(all 160 bytes still a5: nothing written)
AO_SPEAKER_NULL|rc=8026800c
--- before sceAudioOut2Initialize
AO_SPEAKER|flags=00000000|rc=80268006
AO_SPEAKER|flags=00000001|rc=80268006
AO_SPEAKER|flags=00000002|rc=80268006
AO_SPEAKER|flags=80000000|rc=80268006
AO_SPEAKER_NULL|rc=80268006

Tested

  • audio_out2_device_state now checks the front pair at +30 and -30 and -360 in the other 14 slots; with AudioOut2SpeakerArray.cpp as on main it aborts. The nine audio_out2 tests pass.
  • Linux (Arch, kernel 7.2.9, GCC 16.2.1, Release, RX 9070 XT with RADV, Mesa 26.2.4): full CTest with -j8 on main (82ddae75b) and on this branch. 1286 of 1287 pass here; agc_driver_tessellation fails as on main.
  • Windows Server 2025 VM, WinLibs GCC 15.2, Release, BUILD_TESTING=ON, GPU tests skipped: main (82ddae75b) does not build GpuIndirectArgumentsMisalignedWriterAhead.cpp with MinGW (alignas(65536) is above the object file's maximum of 8192; agc tests: GpuIndirectArgumentsMisalignedWriterAhead.cpp does not compile with MinGW GCC (alignas(65536)) #6716, test(agc): align the indirect arguments block at run time #6452), so main and this branch were built with ninja -k 0 and that test does not run. audio_out2_device_state passes. 1319 of 1321 pass; the other failure is guest_kqueue (0xc0000409), as on main, where guest_shader_link and agc_shader_helpers also timed out.
  • tools/check_conventions.py passes. tools/pr_overlap.py finds no overlap with open pull requests.

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

… the console does

A PS5 (firmware 13.60) reports the front left speaker of its speaker info at +30 degrees and the front right one at -30, and -360 for the azimuth and elevation of every empty slot, in every HDMI device type and channel setting it offered. sceAudioOut2GetSpeakerInfo reported the front pair the other way round and empty slots as 0, the front centre direction. The type stays 0: the console's type followed the HDMI device type, and it reported 0 with the device set to TV.
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 docs/dev/debt/libSceAudioOut.md
PR 5965 docs/dev/debt/libSceAudioOut.md
PR 6964 docs/dev/debt/libSceAudioOut.md
PR 7658 docs/dev/debt/libSceAudioOut.md

@adriadam10 adriadam10 self-assigned this Oct 19, 2026
@adriadam10
adriadam10 merged commit c0607cc into boykopovar:main Oct 19, 2026
9 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the diff against the console measurements in the description (front pair +30/-30, -360 in unused slots, type and available bits unchanged), the updated audio_out2_device_state assertions (they fail on the old values) and the TechnicalDebt entry; merged.

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.

2 participants