Pepper.SFX
All Guidance pages

Guidance / API reference

Reverb Send Buses

The “wet path” complement to occlusion. Source-side: voices in a tagged zone send to a per-zone reverb bus. Listener-side: each bus’s character is defined by its own ReverbSendBus asset (the single source of truth) and driven onto the mixer each tick — parametric buses via six exposed SFX Reverb params, convolution buses via a native impulse-response plugin (§15.14). See Manual chapter 15 for architecture and design rationale.


ReverbSendBus

Namespace: AudioSystem Inheritance: ScriptableObject Menu: Create > Audio System > Reverb Send Bus

One acoustic-space identity per asset. Owns one mixer group on the project’s voice mixer, hosting one SFX Reverb effect with six exposed parameters that the listener-side driver writes per tick. The asset’s name is the bus id.

Properties — Mixer Wiring

public AudioMixer ReverbMixer { get; }           // mixer this bus lives on
public AudioMixerGroup ReverbBus { get; }        // mixer group this bus owns (auto-filled by Generate)
public AudioMixerGroup OutputDestination { get; } // optional cross-mixer output target
public AudioMixerGroup ParentGroup { get; }      // optional parent for the "ReverbsWet" return-bus convention
public string MixerGroupGuid { get; }            // hidden idempotency key for re-Generate rename-safety

Properties — Parametric Defaults

The 14 SFX Reverb parameters split into Basic and Advanced. Basic surfaces in the inspector by default; Advanced lives behind an EditorPrefs-backed foldout.

// Basic (levels in millibels, mB, like Unity's SFX Reverb: 0 = full, -10000 = silent)
public float DryLevel { get; }       // -10000..0 mB. Default -10000 (wet-only).
public float Room { get; }           // -10000..0 mB. Default 0 (audible).
public float DecayTime { get; }      //   0.1..20 s. Default 1.49
public float ReverbLevel { get; }    // -10000..2000 mB. Default 200

// Advanced
public float RoomHF { get; }            // -10000..0 mB. Default 0
public float RoomLF { get; }            // -10000..0 mB. Default 0
public float DecayHFRatio { get; }      // 0.1..2 ratio. Default 0.83
public float ReflectionsLevel { get; }  // -10000..1000 mB. Default -2602
public float ReflectionsDelay { get; }  // 0..0.3 s. Default 0.007
public float ReverbDelay { get; }       // 0..0.1 s. Default 0.011
public float HFReference { get; }       // 1000..20000 Hz. Default 5000
public float LFReference { get; }       // 20..1000 Hz. Default 250
public float Diffusion { get; }         // 0..100 %. Default 100
public float Density { get; }           // 0..100 %. Default 100

Only the six listener-relevant parameters (ReverbLevel, DecayTime, Room, RoomHF, DecayHFRatio, ReflectionsLevel) are exposed to the runtime driver. The other eight describe bus identity and stay at the SO-authored snapshot defaults.

Properties — Convolution (Phase 3.2, Windows)

When UseConvolution is true the bus uses the native convolution plugin instead of SFX Reverb, and the parametric defaults above are ignored. See Manual §15.14 for the authoring walkthrough and beta caveats.

public bool UseConvolution { get; }          // false = parametric SFX Reverb; true = convolution plugin
public AudioClip ImpulseResponse { get; }    // the IR to convolve; must be CPU-readable (Decompress On Load / PCM)
public float ConvolutionWetTrimDb { get; }   // -80..+20 dB wet trim, 0 = unity
public int ConvolutionSlot { get; }          // index in the plugin's IR slot table; -1 = unassigned (hidden; Generate assigns it)

ConvolutionSlot is [HideInInspector] — ReverbAutoCreator assigns a stable free slot at Generate, and both the authored “IR Slot” effect param and the runtime IR upload (AudioManager.UploadConvolutionIRs) read it. Designers never set it.

Identity Helpers

public string BusName { get; }                    // sanitized form of asset.name, safe for mixer param ids
public string ParamName(string suffix);           // "Reverb_<BusName>_<suffix>"

public const string SuffixWet           = "Wet";           // → ReverbLevel
public const string SuffixDecay         = "Decay";         // → DecayTime
public const string SuffixRoom          = "Room";          // → Room
public const string SuffixRoomHF        = "RoomHF";        // → RoomHF
public const string SuffixDecayHFRatio  = "DecayHFRatio";  // → DecayHFRatio
public const string SuffixReflections   = "Reflections";   // → ReflectionsLevel

public void GetDefaultProfile(AudioReverbProfile dest);   // non-allocating copy of SO defaults into dest
public static string SanitizeBusName(string raw);

ParamName("Wet") for a bus named “Bathroom” returns "Reverb_Bathroom_Wet" — that’s the exposed mixer parameter the runtime driver writes to.

GetDefaultProfile is the primary (and only) source for AudioManager.DriveReverbBusParams: every parametric bus is driven from its own SO character each tick, unconditionally — no zone lookup. (Before the 2026-05-21 source-of-truth unification this was only a fallback “when no zone feeds the bus”; the zone-driven path was removed.) Convolution buses skip the driver entirely.

