mirror of
https://github.com/SK8-ENGINE/skate-3-rust-engine.git
synced 2026-10-26 19:47:44 +00:00
New audio who dis
Native port of Skate 3's retail audio runtime (AEMS) behind SKATE_AEMS=1, plus the world audio work: - skate-audio crate: formats, patch-program evaluator, voice graph, mixer, MixMap, granular rolling bed and its bus chain, Splice contacts, the buses (env reverb network, eEQChain, flanger returns, collision and footstep submixes, reverb zones) and the player components (rolling layers, seams on the console's 30 fps cadence, grinds, skids, squeaks, tricks, treatment, footsteps, clothing, hands on deck, wind, wheels, collision manager). - game_audio host: native runtime, player audio state from our physics, world emitters from the maps' .ems files, random distant one-shots, zone ambience, state log, e2e render harness, timing. - Setup: audio export of the banks, grains, MixMap, vault tuning and reverb zones. - skate-core: per-wheel / per-part audio surfaces and seam patterns (additive). - Docs: docs/hails-additions/11-audio.md and the PR plan.
This commit is contained in:
117 files changed
+31947
-128
No files matched your search
@@ -45,8 +45,8 @@ the OS setting is sufficient; no code paths need changing.
|
||||
the "already enabled" path does nothing; the "disabled" path builds a valid
|
||||
PowerShell command (checked with the PowerShell tokenizer); `restart()`
|
||||
forwards the original arguments.
|
||||
- **Not exercised end to end:** the real UAC prompt with long paths disabled,
|
||||
and the frozen `skate3setup.exe` relaunch.
|
||||
- **Tested end to end (2026-10-02, the user):** the real UAC prompt with long
|
||||
paths disabled, and the frozen `skate3setup.exe` relaunch.
|
||||
|
||||
## Notes for upstream
|
||||
|
||||
|
||||
@@ -16,15 +16,17 @@ volumes. The game's loader (`skate_world::retail_collision_world`, via
|
||||
`skate_data::retail_collision::visit_clusters`) turned every triangle into
|
||||
solid collision, so these volumes became invisible walls, floors and ceilings.
|
||||
|
||||
SkateSchool has seven, all in its global stream (`cSim_Global.xsf`):
|
||||
SkateSchool has seven, all in its global stream (`cSim_Global.xsf`). Names
|
||||
are those of the matching retail trigger-volume records (see "What the boxes
|
||||
are" below):
|
||||
|
||||
| Box (X / Y / Z, metres) | Effect in game |
|
||||
|---|---|
|
||||
| −79…16.5 / −1.53…6.65 / −43…52 | covers the whole school area; the authored start (y 0.11) is inside it |
|
||||
| −66…−62 / −1.53…6.65 / −3.6…12.7 | the invisible wall in the spawn area |
|
||||
| −11…2.5 / 0…4.16 / −2.6…1.6 (three identical) | invisible block near the origin |
|
||||
| level bounds, Y −73…79 | floor under the whole map |
|
||||
| one more box | — |
|
||||
| Box (X / Y / Z, metres) | Name | Effect in game |
|
||||
|---|---|---|
|
||||
| −79.1…16.5 / −1.53…6.65 / −43.3…52.3 | `tut_sksc_inthehub_vol_02` | covers the whole school area; the authored start (y 0.11) is inside it |
|
||||
| −62.1…−0.5 / −1.53…6.65 / −3.6…12.7 | `tut_sksc_inthehub_vol_01` | the invisible wall in the spawn area |
|
||||
| −11.0…2.5 / 0…4.17 / −2.6…1.6 (three identical) | `coach_frank_sksc` / `ws_sksc_coachfrank_instance_01` | invisible block near the origin |
|
||||
| −212…578 / −73…79 / −483…492 | `tut_sksc_reset_vol01` | level bounds: floor under the whole map |
|
||||
| 104.1…199.7 / −4.1…4.1 / 151.5…247.1 | `tut_sksc_wrongway_vol_01` | — |
|
||||
|
||||
Evidence that these are not solid in the original game: every authored
|
||||
SkateSchool locator (Coach Frank, the hub, all tutorial stations) is at
|
||||
@@ -82,7 +84,8 @@ refresh.
|
||||
afterwards and are also clear.
|
||||
|
||||
Further evidence the volumes are triggers: MegaPark's only box
|
||||
(X 61.4–73.2, Y −4.1…4.1, Z −140.8…−132.6) surrounds the stadium's arrival
|
||||
(`tele_stadium_to_world_volume_a`, X 61.4–73.2, Y −4.1…4.1,
|
||||
Z −140.8…−132.6) surrounds the stadium's arrival
|
||||
point from the world (`tele_world_to_stadium_dest_locator_01`, 2 m from its
|
||||
centre), and one of Maloof's two boxes lies 14 m from its arrival point from
|
||||
DownTown (`tele_dwtn_to_mmcp_dest_locator_01`). The other Maloof box
|
||||
@@ -97,3 +100,36 @@ DownTown (`tele_dwtn_to_mmcp_dest_locator_01`). The other Maloof box
|
||||
boxes, and authored player positions lie inside some). If retail code that
|
||||
consumes these volumes (zones/triggers) is ported later, they should be
|
||||
routed there instead of dropped.
|
||||
|
||||
## What the boxes are (research, 2026-10-02)
|
||||
|
||||
Every surfaceless box is the shape of a named **trigger volume**: a volume-set
|
||||
record (type `0x00EB0019`: matrix, bounding box, link, instance id, name) in the
|
||||
same stream, whose bounding box matches the box to the millimetre. Retail
|
||||
registers them as triggers when the stream loads and posts enter/exit events;
|
||||
they are never solid. All 12 boxes:
|
||||
|
||||
| District | Volumes |
|
||||
|---|---|
|
||||
| SkateSchool | `coach_frank_sksc`, `ws_sksc_coachfrank_instance_01` (same box, 3 meshes), `tut_sksc_inthehub_vol_01`, `tut_sksc_inthehub_vol_02`, `tut_sksc_reset_vol01`, `tut_sksc_wrongway_vol_01` |
|
||||
| MegaPark | `tele_stadium_to_world_volume_a` |
|
||||
| MaloofMoneyCup | `tele_mega_ramp_up_volume_01` (X −9.3…−6.5, Z 54.5…56.5), `tele_mmcp_to_dwtn_volume_01` (X 36.2…42.1, Z 12.8…26.6) |
|
||||
| DownTown | `dwtn_sessionspot_01_kubetower_volume_01` (X 259–333), `dwtn_sessionspot_02_spillway_volume_02` (X 66.2…105.9, Y 50.2…59.0, Z −244.7…−212.2) |
|
||||
|
||||
The `tele_*` volumes are where retail offers a teleport (a yes/no challenge
|
||||
prompt). Exporting them as data the game can use (a "which volumes contain this
|
||||
point" query) is planned follow-up work; this change only stops them being
|
||||
solid. Research source: the TU3 code via the skate3recomp static recompilation
|
||||
(reference only).
|
||||
|
||||
## Correction (2026-10-02)
|
||||
|
||||
An earlier version of this document gave the SkateSchool spawn-wall box as
|
||||
X −66…−62. That came from an analysis script using the vendored Python
|
||||
collision decoder, which reads the 16-bit compressed vertex deltas as
|
||||
**signed**; vertices in clusters spanning more than 32.8 m then wrap by
|
||||
65.536 m. The game's Rust decoder (`retail_collision.rs`) reads them unsigned,
|
||||
as retail does, so **the game and this change were never affected**: the
|
||||
triangle counts and play tests above are unchanged. Re-run with unsigned
|
||||
deltas, every box now matches its retail trigger-volume record exactly. The
|
||||
real box is X −62.1…−0.5 (`tut_sksc_inthehub_vol_01`).
|
||||
+1852
-11
File diff suppressed because it is too large.
Load diff
@@ -11,12 +11,12 @@ verification, open questions).
|
||||
| A | Setup fix | Setup: enable Windows long paths for the pro roster (ISO argument-order half dropped: upstream fixed it in `713fe70`/`7ae67f2`) | [02](02-long-paths.md) ([01](01-iso-extraction.md) superseded upstream) | `0a88f7a`; PR branch `setup/xiso-option-order-and-long-paths` = `4352417` + merge of upstream `7ae67f2` (`d7cd6a2`, upstream lines at both ISO call sites) | — | Draft upstream [#23](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/23), retitled; diff vs upstream `main` = `tools/setup.py` only |
|
||||
| B | Feature (input) | SDL3 gamepad input with XInput fallback | [03](03-sdl3-gamepad-input.md) | `3d485c8` | — | Draft upstream [#24](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/24) |
|
||||
| C | Gameplay data | Authored map spawns and headings | [04](04-map-spawns.md) | `b495ed6`, `f00b329` | — | Draft upstream [#27](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/27) |
|
||||
| D | Gameplay data | Skip collision volumes that have no surface IDs | [05](05-collision-volumes.md) | `dec7ade` | — | Draft upstream [#25](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/25) |
|
||||
| D | Gameplay data | Skip collision volumes that have no surface IDs | [05](05-collision-volumes.md) | `dec7ade`, `d68c3ee` (comment: the boxes are retail trigger volumes) | — | Draft upstream [#25](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/25); description corrected 2026-10-02 (SkateSchool box coordinates, see doc 05 "Correction") |
|
||||
| E | Performance | Indexed stock collection lookups (game startup −5.5 s) | [07](07-collections-index.md) | `810defa` | — | **Merged upstream** as [#26](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/26) (2026-10-02, `4003812`) |
|
||||
| F | Tooling | Streaming map validator (`--validate-maps`) wired into setup | [06](06-map-validator.md) | `18f41a3` | E (speed only) | Draft upstream [#28](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/28) |
|
||||
| H | Gameplay + rendering | Water: detection and bail, shallow water solid / deep water floats, board floats, water camera + vignette, entry splash, water look (family 33 cube blur + tint, anti-tiling, body-size calming, slower waves), animated water (frame-state buffer fix, ocean PCA from default.xex, XEX2 unpacker), ripple scale | [09](09-water.md) | `gameplay/water` (`af1b350`…`55776dc`), upstream branch `water/retail-water` (`8a6e328`, one commit on `60efdef`) | — (carries #28's `install.py` `spawn()` split verbatim) | Draft upstream [#30](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/30) |
|
||||
| I | Test fix | `sky_shader_validates`: add the `VERTEX_POSITIONS` shader def Bevy sets for real meshes | [10](10-sky-shader-test.md) | `b7865d0` | — | Not opened; tiny, can go upstream alone |
|
||||
| J | Feature (audio) | Game audio: setup group `audio` extracts/decodes the disc's audio (vgmstream r2117), per-map ambience, water emitters, rolling by surface and speed band, trick/landing/grind/bail/splash cues, footsteps from foot strikes, volume settings and `--mute` | [11](11-audio.md) | `gameplay/audio` (`98c52b6`, `d9a1818`); upstream branch `audio/retail-audio` (`f1ad166` on #30's `8a6e328`, `main` 7ae67f2 merged) | H (branched from `gameplay/water`; uses its water detection — `collision_feedback.flags.material_12`, `is_water_tag`). Overlaps upstream #4/#1 (retail-exact player audio via transcribed game code + memory image; not adopted — see doc 11): both edit `tools/asset_pipeline/asset_exports.py` and `install.py`, different asset layouts | Draft upstream [#32](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/32), **Work in Progress**: the measured cue tables are interim while the retail audio engine is reverse engineered and re-created natively (doc 11) |
|
||||
| J | Feature (audio) | Game audio: setup group `audio` extracts/decodes the disc's audio (vgmstream r2117), per-map ambience, water emitters, rolling by surface and speed band, trick/landing/grind/bail/splash cues, footsteps from foot strikes, volume settings and `--mute` | [11](11-audio.md) | `gameplay/audio` (`98c52b6`, `d9a1818`); upstream branch `audio/retail-audio` (`f1ad166` on #30's `8a6e328`, `main` 7ae67f2 merged) | H (branched from `gameplay/water`; uses its water detection — `collision_feedback.flags.material_12`, `is_water_tag`). Overlaps upstream #4/#1 (retail-exact player audio via transcribed game code + memory image; not adopted — see doc 11): both edit `tools/asset_pipeline/asset_exports.py` and `install.py`, different asset layouts | Draft upstream [#32](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/32), **Work in Progress**. Branch has the first version; the world-audio work (.ems emitters, location-set one-shots/sirens, zone ambience) is done locally and goes up with the next batch commit; native AEMS runtime (`crates/skate-audio`, new workspace crate) implemented 2026-10-02 behind `SKATE_AEMS=1` (world emitters only), then the MixMap mixer (emitter words) and the granular rolling bed (`grain/`, `game_audio/grain_bed.rs`; setup keeps the whole grains, copies `MixMapSK8.mxb`, exports the grain tuning), then the player inputs and the first native player components (`skate_audio::player`, `game_audio/player_audio.rs`: Class_grind, SenseOfSpeed, Class_foot_drag; setup exports `player_tuning`; `skate-core` `WheelLineState.seam_patterns`), then the Splice board contacts / skid / squeaks and the collision manager, wheel spin and foot taps / scuffs (`player/{contacts,collision,wheels}.rs`; `skate-core` `BoardGroundState.part_audio_surfaces`; setup `player_tuning.collision`), then the buses (reverb network, eEQChain, flanger returns, collision submix) and Class_Seams, the board layers (`player/rolling.rs`), the grain bus chain (`grain/chain.rs`, `dsp/{fss,shelf}.rs`), tricks / treatment, and footsteps / clothing / hands on the deck (`player/{tricks,treatment,footsteps,clothing,step_on}.rs`; setup adds four Class_rolling banks, `bus_tuning.flange`, `player_tuning.audio_tricks_2`, per-material footstep fields and 16 grain-chain vault keys). All uncommitted, all on #32's checklist (updated 2026-10-02 21:30). The seam sample shuffle is in (Listening test 8: retail's boot utility `Start_up_Play_ctl`; setup now copies `Common.abk`). Listening: landings, pops, footsteps and the hand pick-up / put-down confirmed; rolling "is much better, it just has issues with certain surfaces"; after the shuffle, concrete and brick "both sound better but still need work". Plan, in order: (1) surface parity from the paired sessions (ours / recomp at the Aletown brick and the University PCU Library); (2) footstep submix, remaining engine inputs, reverb-zone emitters (1,040 records), Reverb inputs / global env-send scale, utility boot order (done headless 2026-10-02, doc 11 "FootStep SubMix, the skeleton inputs, …"; needs the listening check; setup exports the zones' `reverb` preset); (3) native as the default, interim cue tables removed; (4) the optimisation pass; (5) world / NPC audio stages as follow-ups. #32's description carries the same status and plan (updated 2026-10-02 evening). Latest listening (build 21:57): "rolling sounds better, griding sounds better, walking sounds better"; a University fountain's "doubling/restarting" is retail's relay of short pieces, with the repeat rate being analysed from the user's WATERRELAY retail session. Seams: retail runs them per rendered frame; per the user's decision ours targets the 360's ~30 fps cadence, frame-rate independent (done, default; user: "seams sound much better. overall much better <3"). Plan step (1) done; (2) Treatments 16/17 from the TREAT trace settled 2026-10-02: the recomp plays them too (their samples equal sense_of_speed 3/4, so the trace tool misread them); `+236` now counts through the landing tick, and the e2e scenarios pass the air words (doc 11 "Treatments slots 16 / 17"). Keep #32's description current (standing rule) When #32 is ready for merge, all of it goes up as ONE commit titled `New audio who dis`, only with the user's explicit permission at that time. |
|
||||
| G | Performance (setup) | Skip decoding duplicate stream copies; run the customiser beside the maps; parallel clothing library and pro roster, plus a native RefPack DLL in `Build.ps1` | [08](08-setup-performance.md) | `8327e94` (+ overlap hunks of `install.py` in `18f41a3`) | — | Draft upstream [#29](https://github.com/SK8-ENGINE/skate-3-rust-engine/pull/29) |
|
||||
| K | Gameplay fix (physics) | Board/skater solver: 50 constraint iterations (retail live value) instead of `RWMaxIterations` = 25 | [12](12-solver-iterations.md) | uncommitted (on `gameplay/audio` working tree) | — (one-file change in `physics/settings.rs`) | Ready apart from the asset-gated `customiser_equipment_reaches_ground_force_and_torque` question (doc 12) |
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ Each document stands alone. File paths are relative to the repository root.
|
||||
| # | Change | Area | Status |
|
||||
|---|---|---|---|
|
||||
| 1 | [ISO extraction argument order](01-iso-extraction.md) | Setup (Python) | Superseded: upstream fixed it the same way (`713fe70`, `7ae67f2`, 2026-10-02); dropped from PR A |
|
||||
| 2 | [Windows long paths during setup](02-long-paths.md) | Setup (Python) | Done; UAC path not exercised end to end |
|
||||
| 2 | [Windows long paths during setup](02-long-paths.md) | Setup (Python) | Done; UAC prompt and frozen relaunch tested end to end (2026-10-02) |
|
||||
| 3 | [SDL3 gamepad input](03-sdl3-gamepad-input.md) | Game (Rust), build scripts, vendored `sdl3-sys` | Done, verified in play with an Xbox Elite Series 2 |
|
||||
| 4 | [Authored map spawns](04-map-spawns.md) | Asset pipeline (Python) | Done, all 10 maps confirmed in play |
|
||||
| 5 | [Invisible collision volumes](05-collision-volumes.md) | Game data loader (Rust) | Done, all four affected maps confirmed in play |
|
||||
| 9 | [Water](09-water.md) | Game physics, camera and rendering (Rust), setup, diagnostics | Matched to retail footage (RPCS3): shallow water solid, deep water floats, board floats, water camera + vignette, entry splash, canal water look matched, small bodies calmer |
|
||||
| 10 | [Sky shader validation test](10-sky-shader-test.md) | Game tests (Rust) | Done; all six shader validation tests pass |
|
||||
| 11 | [Game audio](11-audio.md) | Setup (Python, vgmstream), game audio (Rust) | Tuned by ear over ~15 play sessions: rolling, pop/landing, board-down, footsteps, foot drag, splash, grab whoosh confirmed; bail impact, metal grinds, landing weight, fountains and some other cues not yet confirmed; regression pass pending |
|
||||
| 11 | [Game audio](11-audio.md) | Setup (Python, vgmstream), game audio (Rust) | Work in progress (draft #32). Player cues tuned against retail traces; retail world audio done: .ems emitters, location-set one-shots (sirens; 1,859/1,859 retail match over 15 locations), zone ambience beds. Native AEMS runtime (`crates/skate-audio`: evaluator + voice graph) implemented behind `SKATE_AEMS=1` for the world emitters; 234/235 PoC-oracle scripts identical, DSP kernels bit-exact; MixMap + granular rolling bed; player MixMap inputs and the first native player components (grind, wind/rattle, foot drag; wind level within 0.5 dB of retail); needs a listening check. |
|
||||
| 12 | [Board solver: 50 constraint iterations](12-solver-iterations.md) | Game physics (Rust) | Done; maps identical, water traces as expected; one asset-gated customiser test fails (open question) |
|
||||
|
||||
## Environment used for verification
|
||||
|
||||
Reference in new issue
Block a user