639 lines
31 KiB
Markdown
639 lines
31 KiB
Markdown
# 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)*
|