Beryllium.Audio 0.9.990

Prefix Reserved
dotnet add package Beryllium.Audio --version 0.9.990
                    
NuGet\Install-Package Beryllium.Audio -Version 0.9.990
                    
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="Beryllium.Audio" Version="0.9.990" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Beryllium.Audio" Version="0.9.990" />
                    
Directory.Packages.props
<PackageReference Include="Beryllium.Audio" />
                    
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 Beryllium.Audio --version 0.9.990
                    
#r "nuget: Beryllium.Audio, 0.9.990"
                    
#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 Beryllium.Audio@0.9.990
                    
#: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=Beryllium.Audio&version=0.9.990
                    
Install as a Cake Addin
#tool nuget:?package=Beryllium.Audio&version=0.9.990
                    
Install as a Cake Tool

Beryllium.Audio

Audio manager for the Beryllium engine: 3D positional sound with HRTF spatialization, per-emitter effect chains and a shared reverb bus, built on NAudio and NVorbis.

  • Emitters that play WAV or Ogg Vorbis clips, either decoded into a shared in-memory cache or streamed from disk
  • HRTF spatialization from OpenAL Soft .mhr data sets (a default set is embedded)
  • Distance attenuation with air absorption, Doppler pitch shift, 3-band EQ, delay, pitch, fade in/out, volume and a global reverb bus
  • Freely routable effect chains per emitter
  • Output device tracking: follows the Windows default render device and recovers when a device is unplugged
  • Real-time safe audio path: parameter changes from the game thread reach the audio thread through lock-free publication, and the audio thread doesn't allocate in steady state

Audio output uses WASAPI, so it requires Windows. The package targets net10.0.

Installation

dotnet add package Beryllium.Audio

Quick start

using System.Numerics;
using BerylliumAudio;
using BerylliumAudio.EffectWrappers;
using BerylliumAudio.EffectWrappers.Base;
using BerylliumAudio.Emitters.Base;

using var audio = new AudioManager(); // default HRTF, master volume 1.0

audio.TryAddEmitter("campfire", AudioEmitterTypes.Cached, out var fire);
fire.TryAddAudio("Sounds/campfire.ogg");
fire.IsLooped = true;
fire.Position = new Vector3(4, 0, -2);

// Add effects, then wire them between the emitter's send and return endpoints.
fire.TryAddAudioEffect(AudioEffectTypes.Distance, out var distance);
fire.TryAddAudioEffect(AudioEffectTypes.Spatial, out var spatial);
((DistanceAudioEffect)distance).LoudnessDb = 70;

distance.Input = fire.EffectLoopSend;  // send -> distance
spatial.Input = distance;              // distance -> spatial
fire.EffectLoopReturn.Input = spatial; // spatial -> return

fire.Play();

// Once per game frame:
audio.SetListenerData(cameraPosition, cameraForward, cameraUp, cameraRight);
audio.Update(deltaSeconds);

Concepts

AudioManager

AudioManager owns the output device, the mixer (48 kHz, stereo, 32-bit float), the reverb bus and all emitters. Create one per application and dispose of it on shutdown.

Member Purpose
Update(elapsedSeconds) Call once per frame. Advances emitter states and loop pauses, feeds Doppler velocities and re-selects the output device after device changes.
SetListenerData(position, forward, up, right) Sets the whole listener pose in one call (preferred over the individual Listener* properties). The vectors should be normalized.
MasterVolume Global output gain in [0, 1].
ReverbBusRoomSize, ReverbBusCutoffHz, ReverbBusWet Reverb bus decay time (RT60, seconds), brightness (Hz) and wet/dry mix.
TryLoadMhrFile(path) Loads an HRTF data set. A null or unreadable path loads the embedded default. Returns false for invalid data, in which case no data set is loaded and spatial effects pass audio through unspatialized.
MhrFilePath File the current HRTF data came from, or null when the embedded default is in use (including after a fallback).
PlayAll(), PauseAll(), StopAll() Transport control for every emitter.
EmittersVersion Changes whenever emitters are added or removed, so you can invalidate cached emitter references.
OnMmDeviceChanged Raised after the output device has been re-selected.
HearingMinimumDb, AirSoundAbsorptionCoefficient Static environment settings used by distance attenuation.

Most emitter operations are also available on the manager by emitter name (TryPlayEmitter, TryAddAudioToEmitter, TryAddEffectToEmitter, ...).

Emitters

