Core Concepts

Five pieces. Learn what each one is for and the rest of the API is just detail.

OwnAudioSharp has a small vocabulary: an engine that owns the sound card, a mixer that combines audio, sources that produce it, effects that shape it, and a clock that keeps everything on the same timeline. Everything else in these docs hangs off those five.

How audio flows

Sound moves in one direction, from your sources down to the speakers. Every feature in the library plugs in somewhere on this path.

Sources
Where audio comes from β€” a file, a mic, a buffer, your own generator
FileSource
↓
Track effects
Optional per-source chain β€” reverb on the vocal only, say
SourceWithEffects
↓
Mixer
Sums every source into one signal Β· volume Β· pan Β· meters Β· clock
AudioMixer
↓
Master effects
Applied to the finished mix β€” EQ, compressor, limiter, VST3
master chain
↓
Engine
Native Rust β€” owns the device and the real-time thread
OwnaudioNet
↓
Speakers
WASAPI Β· CoreAudio Β· ALSA Β· ASIO
OS

1 Β· The engine

OwnaudioNet is a static class and there is exactly one engine per application. It opens the audio device, starts the real-time thread, and stays out of your way after that.

Three calls make up its whole life: initialize (pick the format and device), start (audio begins to flow), shut down (release the device). Nothing else works before initialization.

C#
await OwnaudioNet.InitializeAsync();   // 48 kHz, stereo, 512 frames
OwnaudioNet.Start();

// ... your app runs ...

await OwnaudioNet.ShutdownAsync();
⚠️

Use the Async variants in anything with a window. Opening a device can block for seconds β€” on Linux, PulseAudio alone can take five. More on the lifecycle β†’

2 Β· The mixer

AudioMixer is the bus. You hand it sources, it sums them into a single signal and pushes that to the engine. One mixer is enough for almost every app.

It also owns the things that belong to "the whole mix": master volume and pan, peak levels for your VU meters, the master effect chain, WAV recording of the output, and the master clock.

C#
var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine);
mixer.Start();

mixer.AddSource(track);        // hot-swappable, safe while playing
mixer.MasterVolume = 0.85f;    // 0.0 – 1.0
πŸ’‘

Adding and removing sources is lock-free β€” you can do it mid-playback without a click. The mixer in full β†’

3 Β· Sources

A source is anything that produces audio. They all implement IAudioSource, so once you know one you know all of them: Play(), Pause(), Stop(), Seek(), plus Volume, Pan, Loop, Position and Duration.

TypeReach for it when…
FileSourceYou have a file. MP3, FLAC, WAV, AAC, ALAC, MP4, OGG, AIFF β€” decoded natively, streamed from disk, seekable, tempo- and pitch-shiftable.
SampleSourceThe audio is already a float[] in memory. Short clips, sound effects, one-shots.
StreamingSourceYou want to generate audio β€” a synth, a metronome, a test tone, a network stream. You write a callback, it asks you for samples.
InputSourceThe audio is coming in live from a microphone or line input.
SourceWithEffectsNot a source of its own β€” a wrapper that gives any of the above its own effect chain.
C#
// Match the engine's format so nothing has to be resampled later
int sr = OwnaudioNet.Engine!.Config.SampleRate;
int ch = OwnaudioNet.Engine!.Config.Channels;

var vocals = new FileSource("vocals.wav", targetSampleRate: sr, targetChannels: ch);
vocals.Volume = 0.9f;
vocals.Pan    = -0.2f;   // a touch to the left

mixer.AddSource(vocals);
vocals.Play();
πŸ’‘

A source keeps playing on its own once started β€” the mixer only decides whether it can be heard. All source types β†’

4 Β· Effects

An effect is anything implementing IEffectProcessor: the 15 built-ins, SmartMaster, or a VST3 plugin. They all go in the same two places.

WhereHowAffects
One tracknew SourceWithEffects(source), then AddEffect()Only that source
The whole mixmixer.AddMasterEffect()Everything, after summing

Order matters β€” effects run in the order you add them, exactly like pedals on a board.

C#
// Compressor first, then reverb β€” on the vocal only
var vocalChain = new SourceWithEffects(vocals);
vocalChain.AddEffect(new CompressorEffect { Ratio = 4f, AttackTimeMs = 10f });
vocalChain.AddEffect(new ReverbEffect { RoomSize = 0.6f, Mix = 0.25f });

mixer.AddSource(vocalChain);   // add the wrapper, not the raw source

// Catch the peaks on the way out
mixer.AddMasterEffect(new LimiterEffect());

5 Β· The clock

Start two files at "the same time" and they will drift apart β€” different decoders, different buffer boundaries, different rounding. Over three minutes that becomes audible flam.

The MasterClock fixes this. Every mixer owns one, and it is the single source of truth for "where are we on the timeline". Attach a source to it and the engine continuously compares that source's position to the clock and nudges it back into line.

C#
// Attach BEFORE Play()
vocals.AttachToClock(mixer.MasterClock);
backing.AttachToClock(mixer.MasterClock);

backing.StartOffset = 2.5;   // this one enters 2.5 s into the song

mixer.Seek(0);               // moves the clock and every attached source
vocals.Play();
backing.Play();

double now = mixer.MasterClock.CurrentTimestamp;   // seconds β€” what your playhead reads
πŸ’‘

Correction happens in three zones: under 5 ms nothing is done, 5–25 ms is smoothed out with a tiny tempo nudge, above that the source is snapped back hard. Drift correction β†’

What runs where

Two rules cover nearly everything you need to know about threading.

Threads
Your UI thread     β†’  Play / Seek / Volume / AddSource      (fast, non-blocking)
Engine thread      β†’  decode Β· mix Β· effects Β· device I/O    (native Rust, never yours)

Everything else β€” setting Volume, adding a source, seeking β€” is safe from any thread and designed to be called from a slider's event handler.

Glossary

The words that show up in every audio API, in plain terms.

TermWhat it means
SampleOne number describing the signal at one instant. In this library, a float between βˆ’1.0 and +1.0.
FrameOne sample for every channel. In stereo, 1 frame = 2 samples. Buffer sizes are counted in frames.
Sample rateFrames per second. 48000 is the default and the safest choice; 44100 is CD audio.
Channels1 = mono, 2 = stereo. More than 2 means a multi-output interface.
InterleavedHow samples are laid out in memory: L R L R L R…, not all-left-then-all-right. Every buffer you touch is interleaved.
Buffer sizeHow many frames the engine hands the sound card at a time. Smaller = lower latency but more chances to fall behind.
LatencyThe delay between a sample being produced and being heard. bufferSize Γ· sampleRate β€” 512 frames at 48 kHz is ~10.6 ms.
Underrun / dropoutThe engine needed audio and it wasn't ready. You hear a click or a gap. Almost always means the buffer is too small for the work being done.
dBFSLevel in decibels where 0 is the loudest a digital signal can go. Everything useful is negative. 20 Γ— log10(peak).
Host / backendThe OS audio system the engine talks to: WASAPI or ASIO on Windows, CoreAudio on macOS, ALSA on Linux. Leave it on auto unless you have a reason.
DeviceA specific input or output β€” built-in speakers, an audio interface, a virtual cable. Identified by DeviceId.
Real-time threadThe thread that must deliver audio on schedule, every time. In 4.0 it lives entirely in Rust, which is why a garbage collection can no longer interrupt your sound.

Where next