Editor Surface

#if UNITY_EDITOR
public void EditorSetReverbBus(AudioMixerGroup group);
public void EditorSetOutputDestination(AudioMixerGroup group);
public void EditorSetMixerGroupGuid(string guid);
public void EditorSetConvolutionSlot(int slot);   // ReverbAutoCreator assigns the IR slot at Generate
#endif

Called by the per-asset inspector’s Generate path. Runtime treats the SO as read-only.


ReverbSendBusRegistry

Namespace: AudioSystem Inheritance: ScriptableObject Menu: Create > Audio System > Reverb Send Bus Registry

Flat list of every ReverbSendBus asset in the project. One per project. Reference it from AudioManager ▸ Reverb Send Bus Registry.

Properties

public IReadOnlyList<ReverbSendBus> Buses { get; }
public int BusCount { get; }

Methods

public ReverbSendBus FindByName(string busName);  // case-sensitive lookup by ReverbSendBus.BusName

Editor Surface

#if UNITY_EDITOR
public void EditorSetBuses(List<ReverbSendBus> entries);
#endif

Called by the Reverb Send Buses window’s Refresh button after re-scanning the project for t:ReverbSendBus assets.


AudioReverbProfile

Namespace: AudioSystem.Propagation Inheritance: [Serializable] public class

Reverb character parameters — six fields, each matching one of the listener-relevant SFX Reverb parameters. Authored on a ReverbSendBus SO (the source of truth) and copied into a non-allocating scratch buffer by the bus-params driver; also interpolatable across portal blend regions by the per-source ambient path.

Fields

[Range(-10000f, 0f)]   public float Room             = -10000f;  // dB, overall wet gain
[Range(-10000f, 0f)]   public float RoomHF           = 0f;       // dB, HF tilt
[Range(0.1f, 20f)]     public float DecayTime        = 1.49f;    // seconds
[Range(0.1f, 2f)]      public float DecayHFRatio     = 0.83f;    // ratio
[Range(-10000f, 1000f)] public float ReflectionsLevel = -2602f;  // dB, early reflections
[Range(-10000f, 2000f)] public float ReverbLevel      = 200f;    // dB, late reverb tail

Default (Room = -10000) is inaudible — zones that don’t author a profile produce zero behavior change. Set Room toward 0 dB to enable. This default is the profile’s own: a new ReverbSendBus asset starts at Room = 0 (audible).

Methods

public static void Lerp(AudioReverbProfile a, AudioReverbProfile b, float t, AudioReverbProfile dest);
public void CopyFrom(AudioReverbProfile src);
public bool IsEffectivelySilent { get; }   // true when Room ≤ -9999 dB
public static readonly AudioReverbProfile Off;  // shared singleton, Room = -10000

Lerp and CopyFrom write into dest rather than returning a fresh instance, so the manager can blend across portal regions without per-frame allocation.


AudioZone reverb fields

AudioZone (see Propagation section) has one reverb-relevant field — routing only:

public AudioMixerGroup ReverbBus { get; }       // routing target (source-side); null when unassigned
  • ReverbBus — the mixer group voices physically in this zone send to. Drag in a ReverbSendBus’s ReverbBus field. Leave null for zones with no dedicated reverb (the source-side send is skipped for sources in that zone). Returns null at runtime when explicitly left empty.

Removed 2026-05-21. AudioZone.ReverbProfile (the per-zone character field) was deleted in the source-of-truth unification. A bus’s character now lives entirely on its ReverbSendBus SO; the zone only routes. The entryFadeMeters field (general propagation, see the AudioZone inspector table) still governs how the send fades across the zone boundary.

Multi-zone-to-bus aggregation is supported — several zones can share a ReverbBus. Because character is per-bus now, all zones feeding a given bus produce that bus’s single SO character (no per-zone variation on a shared bus).


AudioManager Reverb-Sends API

Inspector Fields

Field Default Description
reverbSendBusRegistry (ReverbSendBusRegistry) null Project’s bus registry. Reverb-sends driver is gated on this being assigned and non-empty.
reverbSendsUpdateInterval (range 0.005–0.5) 0.05 Seconds between reverb-sends + bus-params driver ticks (default ≈ 20 Hz).

Property

public ReverbSendBusRegistry ReverbSendBusRegistry { get; }

Synchronous Send Write

public void WriteReverbSendsImmediate(AudioVoiceEnhanced voice, AudioContainer container);

Synchronous per-voice send-level write, called by AudioContainer.ConfigureAudioSource right after the source has been positioned and routed. Ensures a voice’s first audio frame already carries correct reverb routing, without waiting for the next driver tick (≈ 50 ms latency).

Safe to call when the registry is empty / mixer missing / voice has no slot / container opts out — the internal guards short-circuit and the call becomes a no-op.

Most projects never call this directly — AudioContainer.ConfigureAudioSource does. Surfaced publicly for custom playback paths that bypass the standard Play() route.

From the Pepper.SFX 3.1 guides (API_REFERENCE.md). Something wrong or unclear? Tell me.