Pepper.SFX

Features

Buses and mixing

A bus hierarchy for group volume, ducking, pausing, player volume sliders and voice caps, set up as assets.

Players expect a music slider, dialogue they can hear over explosions, and a pause menu that stops the world but not its own clicks. In Pepper.SFX each of those is a setting on an Audio Bus asset. Set it once, and every event routed to that bus follows it.

How it works

  • Hierarchy. Each bus has a Parent Bus. Its level (Volume, plus any state’s offset, plus the player’s volume, in dB) is multiplied by its ducking, its curves and its parents’ levels, so muting a bus mutes its children. A bus can also feed a Unity Audio Mixer Group for Unity’s effects.
  • Ducking. A trigger bus lists Ducking Targets, each with a Duck Amount in dB, plus attack and release times. A TriggerDucking action or bus.TriggerDucking(holdSeconds) starts it. When ducks overlap, the deepest wins, so a short UI duck can’t cut a dialogue duck short.
  • Parameter Curves on a bus. A bus’s volume, and a low- or high-pass on its Mixer Group, can follow a parameter, such as nitro sweeping the other cars’ low-pass.
  • Pausing a bus. Pause() fades the bus and its child buses out over about 25 ms and holds their place without keeping real voices. Resume() carries on, every layer in phase. While Paused decides whether one-shots posted meanwhile are dropped or held.
  • Player volume. PlayerVolumeDb is a separate level for a settings menu. It is never saved into the asset, and no state undoes it.
  • Voice caps. Max Real Voices caps a bus’s real voices. Over it, the least important sounds go virtual, never ended, and come back in step.
  • States. An Audio State can move bus levels: Set Level writes the bus’s Volume, Offset moves it and puts it back when the state ends.
  • Mixer window (full version only): Window > Audio System > Mixer shows every bus as a fader with mute and solo; changes are saved and can be undone.

Example

using UnityEngine;
using AudioSystem;

public class MixControls : MonoBehaviour
{
    [SerializeField] private AudioBus musicBus;
    [SerializeField] private AudioBus worldBus;     // parent of Vehicles, Ambience...
    [SerializeField] private AudioBus dialogueBus;  // ducks Music when triggered

    // Settings sliders, 0 to 1.
    public void SetMasterVolume(float slider) => AudioManager.Instance.SetMasterVolume(slider);
    public void SetMusicVolume(float slider) =>
        musicBus.PlayerVolumeDb = AudioSystem.AudioExtensions.LinearToDb(slider);

    public void OpenPauseMenu()
    {
        Time.timeScale = 0f;
        worldBus.Pause();       // the world holds; the menu's own buses play on
    }

    public void ClosePauseMenu()
    {
        worldBus.Resume();
        Time.timeScale = 1f;
    }

    // Duck the music while a voice line plays.
    public void OnLineStarted(float lineSeconds) => dialogueBus.TriggerDucking(lineSeconds);
}

Sliders set the player’s volume, so a mix state never fights the settings menu. Pausing the World bus holds the game while the UI and menu-music buses outside it keep playing.

Setting it up

  1. Assets > Create > Audio System > Audio Bus for Master, then Music, SFX, Dialogue and so on, each with its Parent Bus set.
  2. On the AudioManager, assign the Master Bus and add every bus to Buses, so lookups by name find them.
  3. Set the Target Bus on each event’s Play action.
  4. For ducking, tick Enable Ducking on the Dialogue bus, add Music to its Ducking Targets, and give the dialogue event a TriggerDucking action (Target Bus: Dialogue, Fade Duration: the hold time).
  5. For a filter curve, give the bus a Mixer Group, add a Low Pass Parameter Curve, and click Add Low Pass to Mixer Group in the bus inspector.

Good to know

  • Ducking is triggered, not detected from what the bus plays. A duck runs on the target bus’s Ducking Time Mode: Scaled, the default, freezes at time scale 0, so set Unscaled on buses ducked during a pause.
  • A raise can’t take a sound past its AudioSource’s full volume, so mix with headroom.
  • Bus curves read only a parameter’s global value, and pitch curves are ignored on a bus. If the inspector button can’t edit the mixer in your Unity version, it logs the manual steps.
  • Unity’s Web audio has no mixer effects, so bus filter curves don’t work in Web builds.
  • On Unity 6.3, write AudioSystem.AudioExtensions in full: Unity added its own AudioExtensions.

Learn more