# 132 — MetaSounds Audio Manager (`SS_AudioManager`) ## Purpose Single entry point for all audio playback in the framework. Every system routes sound through this Game Instance Subsystem instead of calling `UGameplayStatics::PlaySound*` directly. Owns 4 MetaSound buses (SFX, Ambience, Music, Dialogue) → Master Bus, manages room-based reverb zones with crossfade, handles per-category volume from player settings, and accepts gameplay-driven parameter modulation (heart rate, stress, fear, music intensity). ## Dependencies - **Requires:** `SS_SettingsSystem` (105 — persistent volume settings), `BPC_StateManager` (130 — heart rate + vital signals), `BPC_StressSystem` (10 — stress tier), `BPC_PacingDirector` (98 — music intensity), `BPC_HealthSystem` (08 — player health for muffled audio), `BPC_FearSystem` (90 — fear audio modulation), `DA_AudioSettings` (134 — default config) - **Required By:** ALL systems that play audio, `BP_RoomAudioZone` (133 — room preset changes), `WBP_SettingsMenu` (57 — volume sliders), `BPC_AudioAtmosphereController` (95 — DEPRECATED, replaced by this) - **Engine/Plugin Requirements:** MetaSounds plugin (UE 5.5+ default audio engine), GameplayTags plugin ## Class Info | Property | Value | |----------|-------| | **Parent Class** | `GameInstanceSubsystem` | | **Class Type** | Game Instance Subsystem | | **Asset Path** | `Content/Framework/Audio/SS_AudioManager.uasset` | | **Implements Interfaces** | *(none)* | --- ## 1. Enums ### E_AudioBusCategory — Audio Bus Categories (5 values) ```text Enum Name: E_AudioBusCategory (DisplayName = "Audio Bus Category") Values: SFX = 0 // Sound effects — spatial, occluded, surface-reactive Ambience = 1 // Environmental background — room tones, weather Music = 2 // Dynamic music — layers, intensity bands Dialogue = 3 // VO and character dialogue — ducking priority Master = 4 // Master output — overall volume ``` --- ## 2. Structs ### `S_AudioBusConfig` | Field | Type | Description | |-------|------|-------------| | `BusCategory` | `E_AudioBusCategory` | Which bus this config applies to | | `DefaultVolume` | `Float` (0–1) | Default volume (pre-settings) | | `MetaSoundSource` | `UMetaSoundSource` | The MetaSound patch for this bus | | `bSpatialized` | `Boolean` | Use 3D spatialization? | | `AttenuationSettings` | `USoundAttenuation` | Distance falloff curve | | `MaxConcurrentSounds` | `Integer` | Voice limiting per bus | | `DuckingPriority` | `Integer` | 0=lowest, 100=highest (dialogue=100) | | `DuckAmount` | `Float` (0–1) | How much to duck other buses when this bus plays | | `SettingsBindingTag` | `GameplayTag` | Tag for settings lookup (e.g., `Settings.Audio.SFXVolume`) | ### `S_RoomAcousticProfile` | Field | Type | Description | |-------|------|-------------| | `RoomPresetName` | `FName` | Identifier for this room preset | | `ReverbDensity` | `Float` (0–1) | How dense the reverb reflections are | | `ReverbDecayTime` | `Float` (seconds) | RT60 decay time | | `ReverbWetLevel` | `Float` (0–1) | Wet/dry mix for reverb | | `ReflectionsDelay` | `Float` (ms) | Pre-delay before reflections start | | `RoomSizeScale` | `Float` (0.5–3.0) | Perceived room size | | `OcclusionMultiplier` | `Float` (0–1) | How much walls occlude sound (0=fully open, 1=fully blocked) | | `LowPassCutoff` | `Float` (Hz) | Low-pass filter cutoff (simulates wall filtering) | | `bApplyToSFX` | `Boolean` | Apply this room to SFX bus? | | `bApplyToAmbience` | `Boolean` | Apply this room to ambience bus? | | `bApplyToDialogue` | `Boolean` | Apply this room to dialogue bus? | | `TransitionTime` | `Float` (seconds) | Crossfade time when entering this room | --- ## 3. Variables ### Configuration (Instance Editable, Expose On Spawn) | Variable | Type | Default | Category | Description | |----------|------|---------|----------|-------------| | `BusConfigs` | `Array` | `[SFX, Ambience, Music, Dialogue]` | `Audio Config` | Configuration per bus | | `RoomPresets` | `Array` | `DefaultPresets` | `Audio Config` | All room acoustic presets | | `DefaultRoomPreset` | `DA_RoomAcousticPreset` | `Outdoor` | `Audio Config` | Fallback room preset | | `AudioSettings` | `DA_AudioSettings` | `Defaults` | `Audio Config` | Data asset with volume defaults and bus config | ### Internal (Private / Protected) | Variable | Type | Default | Category | Description | |----------|------|---------|----------|-------------| | `ActiveRoomPreset` | `DA_RoomAcousticPreset` | `None` | `Room` | Current room acoustic profile | | `PreviousRoomPreset` | `DA_RoomAcousticPreset` | `None` | `Room` | Previous room (for crossfade) | | `RoomTransitionProgress` | `Float` | `0.0` | `Room` | Crossfade progress 0→1 | | `RoomTransitionDuration` | `Float` | `0.0` | `Room` | Current transition time remaining | | `RoomZoneStack` | `Array` | `Empty` | `Room` | Push/pop stack for nested room zones | | `bIsMuted` | `Boolean` | `false` | `State` | Global mute toggle | | `bIsPaused` | `Boolean` | `false` | `State` | Global pause state | | `BusInstances` | `Map` | `Empty` | `Bus` | Active bus audio components | | `ActiveSFXInstances` | `Array` | `Empty` | `SFX` | Pooled SFX playback instances | | `SFXPoolSize` | `Integer` | `32` | `SFX` | Max concurrent SFX instances | | `bIsCrossfading` | `Boolean` | `false` | `Room` | Room transition in progress | | `ActiveDialogueCount` | `Integer` | `0` | `Dialogue` | Number of active dialogue lines | --- ## 4. Functions ### Public Playback Functions #### `PlaySFX` → `UAudioComponent` - **Description:** Play spatial SFX through SFX bus at world location. Surface tag selects material impact variant. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Sound` | `UMetaSoundSource` | The MetaSound source to play | | `Location` | `FVector` | World position for spatialization | | `SurfaceTag` | `GameplayTag` (optional) | Physical surface tag for material EQ variant | - **Blueprint Authority:** Any - **Flow:** 1. Get or create SFX audio component from pool 2. Set sound to `SFXBus` MetaSound source 3. Set world location 4. If SurfaceTag valid: set `SurfaceEQ` parameter on MetaSound 5. Play audio component 6. Return component reference #### `PlaySFX2D` → `UAudioComponent` - **Description:** Play non-spatial SFX through SFX bus (UI sounds, heartbeat). - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Sound` | `UMetaSoundSource` | The MetaSound source to play | - **Blueprint Authority:** Any - **Flow:** Same as PlaySFX but without world location — 2D playback. #### `PlayAmbient` → `void` - **Description:** Crossfade ambient layer on Ambience bus. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Sound` | `UMetaSoundSource` | Ambient layer MetaSound | | `FadeIn` | `Float` (default 1.0) | Fade-in duration in seconds | - **Blueprint Authority:** Any - **Flow:** 1. Get Ambience bus audio component 2. Set new MetaSound source 3. Fade volume from 0 to target over `FadeIn` seconds 4. Route through current room reverb #### `StopAmbient` → `void` - **Description:** Fade out current ambient layer. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `FadeOut` | `Float` (default 2.0) | Fade-out duration in seconds | - **Blueprint Authority:** Any #### `SetMusicLayer` → `void` - **Description:** Set a music layer with intensity parameter. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `LayerIndex` | `Integer` | Which music layer (0-3: Calm/Tense/Action/Climax) | | `Sound` | `UMetaSoundSource` | MetaSound source for this layer | | `Intensity` | `Float` (default 0.5) | Layer blend intensity 0-1 | - **Blueprint Authority:** Any #### `StopMusicLayers` → `void` - **Description:** Fade out all music layers. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `FadeOut` | `Float` (default 2.0) | Fade-out duration in seconds | - **Blueprint Authority:** Any #### `PlayMusicStinger` → `void` - **Description:** One-shot music stinger on Music bus (overrides layers temporarily). - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Stinger` | `UMetaSoundSource` | Stinger MetaSound source | - **Blueprint Authority:** Any #### `PlayDialogue` → `void` - **Description:** Play dialogue line. Ducks other buses by configured amounts. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `DialogueSound` | `UMetaSoundSource` | Dialogue MetaSound source | | `Priority` | `Integer` (default 0) | 0=Bark, 10=Quest, 100=Cinematic | - **Blueprint Authority:** Any - **Flow:** 1. If `ActiveDialogueCount >= MaxConcurrentDialogue`, check priority 2. If new priority > lowest active: interrupt lowest, play new 3. Apply ducking: SFX -6dB, Ambience -12dB, Music -18dB 4. Route dialogue through Dialogue bus with spatialization #### `StopDialogue` → `void` - **Description:** Stop current dialogue playback. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `FadeOut` | `Float` (default 0.5) | Fade-out duration in seconds | - **Blueprint Authority:** Any ### Public Room Zone Functions #### `SetRoomPreset` → `void` - **Description:** Begin room transition with smooth crossfade of reverb/occlusion parameters. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Preset` | `DA_RoomAcousticPreset` | The new room acoustic preset | - **Blueprint Authority:** Any - **Flow:** 1. Push current preset onto `RoomZoneStack` 2. Set `PreviousRoomPreset = ActiveRoomPreset` 3. Set `ActiveRoomPreset = Preset` 4. Set `RoomTransitionDuration = Preset.TransitionTime` 5. Set `bIsCrossfading = true` 6. Fire `OnRoomPresetChanged(PreviousPreset, Preset)` 7. Begin per-tick interpolation (see `TickRoomTransition`) #### `SetRoomPresetInstant` → `void` - **Description:** Instant room switch — no crossfade. Used for void space entry, cutscenes. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Preset` | `DA_RoomAcousticPreset` | The new room preset to apply immediately | - **Blueprint Authority:** Any #### `GetCurrentRoomPreset` → `DA_RoomAcousticPreset` - **Description:** Returns the currently active room preset. - **Parameters:** *(none)* - **Blueprint Authority:** Any (Pure) #### `PopRoomPreset` → `void` - **Description:** Restores the previous room from the zone stack. Called by `BP_RoomAudioZone` on overlap end. - **Parameters:** *(none)* - **Blueprint Authority:** Any ### Public Settings / Control Functions #### `SetBusVolume` → `void` - **Description:** Set volume for a specific bus category. Called from settings menu. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Bus` | `E_AudioBusCategory` | Which bus to adjust | | `Volume` | `Float` (0–1) | Target volume | - **Blueprint Authority:** Any - **Flow:** 1. Set float parameter `Volume` on the corresponding MetaSound bus 2. Fire `OnBusVolumeChanged` 3. If `Bus == Master`, scale all buses proportionally #### `GetBusVolume` → `Float` - **Description:** Get current volume for a specific bus. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Bus` | `E_AudioBusCategory` | Which bus to query | - **Blueprint Authority:** Any (Pure) #### `SetMasterMute` → `void` - **Description:** Mute/unmute all audio globally. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `bMuted` | `Boolean` | True to mute, false to unmute | - **Blueprint Authority:** Any #### `SetPauseAll` → `void` - **Description:** Pause/resume all audio (used when pause menu opens/closes). - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `bPaused` | `Boolean` | True to pause, false to resume | - **Blueprint Authority:** Any - **Flow:** 1. Set `bIsPaused = bPaused` 2. Set Paused on all bus audio components 3. Fire `OnAudioPaused(bPaused)` #### `UpdateGameplayParameter` → `void` - **Description:** Set a gameplay-driven MetaSound float parameter on the relevant bus. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `ParameterName` | `FName` | MetaSound parameter name (e.g., `MusicIntensity`) | | `Value` | `Float` | Parameter value | - **Blueprint Authority:** Any #### `UpdateHeartRateAudio` → `void` - **Description:** Drives heartbeat SFX tempo and breathing layer intensity from StateManager data. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `BPM` | `Float` | Current heart rate in BPM (60-180) | | `Signal` | `E_PlayerVitalSignals` | Vital signal tier | - **Blueprint Authority:** Any - **Flow:** 1. Set `HeartRateBPM` parameter on SFX bus 2. Set `VitalSignal` parameter (0-4 enum as int) on SFX bus 3. If heartbeat SFX not already playing: start looping heartbeat MetaSound #### `UpdateFearAudio` → `void` - **Description:** Drives fear-reactive audio modulation from StressSystem + FearSystem. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `FearLevel` | `Float` (0–1) | Current fear intensity | | `Tier` | `E_StressTier` | Current stress tier | - **Blueprint Authority:** Any - **Flow:** 1. Set `FearIntensity` parameter on Ambience + SFX buses 2. Set `StressLevel` parameter on Ambience + Music buses 3. Apply fear effects: subtle pitch drop, reverb increase, random pan jitter ### Internal Functions (Private) #### `InitializeBuses` → `void` - **Description:** Create `UAudioComponent` for each bus category and attach MetaSound sources. Called during `Initialize`. - **Flow:** 1. For each `BusConfig` in `BusConfigs`: a. Create `UAudioComponent` b. Set sound to `BusConfig.MetaSoundSource` c. Configure spatialization from `BusConfig.bSpatialized` d. Attach attenuation settings e. Store in `BusInstances` map 2. Apply saved settings volumes to each bus 3. Set `ActiveRoomPreset = DefaultRoomPreset` #### `TickRoomTransition` → `void` - **Description:** Called on Tick — interpolates room reverb/occlusion/filter parameters during crossfade. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `DeltaTime` | `Float` | Frame time | - **Flow:** 1. If `!bIsCrossfading`: return 2. `RoomTransitionProgress += DeltaTime` 3. If `RoomTransitionProgress >= RoomTransitionDuration`: clamp to 1.0, set `bIsCrossfading = false` 4. Alpha = `RoomTransitionProgress / RoomTransitionDuration` 5. Interpolate: ReverbDensity, ReverbDecayTime, ReverbWetLevel, ReflectionsDelay, RoomSizeScale, OcclusionMultiplier, LowPassCutoff between `PreviousRoomPreset` and `ActiveRoomPreset` 6. Apply to relevant buses based on `bApplyToSFX` / `bApplyToAmbience` / `bApplyToDialogue` flags #### `GetOrCreateSFXInstance` → `UAudioComponent` - **Description:** Pool management — reuse an idle SFX audio component or create a new one. If pool is full (32), cull the oldest instance. - **Flow:** 1. Find first idle component in `ActiveSFXInstances` 2. If found: return it 3. If pool not full: create new, add to pool, return 4. If pool full: stop oldest active instance, reuse it #### `ApplyRoomToBus` → `void` - **Description:** Apply a room preset's reverb/occlusion/filter to a specific bus. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Bus` | `E_AudioBusCategory` | Target bus | | `Preset` | `DA_RoomAcousticPreset` | Room preset to apply | #### `ApplySettingsToBus` → `void` - **Description:** Read saved settings volume from `SS_SettingsSystem` and apply to the bus component. - **Parameters:** | Param | Type | Description | |-------|------|-------------| | `Bus` | `E_AudioBusCategory` | Target bus | --- ## 5. Event Dispatchers | Dispatcher | Parameters | Bind Access | Description | |------------|-----------|-------------|-------------| | `OnRoomPresetChanged` | `OldPreset: FName`, `NewPreset: FName` | `Public` | Fired when room acoustic profile changes | | `OnBusVolumeChanged` | `Bus: E_AudioBusCategory`, `Volume: Float` | `Public` | Fired when a bus volume is adjusted | | `OnAudioPaused` | `bPaused: Boolean` | `Public` | Fired on pause/resume — for visual feedback | | `OnMasterMuteChanged` | `bMuted: Boolean` | `Public` | Fired when global mute toggles | | `OnDialogueStarted` | `DialogueSound: UMetaSoundSource`, `Priority: Integer` | `Public` | Fired when dialogue begins (for subtitle triggering) | | `OnDialogueEnded` | `WasInterrupted: Boolean` | `Public` | Fired when dialogue ends | --- ## 6. Overridden Events / Custom Events ### Event: `Initialize` - **Description:** Called when subsystem is created. Loads config, initializes buses, binds settings. - **Flow:** 1. Load `DA_AudioSettings` if assigned 2. Call `InitializeBuses()` 3. Bind to `SS_SettingsSystem.OnSettingChanged` → route volume changes to `SetBusVolume` 4. Enable tick (required for room transition interpolation) 5. Apply saved settings volumes from persistent storage ### Event: `Deinitialize` - **Description:** Cleanup all audio components and unbind delegates. - **Flow:** 1. Stop all bus audio components 2. Clear `ActiveSFXInstances` pool 3. Unbind from `SS_SettingsSystem` 4. Set all references to null --- ## 7. Blueprint Graph Logic Flow ### Audio Playback Routing ```mermaid flowchart TD A[Any System: PlaySound] --> B[SS_AudioManager.PlaySFX / PlayAmbient / PlayMusic / PlayDialogue] B --> C{Route by Category} C -->|SFX| D[SFX Bus MetaSound Source] C -->|Ambience| E[Ambience Bus MetaSound Source] C -->|Music| F[Music Bus MetaSound Source] C -->|Dialogue| G[Dialogue Bus MetaSound Source] D --> H[Room Zone Reverb] E --> H F --> H G --> H H --> I[Master Bus] I --> J[Player Settings Volume Sliders] J --> K[Audio Output] L[BPC_StateManager.HeartRate] -->|Parameter| D M[BPC_StressSystem.StressTier] -->|Parameter| E N[BPC_PacingDirector.IntensityBand] -->|Parameter| F O[BPC_AccessibilitySettings] -->|Volume Sliders| I ``` ### Settings Flow ```mermaid sequenceDiagram participant SM as WBP_SettingsMenu participant SS as SS_SettingsSystem participant AM as SS_AudioManager participant Bus as MetaSound Bus SM->>SS: SetFloat(Settings.Audio.SFXVolume, 0.8) SS->>SS: Save to persistent settings SS->>AM: SetBusVolume(SFX, 0.8) AM->>Bus: Set Float Parameter 'Volume' = 0.8 Bus->>Bus: Apply to output Note over AM: On game launch: AM->>SS: GetFloat(Settings.Audio.SFXVolume) SS->>AM: 0.8 AM->>Bus: Set Float Parameter 'Volume' = 0.8 ``` --- ## 8. Mix Bus Architecture ``` ┌─────────────────────────────────────────────────────┐ │ MASTER BUS │ │ (MS_MasterBus) │ │ - Master Volume (settings) │ │ - Limiter / Compressor │ │ - Global Mute │ │ - Accessibility: Mono collapse, L/R balance │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ SFX BUS (MS_SFXBus) │ │ │ │ - 3D Spatialization │ │ │ │ - Per-source occlusion (line trace) │ │ │ │ - Distance attenuation │ │ │ │ - Surface material EQ (concrete/metal/wood) │ │ │ │ - Heart rate BPM → breathing blend param │ │ │ │ - Max 32 concurrent voices │ │ │ │ - Ducking: -6dB when Dialogue active │ │ │ │ Sub-inputs: │ │ │ │ • WeaponFire (limit 8 voices) │ │ │ │ • Footsteps (limit 4 voices per actor) │ │ │ │ • Impacts (limit 8 voices) │ │ │ │ • UI SFX (2D, no spatialization) │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ AMBIENCE BUS (MS_AmbientBus) │ │ │ │ - Stereo (no 3D) │ │ │ │ - 4-layer crossfade (room tone, wind, drone) │ │ │ │ - Stress tier → layer blend weights │ │ │ │ - Room reverb applied │ │ │ │ - Ducking: -12dB when Dialogue active │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ MUSIC BUS (MS_MusicBus) │ │ │ │ - Stereo (no 3D) │ │ │ │ - 4 intensity layers (Calm/Tense/Action/Climax)│ │ │ │ - PacingDirector.IntensityBand → layer blend │ │ │ │ - Stingers (one-shot overrides) │ │ │ │ - Ducking: -18dB when Dialogue active │ │ │ │ - Combat detected → crossfade to Action │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────┐ │ │ │ DIALOGUE BUS (MS_DialogueBus) │ │ │ │ - 3D (for in-world dialogue) │ │ │ │ - Priority system (Cinematic > Quest > Bark) │ │ │ │ - Ducks all other buses │ │ │ │ - Lip-sync amplitude passthrough │ │ │ │ - Radio/phone EQ preset toggle │ │ │ │ - Max 2 concurrent dialogue voices │ │ │ │ - Settings: DialogueVolume → bus volume │ │ │ └──────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────┘ ``` --- ## 9. Settings Integration ### Player-Facing Volume Sliders | Setting | GameplayTag | Bus Controlled | MetaSound Parameter | |---------|------------|----------------|---------------------| | Master Volume | `Settings.Audio.MasterVolume` | Master Bus | `Volume` (0–1) | | SFX Volume | `Settings.Audio.SFXVolume` | SFX Bus | `Volume` (0–1) | | Music Volume | `Settings.Audio.MusicVolume` | Music Bus | `Volume` (0–1) | | Ambience Volume | `Settings.Audio.AmbientVolume` | Ambience Bus | `Volume` (0–1) | | Dialogue Volume | `Settings.Audio.DialogueVolume` | Dialogue Bus | `Volume` (0–1) | ### Accessibility Settings | Setting | Effect | |---------|--------| | Mono Audio | Collapse all buses to mono on Master Bus | | Subtitle Background Opacity | (UI — not audio, handled by WBP_AccessibilityUI) | | Audio Cues for UI | Play additional confirmation SFX on button press | | Left/Right Balance | Pan parameter on Master Bus (for single-ear players) | | Visual Heartbeat Indicator | Alternative to audio heartbeat for deaf players — UI pulse based on `BPC_StateManager.CurrentHeartRate` | --- ## 10. Gameplay Parameter Modulation MetaSound parameters driven by gameplay state: | Parameter Name | Source System | Bus | Range | Effect | |---------------|--------------|-----|-------|--------| | `HeartRateBPM` | `BPC_StateManager` (130) | SFX | 60–180 | Controls heartbeat SFX tempo + breathing layer intensity | | `VitalSignal` | `BPC_StateManager` (130) | SFX | 0–4 (enum) | Selects heartbeat sound variant (normal/elevated/critical/erratic) | | `StressLevel` | `BPC_StressSystem` (10) | Ambience, Music | 0–1 | Blends tension layers, adds distortion | | `FearIntensity` | `BPC_FearSystem` (90) | Ambience, SFX | 0–1 | Lowers pitch, increases reverb, random pan jitter | | `MusicIntensity` | `BPC_PacingDirector` (98) | Music | 0–1 (4 bands) | Crossfades between Calm/Tense/Action/Climax layers | | `PlayerHealth` | `BPC_HealthSystem` (08) | SFX | 0–1 | Low-pass filter on all SFX as health drops (muffled hearing) | | `IsUnderwater` | (Physics volume) | Master | bool | Apply underwater EQ + muffled low-pass | | `CombatActive` | `BPC_StateManager` (130) | Music | bool | Stinger trigger + immediate intensity ramp | | `TimeOfDay` | World state | Ambience | 0–1 (dawn→dusk) | Ambient layer blend (day birds → night crickets) | --- ## 11. Communication Matrix | Who Talks | How | What Is Sent | |-----------|-----|-------------| | Any System | `SS_AudioManager.PlaySFX()` | `UMetaSoundSource`, `FVector Location`, `GameplayTag SurfaceTag` | | Any System | `SS_AudioManager.PlaySFX2D()` | `UMetaSoundSource` (UI sounds) | | Any System | `SS_AudioManager.PlayAmbient()` | `UMetaSoundSource`, `Float FadeIn` | | Any System | `SS_AudioManager.SetMusicLayer()` | `Integer LayerIndex`, `UMetaSoundSource`, `Float Intensity` | | Any System | `SS_AudioManager.PlayDialogue()` | `UMetaSoundSource`, `Integer Priority` | | `BP_RoomAudioZone` (133) | `SS_AudioManager.SetRoomPreset()` | `DA_RoomAcousticPreset` | | `WBP_SettingsMenu` (57) | `SS_SettingsSystem.SetFloat()` → `SS_AudioManager.SetBusVolume()` | `E_AudioBusCategory`, `Float Volume` | | `BPC_StateManager` (130) | `SS_AudioManager.UpdateHeartRateAudio()` | `Float BPM`, `E_PlayerVitalSignals` | | `BPC_StressSystem` (10) | `SS_AudioManager.UpdateFearAudio()` | `Float FearLevel`, `E_StressTier` | | `BPC_PacingDirector` (98) | `SS_AudioManager.UpdateGameplayParameter("MusicIntensity")` | `Float 0–1` | | `BPC_HealthSystem` (08) | `SS_AudioManager.UpdateGameplayParameter("PlayerHealth")` | `Float 0–1` | | `SS_AudioManager` | `Dispatcher: OnRoomPresetChanged` | `OldPreset: FName`, `NewPreset: FName` | | `SS_AudioManager` | `Dispatcher: OnBusVolumeChanged` | `Bus: E_AudioBusCategory`, `Volume: Float` | | `SS_AudioManager` | `Dispatcher: OnAudioPaused` | `bPaused: Boolean` | | `SS_AudioManager` | `Dispatcher: OnDialogueStarted` | `UMetaSoundSource`, `Integer Priority` (for subtitle system) | | `SS_AudioManager` | `WBP_AccessibilityUI` (45) | Heart rate BPM for visual heartbeat indicator | --- ## 12. Migration: Replacing Deprecated BPC_AudioAtmosphereController (95) | Old (BPC_AudioAtmosphereController) | New (SS_AudioManager) | |-------------------------------------|----------------------| | `PlayOneShotSFX(Sound, Location)` | `SS_AudioManager.PlaySFX(Sound, Location)` | | `PlayAmbientSound(Sound, FadeIn)` | `SS_AudioManager.PlayAmbient(Sound, FadeIn)` | | `SetMusicLayer(LayerIndex, Sound, Volume)` | `SS_AudioManager.SetMusicLayer(LayerIndex, Sound, Intensity)` | | `PlayDialogue(DialogueSound)` | `SS_AudioManager.PlayDialogue(DialogueSound, Priority)` | | `SetReverb(Reverb, WetLevel)` | `SS_AudioManager.SetRoomPreset(Preset)` via `BP_RoomAudioZone` | | `SetOcclusion(Intensity)` | Automatic — per-source line trace in MetaSound bus | | `FearReactiveAudioUpdate(Fear, Threshold)` | `SS_AudioManager.UpdateFearAudio(Fear, Tier)` | | `HandleRoomChange(RoomAcousticPreset)` | `BP_RoomAudioZone.OnActorBeginOverlap` | | `ActiveAudioPreset` / `TargetAudioPreset` | `SS_AudioManager.ActiveRoomPreset` | | `Master/SFX/Music/Ambient/DialogueVolumeModifier` | `SS_AudioManager.SetBusVolume()` bound to `SS_SettingsSystem` | ### Phase-Out Strategy 1. **Phase 14a:** Create `SS_AudioManager` + `BP_RoomAudioZone` + all MetaSound patches (CURRENT) 2. **Phase 14b:** Update all 129 systems to call `SS_AudioManager` instead of raw `UGameplayStatics::PlaySound*` 3. **Phase 14c:** Convert all `USoundBase` references to `UMetaSoundSource` in Data Assets 4. **Phase 14d:** Remove `BPC_AudioAtmosphereController` (95) from build --- ## 13. Validation / Testing Checklist - [ ] `PlaySFX(Sound, Location)` spawns at correct world position with spatialization - [ ] `PlaySFX2D(Sound)` plays without spatialization (UI sounds) - [ ] `PlayAmbient(Sound)` crossfades ambient layer smoothly - [ ] `SetMusicLayer(idx, Sound, intensity)` blends music layers correctly - [ ] `PlayDialogue(Sound, Priority)` ducks other buses by correct amounts - [ ] `BP_RoomAudioZone` on overlap → `SetRoomPreset` transitions reverb smoothly - [ ] Nested room zones use stack correctly (push/pop) - [ ] Room transition crossfade interpolates reverb parameters - [ ] `SS_SettingsSystem` volume changes apply to correct bus - [ ] Master Mute silences all buses - [ ] Pause/Resume toggles all bus audio components - [ ] `UpdateHeartRateAudio(BPM)` modulates heartbeat tempo in MetaSound - [ ] `UpdateFearAudio(0.8, Terrified)` applies fear distortion - [ ] SFX pooling limits to 32 concurrent (oldest culled when full) - [ ] Dialogue priority system: higher priority interrupts lower - [ ] Accessibility mono audio collapses all buses - [ ] Accessibility L/R balance pans correctly on Master Bus - [ ] Edge case: Rapid room zone enter/exit doesn't cause audio glitches - [ ] Edge case: SS_AudioManager handles null MetaSound source gracefully - [ ] Edge case: Settings loaded before first sound plays (Init order) - [ ] Edge case: `SetMasterMute(true)` while crossfading — immediate mute --- ## 14. Reuse Notes - `SS_AudioManager` is the **ONLY** entry point for audio playback. Systems must never call `UGameplayStatics::PlaySound*` directly. - Game instance subsystem — exists for the entire game session. No per-level reinitialization needed. - SFX pool of 32 ensures no unbounded audio component creation. Reuse is automatic. - Room zone stack supports arbitrarily nested zones (room within building within cave). - All gameplay parameters are soft-referenced — if a source system (e.g., `BPC_PacingDirector`) is not present, `UpdateGameplayParameter` fails gracefully (log warning, no crash). - MetaSound sources can be hot-reloaded in-editor while the game is running for rapid sound design iteration. --- *Blueprint Spec: SS_AudioManager — Single entry point for all MetaSounds audio. Replaces BPC_AudioAtmosphereController (95). Architecture document: [`metasounds-audio-system.md`](../../architecture/metasounds-audio-system.md)*