SCPSL-AudioManagerAPI 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package SCPSL-AudioManagerAPI --version 1.0.0
                    
NuGet\Install-Package SCPSL-AudioManagerAPI -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SCPSL-AudioManagerAPI" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SCPSL-AudioManagerAPI" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="SCPSL-AudioManagerAPI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SCPSL-AudioManagerAPI --version 1.0.0
                    
#r "nuget: SCPSL-AudioManagerAPI, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SCPSL-AudioManagerAPI@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SCPSL-AudioManagerAPI&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=SCPSL-AudioManagerAPI&version=1.0.0
                    
Install as a Cake Tool

SCPSL-AudioManagerAPI

NuGet Version
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 to prevent conflicts across multiple plugins.

Features

  • Centralized Controller ID Management: Uses ControllerIdManager to ensure unique speaker IDs (1-255) across all plugins, preventing conflicts in multiplayer environments.
  • 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 and ISpeakerFactory interfaces.
  • Thread-Safe Operations: Handles concurrent audio playback, caching, and ID allocation safely.
  • LabAPI Compatibility: Optimized for SCP:SL, integrating seamlessly with SpeakerToy for spatial audio playback.

Installation

Install the SCPSL-AudioManagerAPI package via NuGet:

dotnet add package SCPSL-AudioManagerAPI --version 1.0.0

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.0" />
    <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 : ISpeaker
{
    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();
    }

    // Optional: Configure which players can hear the audio
    public void SetValidPlayers(Func<Player, bool> playerFilter)
    {
        var transmitter = SpeakerToy.GetTransmitter(speakerToy.ControllerId);
        if (transmitter != null)
        {
            transmitter.ValidPlayers = playerFilter;
        }
    }
}

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.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, with optional speaker configuration.

using UnityEngine;

public void PlayScream(Vector3 position, Player targetPlayer)
{
    byte? controllerId = audioManager.PlayAudio("myplugin.scream", position, false, speaker =>
    {
        if (speaker is LabApiSpeaker labSpeaker)
        {
            labSpeaker.SetValidPlayers(p => p == targetPlayer);
        }
    });

    if (controllerId.HasValue)
    {
        Log.Info($"Played 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);
    

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.

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.
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 across plugins.

Important Methods

  • IAudioManager.RegisterAudio(string key, Func<Stream> streamProvider): Registers a WAV stream for lazy loading.
  • IAudioManager.PlayAudio(string key, Vector3 position, bool loop, Action<ISpeaker> configureSpeaker): Plays audio at a position with optional configuration.
  • 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), critical for SCP:SL’s multiplayer environment.
  • Thread Safety: All operations (ID allocation, caching, speaker management) are thread-safe using locks.
  • Dependencies: Requires UnityEngine.CoreModule for Vector3 and LabApi for SpeakerToy. Ensure these are available in your SCP:SL environment.
  • Logging: Use your plugin’s logging system (e.g., Exiled’s Log) for debugging playback or resource errors.

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 Compatible and additional computed target framework versions.
.NET Framework net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .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 120 7/28/2025
1.6.0 71 7/27/2025
1.5.2 215 7/26/2025
1.5.1 216 7/26/2025
1.5.0 444 7/24/2025
1.4.2 446 7/24/2025
1.4.1 439 7/24/2025
1.4.0 444 7/24/2025
1.3.0 445 7/23/2025
1.2.3 491 7/22/2025
1.2.2 490 7/22/2025
1.2.1 495 7/22/2025
1.2.0 493 7/22/2025
1.0.3 490 7/22/2025
1.0.2 460 7/21/2025
1.0.1 459 7/21/2025
1.0.0 460 7/21/2025