SCPSL-AudioManagerAPI
1.0.2
See the version list below for details.
dotnet add package SCPSL-AudioManagerAPI --version 1.0.2
NuGet\Install-Package SCPSL-AudioManagerAPI -Version 1.0.2
<PackageReference Include="SCPSL-AudioManagerAPI" Version="1.0.2" />
<PackageVersion Include="SCPSL-AudioManagerAPI" Version="1.0.2" />
<PackageReference Include="SCPSL-AudioManagerAPI" />
paket add SCPSL-AudioManagerAPI --version 1.0.2
#r "nuget: SCPSL-AudioManagerAPI, 1.0.2"
#:package SCPSL-AudioManagerAPI@1.0.2
#addin nuget:?package=SCPSL-AudioManagerAPI&version=1.0.2
#tool nuget:?package=SCPSL-AudioManagerAPI&version=1.0.2
SCPSL-AudioManagerAPI
A lightweight, reusable C# library for managing audio playback in SCP: Secret Laboratory (SCP:SL) plugins using LabAPI. It provides a robust system for loading, caching, and playing audio through SpeakerToy
instances, with centralized controller ID management, advanced audio control (volume, range, spatialization), and prioritization for enhanced gameplay.
Features
- Centralized Controller ID Management: Uses
ControllerIdManager
to ensure unique speaker IDs (1-255) across plugins, with priority-based eviction and queuing for high-priority audio. - LRU Audio Caching: Efficiently manages audio samples with lazy loading and least-recently-used (LRU) eviction via
AudioCache
. - Flexible Speaker Abstraction: Supports custom speaker implementations through
ISpeaker
,ISpeakerWithPlayerFilter
, andISpeakerFactory
interfaces. - Advanced Audio Control: Configurable volume (0.0 to 1.0), minimum/maximum distance, and spatialization (3D audio) for precise audio tuning.
- Audio Prioritization: Supports Low, Medium, and High priorities, with queuing for high-priority audio when IDs are limited.
- Thread-Safe Operations: Handles concurrent audio playback, caching, and ID allocation safely.
- LabAPI Compatibility: Optimized for SCP:SL, integrating seamlessly with
SpeakerToy
for spatial and global audio playback.
Installation
Install the SCPSL-AudioManagerAPI
package via NuGet:
dotnet add package SCPSL-AudioManagerAPI --version 1.0.1
Or, in Visual Studio, use the NuGet Package Manager to search for SCPSL-AudioManagerAPI
.
Project Setup
Add the SCPSL-AudioManagerAPI
package to your SCP:SL plugin project. Ensure you reference UnityEngine.CoreModule
for Vector3
and LabApi
for SpeakerToy
integration.
Example .csproj
snippet:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SCPSL-AudioManagerAPI" Version="1.0.1" />
<Reference Include="LabApi">
<HintPath>path\to\LabApi.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>path\to\UnityEngine.CoreModule.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
Usage
1. Implement ISpeaker and ISpeakerFactory
Create a custom speaker implementation compatible with LabAPI's SpeakerToy
.
using AudioManagerAPI.Features.Speakers;
using LabApi.Features.Wrappers;
using UnityEngine;
public class LabApiSpeaker : ISpeakerWithPlayerFilter
{
private readonly SpeakerToy speakerToy;
public LabApiSpeaker(SpeakerToy speakerToy)
{
this.speakerToy = speakerToy ?? throw new ArgumentNullException(nameof(speakerToy));
}
public void Play(float[] samples, bool loop)
{
var transmitter = SpeakerToy.GetTransmitter(speakerToy.ControllerId);
transmitter?.Play(samples, queue: false, loop: loop);
}
public void Stop()
{
var transmitter = SpeakerToy.GetTransmitter(speakerToy.ControllerId);
transmitter?.Stop();
}
public void Destroy()
{
speakerToy.Destroy();
}
public void SetValidPlayers(Func<object, bool> playerFilter)
{
var transmitter = SpeakerToy.GetTransmitter(speakerToy.ControllerId);
if (transmitter != null)
{
transmitter.ValidPlayers = playerFilter as Func<Player, bool>;
}
}
public void SetVolume(float volume)
{
speakerToy.Volume = Mathf.Clamp01(volume);
}
public void SetMinDistance(float minDistance)
{
speakerToy.MinDistance = Mathf.Max(0, minDistance);
}
public void SetMaxDistance(float maxDistance)
{
speakerToy.MaxDistance = Mathf.Max(0, maxDistance);
}
public void SetSpatialization(bool isSpatial)
{
speakerToy.IsSpatial = isSpatial;
}
}
public class LabApiSpeakerFactory : ISpeakerFactory
{
public ISpeaker CreateSpeaker(Vector3 position, byte controllerId)
{
SpeakerToy speaker = SpeakerToy.Create(position, networkSpawn: true);
if (speaker == null) return null;
speaker.ControllerId = controllerId;
return new LabApiSpeaker(speaker);
}
}
2. Initialize AudioManager
Create an instance of AudioManager
with your ISpeakerFactory
and register audio resources. The AudioCache
supports only 48kHz, Mono, Signed 16-bit PCM WAV files.
using AudioManagerAPI;
using AudioManagerAPI.Features.Management;
using System;
using System.Reflection;
public class MyPluginAudioManager
{
private readonly IAudioManager audioManager;
public MyPluginAudioManager()
{
audioManager = new AudioManager(new LabApiSpeakerFactory(), cacheSize: 20);
RegisterAudioResources();
}
private void RegisterAudioResources()
{
var assembly = Assembly.GetExecutingAssembly();
audioManager.RegisterAudio("myplugin.scream", () =>
assembly.GetManifestResourceStream("MyPlugin.Audio.scream.wav"));
}
}
3. Play Audio
Use IAudioManager
to play audio at specific positions, either locally or globally, with volume, range, spatialization, and priority settings.
Local Playback (specific players):
using UnityEngine; public void PlayScream(Vector3 position, Player targetPlayer) { byte? controllerId = audioManager.PlayAudio("myplugin.scream", position, false, volume: 0.8f, minDistance: 5f, maxDistance: 50f, isSpatial: true, priority: AudioPriority.High, speaker => { if (speaker is LabApiSpeaker labSpeaker) { labSpeaker.SetValidPlayers(p => p == targetPlayer); } }); if (controllerId.HasValue) { Log.Info($"Played scream with controller ID {controllerId.Value}."); } }
Global Playback (all players):
public void PlayGlobalScream(Vector3 position) { byte? controllerId = audioManager.PlayGlobalAudio("myplugin.scream", position, false, volume: 0.8f, minDistance: 5f, maxDistance: 50f, isSpatial: true, priority: AudioPriority.High); if (controllerId.HasValue) { Log.Info($"Played global scream with controller ID {controllerId.Value}."); } }
4. Manage Speakers
Stop Audio: Stop playback for a specific speaker.
audioManager.StopAudio(controllerId);
Destroy Speaker: Free resources for a specific speaker.
audioManager.DestroySpeaker(controllerId);
Retrieve Speaker: Access a speaker for further configuration.
ISpeaker speaker = audioManager.GetSpeaker(controllerId); if (speaker is ISpeakerWithPlayerFilter playerFilterSpeaker) { playerFilterSpeaker.SetVolume(0.5f); // Adjust volume playerFilterSpeaker.SetMinDistance(3f); // Adjust min distance playerFilterSpeaker.SetMaxDistance(30f); // Adjust max distance playerFilterSpeaker.SetSpatialization(false); // Disable spatial audio }
5. Cleanup
Clean up all speakers to free resources.
audioManager.CleanupAllSpeakers();
Audio Requirements
The AudioCache
class processes WAV files with the following specifications:
- Format: 48kHz, Mono, Signed 16-bit PCM.
- Header: Expects a standard WAV header; skips the first 44 bytes during loading.
- Recommendation: Prefix audio keys with your plugin’s namespace (e.g.,
myplugin.scream
) to avoid conflicts with other plugins.
Audio Control and Prioritization
- Volume: Set between 0.0 (mute) and 1.0 (full volume) to control loudness (
SetVolume
). - MinDistance/MaxDistance: Define the range where audio starts to fall off and drops to zero, in Unity units (
SetMinDistance
,SetMaxDistance
). - Spatialization: Enable/disable 3D audio (
SetSpatialization
) for positional or ambient effects. - Priority: Use
AudioPriority
(Low, Medium, High) to prioritize critical sounds. High-priority audio can evict lower-priority speakers or be queued if IDs are unavailable.
API Reference
Key Classes and Interfaces
Name | Namespace | Description |
---|---|---|
IAudioManager |
AudioManagerAPI.Features.Management |
Defines the contract for audio playback and speaker lifecycle management. |
AudioManager |
AudioManagerAPI.Features.Management |
Implements audio management with caching and shared controller IDs. |
ISpeaker |
AudioManagerAPI.Features.Speakers |
Represents a speaker for playing audio samples at a position. |
ISpeakerWithPlayerFilter |
AudioManagerAPI.Features.Speakers |
Extends ISpeaker to support player-specific audibility, volume, range, and spatialization. |
ISpeakerFactory |
AudioManagerAPI.Features.Speakers |
Defines a factory for creating speaker instances. |
AudioCache |
AudioManagerAPI.Cache |
Manages audio samples with LRU eviction and lazy loading. |
ControllerIdManager |
AudioManagerAPI |
Static class for managing unique controller IDs with priority-based eviction and queuing. |
AudioPriority |
AudioManagerAPI |
Enum defining audio priority levels (Low, Medium, High). |
Important Methods
IAudioManager.RegisterAudio(string key, Func<Stream> streamProvider)
: Registers a WAV stream for lazy loading.IAudioManager.PlayAudio(string key, Vector3 position, bool loop, float volume, float minDistance, float maxDistance, bool isSpatial, AudioPriority priority, Action<ISpeaker> configureSpeaker)
: Plays audio at a position with optional configuration.IAudioManager.PlayGlobalAudio(string key, Vector3 position, bool loop, float volume, float minDistance, float maxDistance, bool isSpatial, AudioPriority priority)
: Plays audio globally, audible to all players.IAudioManager.StopAudio(byte controllerId)
: Stops audio for a specific speaker.IAudioManager.DestroySpeaker(byte controllerId)
: Destroys a speaker and releases its ID.IAudioManager.CleanupAllSpeakers()
: Cleans up all active speakers and releases their IDs.IAudioManager.GetSpeaker(byte controllerId)
: Retrieves a speaker instance for further configuration.
Notes
- Controller ID Synchronization:
ControllerIdManager
ensures no ID conflicts by maintaining a shared pool of IDs (1-255). High-priority audio can evict lower-priority speakers or be queued for later allocation. - Thread Safety: All operations (ID allocation, caching, speaker management) are thread-safe using locks.
- Dependencies: Requires
UnityEngine.CoreModule
forVector3
andLabApi
forSpeakerToy
. Ensure these are available in your SCP:SL environment. - Logging: Use your plugin’s logging system (e.g., Exiled’s
Log
) for debugging playback, prioritization, or resource errors. - Spatial Audio: Use
isSpatial: true
for positional effects (e.g., screams) andisSpatial: false
for ambient sounds (e.g., background music).
Contributing
Contributions are welcome! Please submit issues or pull requests to the GitHub repository.
License
This project is licensed under the GNU Lesser General Public License v3.0 (LGPL3). See the LICENSE file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.7.0 | 86 | 7/28/2025 |
1.6.0 | 57 | 7/27/2025 |
1.5.2 | 204 | 7/26/2025 |
1.5.1 | 207 | 7/26/2025 |
1.5.0 | 435 | 7/24/2025 |
1.4.2 | 438 | 7/24/2025 |
1.4.1 | 432 | 7/24/2025 |
1.4.0 | 435 | 7/24/2025 |
1.3.0 | 437 | 7/23/2025 |
1.2.3 | 483 | 7/22/2025 |
1.2.2 | 483 | 7/22/2025 |
1.2.1 | 488 | 7/22/2025 |
1.2.0 | 487 | 7/22/2025 |
1.0.3 | 484 | 7/22/2025 |
1.0.2 | 433 | 7/21/2025 |
1.0.1 | 430 | 7/21/2025 |
1.0.0 | 434 | 7/21/2025 |