Investigate AO audio and plan PRK.Client sound implementation
Outcome Establish how the original AO client loads, selects, schedules, spatializes, mixes, and stops sounds, then discuss and agree a phased sound implementation for PRK.Client. This is the research/planning prerequisite to the larger implementation, not permission to select a backend or build playback yet. Planning must not edit repository files. Leave open during planning; implementation tasks follow the discussion gate. Initial repository findings - PRK.Client/PRK.Client/PRK.Client.csproj targets net10.0, NativeAOT, with win-x64 publishing; no playback foundation identified. - AOEmu.PlayfieldEngine/Entities/Sound.cs already has SoundDictionary/Sound for version-11 SBF banks, encoded paths, sound-name hashing and child references. It uses dynamic rotation helpers and stores 208 bytes of opaque metadata. Extract/extend a dependency-light, typed, validated shared parser rather than referencing PlayfieldEngine or copying it into the client. scripts/ReadSBF.cs duplicates historical decoding logic. - Tools/RDBExtractor/Extractors/SwsClasses.cs describes music project/layer/sample/transition/fade structures, but SWSExtractor.cs is an unimplemented/commented-out experiment, not a working music reader. - PRK.Common/RDBLib2/RDBObjects/RdbPlayfieldStatels.cs retains global/chunk sound emitter records but two fields remain unknown. PRK.Client/PRK.Client/Anarchy/Playfield.cs currently skips the flat-block sound records. Existing room/chunk transforms and fog/emitter framing tests are reuse points, not proof of sound-field semantics. - PRK.Common/AOEmu.Common/Messaging/N3Messages/PlaySoundMessage.cs provides name and target identities; no PRK.Client handler found. Original target/position semantics still require tracing. - Existing Effects/WeaponNote.cs and WeaponShotEffects.cs schedule combat visuals from attack-animation notes. Extend established timing/event ownership rather than adding unrelated audio timers that drift or double-trigger. Also inspect nano/item, movement/footstep, door, character and UI events. - Preferences/InstallPreferenceSeeds.cs already declares MasterVolume, FXVolume, MusicVolume and VoiceSndFxVolume. Reuse PreferenceStore, ClientDataSources, Bootstrap/FrameWiring and world/session teardown ownership. Original-client evidence from initial reconnaissance Installation examined: /mnt/games/Anarchy Online. Imported neighboring audio/client binaries together through ghidra_container; analysis uses only /data/inbox paths. - N3.dll and Gamecode.dll import SandyInterface audio APIs; SandyInterface.dll imports mss32.dll AIL functions (Miles) and SIMPlayer.dll. Separate GUI, game/environment and music entry points exist; Gamecode exposes combat/death music and district overrides. - SandyInterface.dll: SetupGameSounds 0x10006a0a loads sound/SourceFiles/SM_Sandy_Game_Dummy.sbf; ParseSourceFile 0x10003520 recognizes version 11, rotates encoded path bytes, resolves child/material references and interprets bank metadata. GetSoundID 0x100071ca -> CreateSoundID 0x10005ad2 -> hash 0x10008213 lowercases bytes, limits input to 255 bytes, and XORs rotated 32-bit chunks. Compare shared C# hashing against this unsigned arithmetic before reuse. - PlayGameSound 0x10007673 maps material then calls PlaySample 0x10002d98. PlaySample includes distance cutoff and linear attenuation between inner/outer distances, composite selection, delays, randomized values and category handling. FrameProcessSound 0x10003b70 updates playback lifetime, fade/stop/release and timed child sounds. Decompiled parameter types are unreliable; exact flags/field meanings need disassembly/call-site corroboration. - SE_Create2DSoundFromFile 0x100079cd uses AIL file detection and decompression, including MP3/Ogg paths. Do not assume WAV means PCM, or assume a modern 3D backend reproduces AO mixing/panning automatically. - Read-only bank census consumed complete files: game bank 6,810 records, 1,452 with child references; GUI bank 85 records, 5 with children. Sound tree contains WAV and Ogg plus anarchy.sws. Preliminary WAV header scan found format tags 17 (IMA ADPCM), 85 (MPEG), and 1 (PCM); confirm chunk parsing and required codec coverage during research. - Music strings reference sound/music/env/sim.config and anarchy.sws; SetupENVSounds 0x1000657d selects music layers and a land-control override. Complete music transition behavior remains unverified. Proposed sequence / discussion gate 1. Map bank/resource semantics, actual codec coverage and representative asset resolution; separate established facts from unknowns with binary version/hash and function addresses. 2. Trace trigger-to-playback paths: server PlaySound, GUI/login/character creation, combat/nano/item/animation notes, footsteps/materials, doors, placed ambience, district and combat/death music. Verify listener position/orientation, attenuation/panning, composite flags, priorities/limits, fades and cleanup. 3. Present a compatibility matrix and evaluate decoder options and the selected OpenAL Soft backend for packaging, NativeAOT, platform support, streaming/caching, device failure and licensing. Do not reuse proprietary Miles DLLs as the default architecture. 4. Plan implementation against the confirmed platforms, backend, gameplay listener and first playable scope below. Later milestones cover animation-driven world effects/footsteps/ambience and authored music transitions. One shared audio runtime/catalog; adapters should not each resolve banks, decode files or own mixers. Acceptance criteria for this research task - Evidence-backed architecture and asset/codec map with uncertainty explicitly labeled. - Representative sound paths traced from source event through bank selection to playback; unresolved coverage and assumptions listed rather than claimed complete. - Reuse/refactor opportunities and a bounded phased implementation proposal cover NativeAOT, nonblocking frame updates, missing/corrupt assets, unsafe paths, cycles/unresolved bank references, duplicate triggers, excessive voices, unavailable devices and zoning/logout/shutdown cleanup. - Validation strategy includes parser/hash/metadata fixtures, deterministic scheduling and fake-backend tests, installed-asset census, audible comparison with original AO, packaged-client smoke tests, and repeated zone/session lifecycle tests. No game assets committed for tests without confirming redistribution constraints. - User discussion records chosen scope/platforms/fidelity and backend direction before follow-up implementation tasks are created. Backend, gameplay listener placement and first playable milestone are approved. Implementation is now authorized and tracked separately in tsk_vjf59g4jc2 (Implement first playable PRK.Client audio iteration). This task retains the broader research/planning handoff; full world-trigger/ambience/music investigation remains deferred rather than marked complete. See the implementation task for current validation and release gates. Confirmed first playable scope - Gameplay listener uses the character's head position with camera-facing orientation; camera zoom does not change listener position. Free-camera/no-character behavior remains a boundary policy to define during implementation. - First playable milestone covers original-format decoding, sound-bank resolution, UI/server-requested sounds, positional playback, existing volume controls and clean zoning/logout/shutdown teardown on Windows, Linux and macOS. - Defer combat/footstep/placed-ambience integration and authored music transitions to later milestones. - Use baseline/default playback without new enhancement settings for the first version. Preserve authored attenuation/timing; defer custom HRTF controls, reverb, occlusion, Doppler, ducking and EQ enhancements. Validate backend defaults so they do not inadvertently alter authored behavior. Confirmed platform requirement Windows, Linux and macOS are first-class supported platforms from the outset. macOS uses MoltenVK for graphics but otherwise runs natively; audio must be native too, with no Wine or Windows-only runtime dependency. The current win-x64 publishing entry is not the product support boundary. Backend/decoder evaluation and packaged-client validation must cover all three platforms and NativeAOT-compatible bindings/native-library delivery. CPU architecture targets remain to be established from project requirements; do not infer them solely from the current RID. Confirmed backend decision User approved OpenAL Soft as the playback backend following the licensing and NativeAOT discussion. Ship a separate native DLL/.so/.dylib, loaded through thin AOT-compatible P/Invoke bindings; no static linking and no reliance on system OpenAL. PRK.Client remains closed source. Use the LGPL 2.1 shared-library compliance route allowed by OpenAL Soft's LGPL v2-or-later grant: include license/copyright notices, distribute exact corresponding library source and build scripts alongside client downloads, preserve replacement by an interface-compatible modified library, and include the required EULA permissions for own-use modification and debugging reverse engineering. Review macOS signing/library validation and updater/integrity behavior for replacement compatibility. Include applicable HRTF dataset notices (default dataset Apache 2.0). Final release compliance requires review. This backend decision does not select a decoder library, fixed voice count or the whole proposed runtime design. Gameplay listener placement and first playable scope are approved separately above. Modern playback discussion — remaining design proposals User requires original-format compatibility while allowing increased simultaneous channels/voices and improved playback quality. - Preserve AO authored bank semantics and trigger timing in a managed compatibility layer; replace Miles device/mixing/voice limits. Distinguish sound instances, physical playback voices, and output speaker channels. - Selected backend: bundled OpenAL Soft for native Windows/Linux/macOS spatial playback, float buffers, HRTF, surround output and optional EFX. Separate decoding is required. Verify NativeAOT interop, extension availability, LGPL distribution obligations and per-platform packaging. miniaudio was considered as a permissively licensed alternative but is not the selected backend. - Proposed decoding layer: validated RIFF/container dispatch plus PCM/IMA ADPCM, MPEG-in-WAV and Ogg/Vorbis decoding to float PCM; evaluate small native dr_wav/dr_mp3/stb_vorbis-based wrapper or another proven library against the installed corpus before choosing. MPEG-in-WAV needs explicit container/payload handling; a library advertising WAV and MP3 is not sufficient proof. Short clips use a bounded shared decoded cache; music/long ambience stream from worker-produced buffers. Retain original rates/layout; quality resampling belongs at the playback boundary. - Managed bank catalog resolves IDs, child/material variants and authored policies into sound instances. Each instance can own multiple independently positioned voices. Backend physical source limits must not become catalog-instance limits. Start with a configurable benchmark target around 128–256 physical voices (not a promised number), category priorities/reservations, per-event limits, quiet/distant voice virtualization and fade-based stealing. Virtual loops retain logical time; obsolete transient events are dropped, not replayed late. - Float playback, high-quality resampling, smooth gain transitions, headroom/clipping policy and optional headphone HRTF improve rendering but cannot recover information absent from low-rate/lossy source assets. Preserve authored attenuation initially and apply it only once; do not silently substitute backend inverse-distance behavior. Preserve stereo music/UI; positional mono and stereo-world behavior need an explicit policy. Doppler, room reverb/occlusion, ducking and EQ should be opt-in additions rather than unverified defaults. - Keep backend context/source operations on a dedicated owner thread; decoding on workers; native backend owns real-time mixing. No managed allocation, blocking I/O or world locks on a real-time audio callback. Bounded timestamped commands and coalesced emitter/listener snapshots cross from client frames into audio. NativeAOT callback/ABI safety is a prototype acceptance gate. - Networking/Client.cs drains messages in Update with a 128-message/4-ms budget, making main-frame event handoff a reuse point. App/FrameWiring.cs updates camera before world; publish listener/emitter state after authoritative frame updates, without sharing mutable entity references across threads. WorldManager.cs already owns character/door/effect state; audio must not depend on EnableEffects having a non-null graphics catalog. Share animation-note/event scheduling with visuals, not ownership of the visual renderer. - Bootstrap owns a long-lived audio service; screen/world/session scopes own sound instances. World-generation tags cancel stale commands and decode completions on zone/logout; device reset is independent of world teardown. Reuse existing volume preferences; UI/dialogue/music can have distinct internal gain groups while preserving existing user-facing controls. - MusicDirector owns SWS state and authored transitions separately from one-shot effects, using the same decoding/cache/backend services. Beat/sample-aligned layered transitions require an explicit clock/synchronization prototype; frame-tick crossfades or independent stream starts are not assumed sufficient. - Initial prototype gates: decode representative and then all required installed formats; NativeAOT playback on all three OSes; source/voice stress and memory budgets; original attenuation and composite tests; timing and stream synchronization; clean device-unavailable and zone/logout recovery. Validate the selected backend against these gates; report concrete blockers rather than silently changing the approved choice.
Checklist
0 of 5 complete- Verify original-client bank/hash/metadata semantics and codec coverage with binary addresses and representative installed assets; label remaining unknowns.
- Trace representative UI, server-message, animation/world, ambience and music paths through playback, listener/mixing behavior and teardown.
- Present a phased implementation proposal comparing backend/decoder options and identifying shared parser, preferences, event-timing and lifecycle reuse.
- Define automated, installed-asset, audible-parity and packaged-client validation, including malformed assets, unavailable devices and repeated zoning/logout.
- Discuss and record agreed platforms, fidelity, first playable scope and backend direction before creating follow-up implementation tasks.
- Area
- Project Rubi-Ka
- Project
- engines
- Kind
- Research
- Task ID
tsk_n87n48dj3s- Updated