# 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<S_AudioBusConfig>` | `[SFX, Ambience, Music, Dialogue]` | `Audio Config` | Configuration per bus |
| `RoomPresets` | `Array<DA_RoomAcousticPreset>` | `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<DA_RoomAcousticPreset>` | `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<E_AudioBusCategory, UAudioComponent>` | `Empty` | `Bus` | Active bus audio components |
| `ActiveSFXInstances` | `Array<UAudioComponent>` | `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)*
