Audio Sources

All sources implement IAudioSource and inherit from BaseAudioSource. Namespace: OwnaudioNET.Sources

Common API (all sources)

PropertyTypeDefaultDescription
IdGuidautoUnique identifier for this source.
StateAudioStateStoppedCurrent playback state.
Volumefloat1.0Track volume (0.0 – 20.0). Values above 1.0 amplify.
LoopboolfalseLoop when reaching end of stream.
Positiondouble—Current playback position in seconds (read-only).
Durationdouble—Total duration in seconds (read-only).
IsEndOfStreambool—Whether the source has reached its end.
Tempofloat1.0Playback speed multiplier (0.8–1.2). Clears buffer on set — use SetTempoSmooth() for sliders.
PitchShiftfloat0.0Pitch 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).
OutputChannelMappingint[]?nullHardware channel routing. See Channel Routing.
C# — Common methods
source.Play();
source.Pause();
source.Stop();
source.Seek(double positionInSeconds);  // returns bool
source.RouteToChannels(params int[] channels); // fluent helper
source.Dispose();

Common Events

EventArgsDescription
StateChangedAudioStateChangedEventArgsPlayback state changed.
BufferUnderrunBufferUnderrunEventArgsRead buffer underrun detected.
ErrorAudioErrorEventArgsAn error occurred during playback.
PositionChangedEventArgsPosition 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

C#
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

PropertyTypeDefaultDescription
StartOffsetdouble0.0Timeline start position in seconds for master clock sync.
IsAttachedToClockboolfalseWhether attached to a master clock (read-only).
SyncTolerancedouble0.020Green zone threshold: drift below this needs no correction (20ms).
SoftSyncTolerancedouble0.100Yellow zone threshold: triggers gradual tempo correction (100ms).
SoftSyncMaxTempoAdjustmentdouble0.02Maximum 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.

C#
// 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:

C#
// Pre-fill the ring buffer on a background thread
await Task.Run(() => source.PreBuffer());
source.Play(); // buffer is ready — no underrun on first buffer

Complete Example

C#
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.

C#
// 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 buffer

InputSource

Captures audio from an input device (microphone, line-in) and routes it into the mixer.

C#
// 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.

C#
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.

C#
// 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.