An emitter is a sound source with a position, a list of clips and an effect chain.

  • AudioEmitterTypes.Cached decodes each clip once (resampled and converted to the mixer format) into a process-wide cache shared by all emitters. Use it for short, frequently played sounds. AudioManager.ClearAudioCache() releases the cache.
  • AudioEmitterTypes.Streaming decodes from disk while playing. Use it for music and long ambiences.

An emitter can hold several clips (TryAddAudio). Each Play() from a stopped or finished state, and each loop iteration, picks one of them at random. Looping emitters can wait a random time between iterations (LoopPauseRangeMs = (min, max)).

State (Idle, Playing, Paused, Finished, EffectLoopDisconnected) is refreshed by Update(); subscribe to OnStateChanged or OnCurrentAudioChanged to react to changes.

Supported files: WAV (8/16/24/32-bit PCM or 32-bit float) and Ogg Vorbis, mono or stereo, any sample rate. Mono clips are upmixed and clips at other sample rates are resampled. Files are identified by their header, not their extension.

Effect chains

Every emitter has two fixed endpoints: EffectLoopSend (the clip's samples) and EffectLoopReturn (what goes to the mixer). A new emitter connects send directly to return. Effects added with TryAddAudioEffect start out unconnected; you place them by setting Input (or Output):

emitter.TryAddAudioEffect(AudioEffectTypes.Equalizer, out var eq);
emitter.TryAddAudioEffect(AudioEffectTypes.Reverb, out var reverb);

eq.Input = emitter.EffectLoopSend;
reverb.Input = eq;
emitter.EffectLoopReturn.Input = reverb;

While the chain from send to return is broken, the emitter is stopped and reports EffectLoopDisconnected, and Play() is ignored until the chain is complete again. Removing an effect that sits in the chain breaks it the same way. Rewiring is thread-safe while audio is playing.

Effect Wrapper Main parameters
Distance* DistanceAudioEffect LoudnessDb (sets MaxAudibleDistanceMeters), volume and low-pass attenuation curves, DistanceMinimumCutoffHz / DistanceMaximumCutoffHz
Doppler* DopplerAudioEffect Pitch shift from the relative velocity of listener and emitter (measured between Update calls)
Spatial* SpatialAudioEffect HRTF binaural rendering; AudioSpread from 0 (point source) to 1 (omnidirectional)
Equalizer ThreeBandEqualizerAudioEffect Low shelf, mid peak and high shelf: *GainDb, *FreqHz, LowSlope, MidQ, HighSlope
FadeInOut FadeInOutAudioEffect FadeInDurationMs, FadeOutDurationMs, shaping functions
Pitch PitchAudioEffect Pitch factor (0.5 = octave down, 2 = octave up)
Delay DelayAudioEffect DelayMs (up to 3 s), Feedback, Mix
Reverb ReverbAudioEffect ReverbSend to the shared reverb bus
TimePosition* TimePositionAudioEffect Read or seek the playback position
Volume VolumeAudioEffect Volume within VolumeRange

* At most one per emitter.

Every effect has IsBypass to pass audio through unchanged. Distance, Doppler and Spatial also offer a demo mode (IsDemoMode + DemoEmitterPosition) that ignores the real listener and places a listener at the origin facing -Z, which is handy for editor previews.

Attenuation curves and fade shapes take BaseShapingFunction instances from Beryllium.ShapingFunctions.

Reverb bus

Emitters with a Reverb effect send part of their signal (ReverbSend) to one shared Freeverb-style reverb. Configure it through the manager:

audio.ReverbBusRoomSize = 1.8f; // RT60 in seconds (0.05-6)
audio.ReverbBusCutoffHz = 6000; // darker <-> brighter tail
audio.ReverbBusWet = 0.3f;      // wet/dry balance of the final mix

When nothing is sent to the bus and the tail has died out, the reverb's processing is skipped entirely.

HRTF data

Spatialization uses OpenAL Soft's minimum-phase HRTF format (.mhr, MinPHR03). The embedded default set is used unless you pass a path to the constructor or to TryLoadMhrFile. Data sets are resampled to the mixer rate on load.

Threading

Call the control API (emitters, effects, listener, Update) from your game thread. Mixing runs on the WASAPI render thread. Parameter changes reach it through lock-free publication or per-block snapshots, and effect-graph rewiring is serialized with rendering. The emitter registry itself is concurrent, so emitters can be looked up or added from other threads.

Building and testing

dotnet build
dotnet test

Tests live in Tests/BerylliumAudio.Tests (xUnit v3, run through Microsoft.Testing.Platform, which global.json opts into). They render audio offline without an output device, so they also run on CI machines without sound hardware.

License

MIT © Beryllium Co.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
0.9.990 66 9/30/2026