Audio Sources
All sources implement IAudioSource and inherit from BaseAudioSource. Namespace: OwnaudioNET.Sources
Common API (all sources)
| Property | Type | Default | Description |
|---|---|---|---|
Id | Guid | auto | Unique identifier for this source. |
State | AudioState | Stopped | Current playback state. |
Volume | float | 1.0 | Track volume (0.0 â 20.0). Values above 1.0 amplify. |
Loop | bool | false | Loop when reaching end of stream. |
Position | double | â | Current playback position in seconds (read-only). |
Duration | double | â | Total duration in seconds (read-only). |
IsEndOfStream | bool | â | Whether the source has reached its end. |
Tempo | float | 1.0 | Playback speed multiplier (0.8â1.2). Clears buffer on set â use SetTempoSmooth() for sliders. |
PitchShift | float | 0.0 | Pitch shift in semitones (-12 to +12). Clears buffer on set. |
OutputLevels | (float left, float right) | â | Real-time output levels for VU metering (0.0â1.0). |
OutputChannelMapping | int[]? | null | Hardware channel routing. See Channel Routing. |
source.Play();
source.Pause();
source.Stop();
source.Seek(double positionInSeconds); // returns bool
source.RouteToChannels(params int[] channels); // fluent helper
source.Dispose();Common Events
| Event | Args | Description |
|---|---|---|
StateChanged | AudioStateChangedEventArgs | Playback state changed. |
BufferUnderrun | BufferUnderrunEventArgs | Read buffer underrun detected. |
Error | AudioErrorEventArgs | An error occurred during playback. |
PositionChanged | EventArgs | Position changed significantly (throttled >50ms). |
FileSource
Plays audio from a file with background decoding, circular buffer, real-time pitch/tempo via SoundTouch, and master clock synchronization. Supported formats: MP3, WAV, FLAC.
Constructor
var source = new FileSource(
filePath: "track.mp3",
bufferSizeInFrames: 8192, // internal circular buffer (default: 8192)
targetSampleRate: 48000, // auto-resampling; 0 = use file's rate
targetChannels: 2 // auto-channel conversion; 0 = use file's channels
);FileSource-Specific Properties
| Property | Type | Default | Description |
|---|---|---|---|
StartOffset | double | 0.0 | Timeline start position in seconds for master clock sync. |
IsAttachedToClock | bool | false | Whether attached to a master clock (read-only). |
SyncTolerance | double | 0.020 | Green zone threshold: drift below this needs no correction (20ms). |
SoftSyncTolerance | double | 0.100 | Yellow zone threshold: triggers gradual tempo correction (100ms). |
SoftSyncMaxTempoAdjustment | double | 0.02 | Maximum tempo drift during soft sync correction (2%). |
Tempo & Pitch Control
Hard set (.Tempo = âĻ) clears the SoundTouch buffer and causes a brief silence gap. Use smooth set for real-time sliders to avoid audio glitches.
// Hard set â resets SoundTouch buffer (use on load)
source.Tempo = 1.1f; // 10% faster (range: 0.8 â 1.2)
source.PitchShift = 2.0f; // 2 semitones up (range: -12.0 â +12.0)
// Smooth set â no buffer clear, ideal for real-time sliders
source.SetTempoSmooth(1.1f);
source.SetPitchSmooth(2.0f);PreBuffer
Warm up the decoder before Play() to eliminate initial underruns:
// Pre-fill the ring buffer on a background thread
await Task.Run(() => source.PreBuffer());
source.Play(); // buffer is ready â no underrun on first bufferComplete Example
int sr = OwnaudioNet.Engine!.Config.SampleRate;
int ch = OwnaudioNet.Engine!.Config.Channels;
var source = new FileSource("backing.mp3",
bufferSizeInFrames: 4096,
targetSampleRate: sr,
targetChannels: ch);
source.Volume = 0.8f;
source.Tempo = GlobalTempo / 100f; // e.g. 100 â 1.0f
source.PitchShift = 0;
source.StartOffset = 0.0;
source.StateChanged += (_, e) =>
{
if (e.NewState == AudioState.EndOfStream)
Console.WriteLine("Track finished.");
};
mixer.AddSource(source);SampleSource
Plays audio from a pre-loaded float[] array. Ideal for sound effects, short clips, or synthesized audio.
// Static sample
float[] samples = LoadSamplesFromFile("click.wav");
var click = new SampleSource(samples, OwnaudioNet.CreateDefaultConfig());
mixer.AddSource(click);
click.Play();
// Dynamic â submit samples in real time
var synth = new SampleSource(bufferSizeInFrames: 2048, OwnaudioNet.CreateDefaultConfig());
synth.AllowDynamicUpdate = true;
// Submit new samples as they are generated
synth.SubmitSamples(newSamples); // ReadOnlySpan<float>
synth.Clear(); // flush bufferInputSource
Captures audio from an input device (microphone, line-in) and routes it into the mixer.
// Enable input in AudioConfig first
var config = OwnaudioNet.CreateDefaultConfig();
config.EnableInput = true;
await OwnaudioNet.InitializeAsync(config);
OwnaudioNet.Start();
var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine);
mixer.Start();
var mic = new InputSource(OwnaudioNet.Engine!, bufferSizeInFrames: 8192);
mixer.AddSource(mic);
mic.Play();
// Monitor input peak levels
var (leftLevel, rightLevel) = mic.GetInputLevels();SourceWithEffects
Wraps any IAudioSource to add a per-track effect chain. Effects run in the order they are added.
var source = new FileSource("vocal.wav");
var trackFx = new SourceWithEffects(source);
// Build effect chain
trackFx.AddEffect(new CompressorEffect { Threshold = 0.7f, Ratio = 4f });
trackFx.AddEffect(new ReverbEffect { RoomSize = 0.4f, Mix = 0.2f });
trackFx.AddEffect(new EqualizerEffect());
// Add the wrapper to the mixer â NOT the raw source
mixer.AddSource(trackFx);
// Manage the chain
trackFx.RemoveEffect(effect); // returns bool
trackFx.ClearEffects();
int count = trackFx.EffectCount;
IEffectProcessor[] fx = trackFx.GetEffects();If you add effects to a source that is already in the mixer, remove the raw source and add the SourceWithEffects wrapper: mixer.RemoveSource(source.Id); mixer.AddSource(trackFx);
Channel Routing
Route individual sources to specific physical output channels on multi-channel audio interfaces.
// Configure 4-channel output in AudioConfig
var config = new AudioConfig
{
Channels = 4,
OutputChannelSelectors = new[] { 0, 1, 2, 3 } // physical channels 0â3
};
// Route music to channels 0+1, metronome to channels 2+3
var music = new FileSource("music.mp3");
var metronome = new FileSource("click.wav");
music.OutputChannelMapping = new[] { 0, 1 };
metronome.OutputChannelMapping = new[] { 2, 3 };
// Fluent style
music.RouteToChannels(0, 1);
metronome.RouteToChannels(2, 3);
mixer.AddSource(music);
mixer.AddSource(metronome);The OutputChannelMapping array length must equal the source's Config.Channels. Channels are zero-indexed.