Pepper.SFX

Features

Parameters, states and switches

Drive sounds from game values: per-object parameters with smoothing, built-in distance and angle, switches and mix states.

A car’s engine follows its RPM, footsteps change with the ground, and the mix shifts when the player dives underwater. Pepper.SFX gives each a home: parameters for numbers, switches for choices and states for game modes, set from code or from an event’s actions.

How it works

  • Parameter assets (RTPCs) are named numbers with a range, a unit label, a default and Smoothing: None, Rate or Ease, with separate rise and fall. The string API (SetRTPC("CombatIntensity", 0.7f)) and an asset with that Parameter Name are the same parameter.
  • Three scopes. A value can be set on one sound’s handle, on an Audio Emitter (every sound on one car), or globally. A sound reads the closest one that has a value, so two cars can play the same engine Blend at different RPMs.
  • Built-in values. Set a parameter’s Value From to Distance, Approach Speed or Angle and Pepper works it out for each sound, from the listening point.
  • Parameter Curves on any container drive its volume (dB), pitch (cents), low-pass or high-pass (Hz) from a parameter, with no code. A Blend Container crossfades its layers along one.
  • Values at post. PostValues carries up to four parameter values and two switch values, so a one-shot’s first sample hears them.
  • Switch Group assets list a switch’s values (Asphalt, Gravel, Grass). Set them globally, per emitter or per handle, and a Switch Container plays the matching child. When Switch Changes (Next Play Only, Crossfade, Restart) decides what a playing loop does. A group can also be Driven By a parameter through ranges, with hysteresis.
  • Audio State assets belong to a State Group, and one state per group is active. A state sets bus volumes, switches, RTPCs and exposed mixer effect values, easing the levels over a transition time.

Example

using UnityEngine;
using AudioSystem;

[RequireComponent(typeof(AudioEmitter))]
public class CarAudio : MonoBehaviour
{
    [SerializeField] private AudioEvent engineEvent;        // a Blend Container on RPM
    [SerializeField] private AudioEvent impactEvent;
    [SerializeField] private AudioParameter rpm;            // 800-7000, Smoothing: Ease
    [SerializeField] private AudioParameter impactStrength; // 0-1
    [SerializeField] private AudioSwitchGroup surface;      // Asphalt, Gravel, Grass

    private AudioEmitter emitter;

    void Start()
    {
        emitter = GetComponent<AudioEmitter>();
        emitter.Post(engineEvent);
    }

    public void UpdateEngine(float engineRpm) => emitter.SetParameter(rpm, engineRpm);  // this car only

    public void OnSurfaceChanged(string value) => emitter.SetSwitch(surface, value);

    void OnCollisionEnter(Collision collision)
    {
        float strength = Mathf.Clamp01(collision.relativeVelocity.magnitude / 20f);
        emitter.Post(impactEvent, PostValues.Of(impactStrength, strength));
    }
}

Each car keeps its RPM and surface on its Audio Emitter, so many cars share one engine event, and the impact’s strength travels with the post. A game mode is one global call: AudioManager.Instance.SetState("Underwater", 1.5f).

Setting it up

  1. Assets > Create > Audio System > Parameter. Set Unit Label, Min Value, Max Value, Default Value and Smoothing.
  2. Assets > Create > Audio System > Switch Group. List its Values and set a Default Value.
  3. On a container, add a Parameter Curve, set a Blend Container’s Blend Parameter, or set a Switch Container’s Switch Group.
  4. Add Add Component > Audio System > Audio Emitter to each object that needs its own values, and post its sounds on it.
  5. Assets > Create > Audio System > Audio State. Set its State Name and State Group, then the bus volumes, switches and RTPCs it changes. Keep states in Resources/Audio/States, or list them in an Audio Event Registry.

Good to know

  • Values set by name (SetRTPC, TransitionRTPC) are never smoothed. Smoothing applies to writes through the asset (SetParameter, RampParameter).
  • Code can’t set a built-in value: SetParameter on one is ignored with a warning.
  • A value that isn’t a number (NaN or infinity) is refused with a warning, and sounds keep the last good value.
  • Setting a state applies only its own values: nothing from the previous state is undone, so give each state in a group a value for everything its siblings change. The exception is Bus Volume Mode Offset: its offsets go back when the state ends.
  • Parameters update once a frame, after every LateUpdate, so a value written anywhere this frame is heard this frame.
  • In Play mode, Window > Audio System > Live View shows every Audio Emitter’s values and sounds.

Learn more