Skip to content

AudioPlayer

Axwabo edited this page Feb 6, 2026 · 7 revisions

AudioPlayer

To play audio, create an AudioPlayer and use extension methods (e.g. UseFile or UseShortClip) to specify what it should play. The AudioPlayer is always attached to a speaker.

Most extension methods return the player itself, so you can chain calls (builder pattern).

For more granular control, use audio processors or a custom ISampleProvider

How It Works

Audio samples are provided by a sample provider

The player keeps track of how many packets need to be sent using Time.deltaTime

At a stable 60 TPS, this means 1-2 packets every frame. 1 packet is 480 samples. When no samples are read, the buffer is cleared

The player reads audio if IsPaused is false and the provider is not null, regardless of send engine or output monitor

Right before encoding, the samples may be amplified regardless of provider or monitor.

Note

When the component is disabled, it will be reset, and the Destroyed event will be invoked. This usually happens when the speaker is pooled

Execution Sequence

When a packet needs to be processed (at least 480 samples should be read), the method runs as follows, repeating until less than 480 samples are needed:

  1. Return if IsPaused is true or if the SampleProvider is null
  2. Read from the provider
  3. If 0 samples were read:
    • Set HasEnded to true
    • Clear the buffer
    • Invoke the OutputMonitor's OnEmpty method
    • Invoke the NoSamplesRead event
    • Return
  4. Clear the remainder of the buffer if less than 480 samples were read
  5. Invoke the OutputMonitor's OnRead method
  6. Return if the SendEngine is null
  7. Amplify the read samples if MasterAmplification is not 1
  8. Encode the samples with Opus
  9. Pass the encoded data as an AudioMessage to the SendEngine

Instantiation

You can obtain an audio player by calling:

  • AudioPlayerPool.Rent - recommended method, read more here
  • AudioPlayer.Create
  • the AddAudioPlayer extension method on a SpeakerToy

Properties

SampleProvider

This is the interface which provides audio samples. May be null.

When changing the provider, the current one (if set) may be disposed automatically. See: OwnsProvider

The OwnsProvider property is set to whether the new provider is an IAudioProcessor when changing the provider.

Important

The provider (if not null) must have a wave format matching the following criteria:

  • 48000 Hz sample rate
  • mono (1 channel)
  • IEEEFloat encoding

Use the WithProvider extension method to automatically downmix & resample to the correct format.

OwnsProvider

Whether to dispose of the SampleProvider when it's changed, and when the player is pooled/destroyed.

This property is automatically set when the SampleProvider changes.

Speaker

The SpeakerToy this component is attached to (read-only).

SendEngine

The send engine that will be used to broadcast audio messages. Set to null to disable encoding and broadcasting.

Defaults to SendEngine.DefaultEngine

OutputMonitor

An optional packet monitor that can analyze the outputted samples. null by default.

The output monitor (if set) is invoked even if no send engine is specified.

MasterAmplification

A volume scalar to multiply the samples by before encoding. The output monitor is not affected by this, meaning it'll observe the samples from the provider as if they were not amplified after reading.

This property lets you amplify the volume further without wrapping all providers into a VolumeSampleProvider

Note

This property is different from the volume of the SpeakerToy itself. It can be used to always amplify audio, allowing for easier personalization

IsPaused

When set to true, the player will pause, no updates will be performed.

HasEnded

true if the playback has finished during the previous update (fewer samples were read than requested).

Note

This value is not updated if the player is paused or if the provider is null.

Id

Gets or sets the controller ID of the speaker. If multiple speakers share the same ID, audio from the player will be heard from each of them.

See also: grouping speakers

AlwaysRead

true by default.

When disabled, the provider will be set to null when it reaches the end.

Events

NoSamplesRead

Invoked when the provider reads 0 samples.

Before the event is invoked, HasEnded is set to true, the buffer is cleared, and the monitor's OnEmpty method is called.

Destroyed

Invoked when the component is destroyed. The event also gets called when the component is disabled (when the speaker is pooled).

Methods

ClearBuffer

Sets the remaining time to 0 and clears the single input's buffer if it's a BufferedSampleProvider

Destroy

Destroys the game object, removing the speaker and all of its components (including the audio player).

Exception Handling

If the provider throws an exception, it is logged with Unity's logger. The player treats this state as if no samples were read.

You can find Unity logs in the LocalAdmin logs directory:

  • Linux: ~/.config/SCP Secret Laboratory/LocalAdminLogs/<port>
  • Windows: %appdata%/SCP Secret Laboratory/LocalAdminLogs/<port>

Advanced

The Mixer takes precedence over the AudioQueue if using both of them. See below.

Mixing

Use the Mixer play multiple sources via a single AudioPlayer

Extension methods make using the mixer easier, e.g. MixFile MixShortClip

To create an empty Mixer, call UseMixer() and pass keepInputs: false

You can also add inputs via a delegate passed to the UseMixer extension method.

To get the current Mixer instance, use the Mixer extension property.

Caution

The UseMixer and its consuming methods will replace the provider unless it's already a Mixer

To remove sources from the mixer, call an extension method.

Note

Calling an AudioPlayer extension method to remove a mixer input will do nothing if the provider is not a Mixer

Queueing

To play back sources one after another, use an AudioQueue

Extension methods make it easier, e.g. EnqueueFile EnqueueShortClip

To get the current AudioQueue instance, use the Queue extension property.

Caution

The UseQueue method will replace the provider with a new AudioQueue if the single input is not an AudioQueue

Extracting Providers

Several extension methods and properties help get an underlying provider if needed.

Single Input

The single mixer input may be the sample provider itself depending on the type requested.

If the provider is an IAudioProcessor, the return value is based on the following criteria:

  1. Mixer with exactly 1 input matching the type: the single mixer input
  2. ProcessorChain with an IAudioProcessor source: pass the source to step 1
  3. If the above don't match, default is returned

Getting Started

Playing Audio

Advanced

Audio Processors

v1 Guides

Caution

v1 will be out of support soon.

Clone this wiki locally