Code Examples

Practical examples demonstrating OwnAudioSharp's capabilities. From simple playback to advanced real-time processing.

🎵 Audio Player Beginner

Complete console-based audio player with interactive controls

View Example →

🎛️ Effect Processor Intermediate

Apply and chain multiple audio effects with real-time control

View Example →

🎼 Music Analyzer Advanced

Analyze music files for chord progressions, key, and tempo

View Example →

🔄 Real-Time Synthesizer Advanced

Generate and process audio in real-time with effects

View Example →

Simple Audio Playback

The most basic example - loading and playing an audio file.

BasicPlayback.cs Beginner
using Ownaudio;
using Ownaudio.Sources;
using System;
using System.Threading.Tasks;

class BasicPlayback
{
    static async Task Main(string[] args)
    {
        try
        {
            // Initialize OwnAudio
            OwnAudio.Initialize();
            
            var sourceManager = SourceManager.Instance;
            
            // Load an audio file
            await sourceManager.AddOutputSource("music.mp3", "MyTrack");
            
            Console.WriteLine($"Loaded: {sourceManager["MyTrack"].Duration}");
            
            // Start playback
            sourceManager.Play();
            Console.WriteLine("Playing... Press any key to stop.");
            Console.ReadKey();
            
            // Stop and cleanup
            sourceManager.Stop();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
        finally
        {
            OwnAudio.Free();
        }
    }
}

Multiple Audio Sources

Mix multiple audio sources with individual volume control.

AudioMixer.cs Beginner
using Ownaudio;
using Ownaudio.Sources;
using System;
using System.Threading.Tasks;

class AudioMixer
{
    static async Task Main(string[] args)
    {
        try
        {
            OwnAudio.Initialize();
            var sourceManager = SourceManager.Instance;
            
            // Add multiple sources
            await sourceManager.AddOutputSource("background.mp3", "Background");
            await sourceManager.AddOutputSource("drums.wav", "Drums");
            await sourceManager.AddOutputSource("bass.wav", "Bass");
            
            // Set individual volumes
            sourceManager["Background"].Volume = 0.6f;  // 60% background music
            sourceManager["Drums"].Volume = 0.8f;       // 80% drums
            sourceManager["Bass"].Volume = 0.7f;        // 70% bass
            
            // Start mixed playback
            sourceManager.Play();
            
            // Interactive volume control
            await RunVolumeControl(sourceManager);
        }
        finally
        {
            OwnAudio.Free();
        }
    }
    
    static async Task RunVolumeControl(SourceManager manager)
    {
        while (manager.IsPlaying)
        {
            Console.WriteLine("\nVolume Control:");
            Console.WriteLine("1. Background  2. Drums  3. Bass  4. Quit");
            
            var key = Console.ReadKey().KeyChar;
            if (key == '4') break;
            
            string sourceName = key switch
            {
                '1' => "Background",
                '2' => "Drums", 
                '3' => "Bass",
                _ => null
            };
            
            if (sourceName != null)
            {
                Console.Write($"\nNew volume for {sourceName} (0.0-1.0): ");
                if (float.TryParse(Console.ReadLine(), out float volume))
                {
                    manager[sourceName].Volume = Math.Clamp(volume, 0f, 1f);
                    Console.WriteLine($"{sourceName} volume set to {volume:F2}");
                }
            }
        }
    }
}

Audio Recording

Record audio from microphone to file with configurable bit depth.

AudioRecorder.cs Beginner
using Ownaudio;
using Ownaudio.Sources;
using System;
using System.Threading.Tasks;

class AudioRecorder
{
    static async Task Main(string[] args)
    {
        try
        {
            OwnAudio.Initialize();
            var sourceManager = SourceManager.Instance;
            
            // Add input source (microphone)
            var inputSource = await sourceManager.AddInputSource("Microphone");
            Console.WriteLine("Microphone ready for recording.");
            
            Console.WriteLine("Press ENTER to start recording...");
            Console.ReadLine();
            
            // Start recording to file (16-bit WAV)
            string outputFile = $"recording_{DateTime.Now:yyyyMMdd_HHmmss}.wav";
            sourceManager.Play(outputFile, 16);
            
            Console.WriteLine($"🔴 Recording to {outputFile}");
            Console.WriteLine("Press ENTER to stop recording...");
            Console.ReadLine();
            
            // Stop recording
            sourceManager.Stop();
            Console.WriteLine($"✅ Recording saved: {outputFile}");
            
            // Optional: Playback the recorded file
            Console.WriteLine("Play back recording? (y/n)");
            if (Console.ReadKey().KeyChar == 'y')
            {
                await PlaybackRecording(outputFile);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Recording error: {ex.Message}");
        }
        finally
        {
            OwnAudio.Free();
        }
    }
    
    static async Task PlaybackRecording(string filePath)
    {
        try
        {
            var sourceManager = SourceManager.Instance;
            
            // Clear previous sources
            sourceManager.Sources.Clear();
            
            // Load and play recording
            await sourceManager.AddOutputSource(filePath, "Recording");
            sourceManager.Play();
            
            Console.WriteLine($"\n🎵 Playing back recording ({sourceManager["Recording"].Duration})");
            Console.WriteLine("Press any key to stop...");
            Console.ReadKey();
            
            sourceManager.Stop();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Playback error: {ex.Message}");
        }
    }
}

Applying Audio Effects

Apply professional audio effects like reverb, delay, and compression.

EffectProcessor.cs Intermediate
using Ownaudio;
using Ownaudio.Sources;
using Ownaudio.Processors;
using System;
using System.Threading.Tasks;

class EffectProcessor
{
    private static SourceManager sourceManager;
    
    static async Task Main(string[] args)
    {
        try
        {
            OwnAudio.Initialize();
            sourceManager = SourceManager.Instance;
            
            // Load audio file
            await sourceManager.AddOutputSource("audio.mp3", "Track");
            sourceManager.Play();
            
            Console.WriteLine("🎛️  Effect Processor");
            Console.WriteLine("Track loaded and playing...");
            
            await RunEffectMenu();
        }
        finally
        {
            OwnAudio.Free();
        }
    }
    
    static async Task RunEffectMenu()
    {
        while (sourceManager.IsPlaying)
        {
            Console.WriteLine("\n=== Audio Effects ===");
            Console.WriteLine("1. Hall Reverb     2. Room Reverb");
            Console.WriteLine("3. Echo Delay      4. Ping Pong Delay");
            Console.WriteLine("5. Compressor      6. Equalizer");
            Console.WriteLine("7. Clear Effects   8. Exit");
            Console.Write("Choose effect: ");
            
            var choice = Console.ReadKey().KeyChar;
            Console.WriteLine();
            
            switch (choice)
            {
                case '1': ApplyHallReverb(); break;
                case '2': ApplyRoomReverb(); break;
                case '3': ApplyEchoDelay(); break;
                case '4': ApplyPingPongDelay(); break;
                case '5': ApplyCompressor(); break;
                case '6': ApplyEqualizer(); break;
                case '7': ClearEffects(); break;
                case '8': return;
            }
        }
    }
    
    static void ApplyHallReverb()
    {
        var reverb = new Reverb(
            roomSize: 0.8f,    // Large hall
            damping: 0.2f,     // Minimal damping
            wetLevel: 0.4f,    // 40% reverb
            dryLevel: 0.7f     // 70% original
        );
        sourceManager.CustomSampleProcessor = reverb;
        Console.WriteLine("✅ Hall reverb applied");
    }
    
    static void ApplyRoomReverb()
    {
        var reverb = new Reverb(
            roomSize: 0.4f,    // Small room
            damping: 0.6f,     // More damping
            wetLevel: 0.3f,    // 30% reverb
            dryLevel: 0.8f     // 80% original
        );
        sourceManager.CustomSampleProcessor = reverb;
        Console.WriteLine("✅ Room reverb applied");
    }
    
    static void ApplyEchoDelay()
    {
        var delay = new Delay(
            delayMs: 500,      // 500ms delay
            feedback: 0.4f,    // 40% feedback
            wetLevel: 0.3f,    // 30% effect
            sampleRate: 44100
        );
        sourceManager.CustomSampleProcessor = delay;
        Console.WriteLine("✅ Echo delay applied");
    }
    
    static void ApplyPingPongDelay()
    {
        var delay = new Delay(
            delayMs: 250,      // 250ms delay
            feedback: 0.6f,    // 60% feedback
            wetLevel: 0.4f,    // 40% effect
            sampleRate: 44100
        );
        sourceManager.CustomSampleProcessor = delay;
        Console.WriteLine("✅ Ping-pong delay applied");
    }
    
    static void ApplyCompressor()
    {
        var compressor = new Compressor(
            threshold: 0.6f,   // Compress above 60%
            ratio: 4.0f,       // 4:1 ratio
            attackMs: 10f,     // Fast attack
            releaseMs: 100f,   // Medium release
            makeupGain: 1.2f,  // Compensate gain
            sampleRate: 44100f
        );
        sourceManager.CustomSampleProcessor = compressor;
        Console.WriteLine("✅ Compressor applied (4:1 ratio)");
    }
    
    static void ApplyEqualizer()
    {
        var equalizer = new Equalizer(44100);
        
        // Boost bass
        equalizer.SetBandGain(0, 60f, 3.0f, 1.0f);    // 60Hz +3dB
        equalizer.SetBandGain(1, 100f, 2.5f, 1.0f);   // 100Hz +2.5dB
        
        // Slight mid cut
        equalizer.SetBandGain(10, 800f, -1.0f, 2.0f); // 800Hz -1dB
        
        // Presence boost
        equalizer.SetBandGain(15, 3000f, 2.0f, 1.5f); // 3kHz +2dB
        
        sourceManager.CustomSampleProcessor = equalizer;
        Console.WriteLine("✅ EQ applied (Bass boost, presence enhancement)");
    }
    
    static void ClearEffects()
    {
        sourceManager.CustomSampleProcessor = null;
        Console.WriteLine("✅ All effects cleared");
    }
}

Real-Time Sine Wave Generator

Generate and stream audio in real-time with interactive control.

SineGenerator.cs Intermediate
using Ownaudio;
using Ownaudio.Sources;
using System;
using System.Threading;
using System.Threading.Tasks;

class SineGenerator
{
    private static SourceSound realtimeSource;
    private static bool isGenerating = false;
    private static float frequency = 440f; // A4
    private static float amplitude = 0.3f;
    private static int sampleRate = 44100;
    
    static async Task Main(string[] args)
    {
        try
        {
            OwnAudio.Initialize();
            var sourceManager = SourceManager.Instance;
            
            // Create real-time source
            realtimeSource = sourceManager.AddRealTimeSource(1.0f, 2, "SineWave");
            
            Console.WriteLine("🎵 Real-Time Sine Wave Generator");
            Console.WriteLine($"Initial frequency: {frequency}Hz");
            
            // Start audio generation
            StartGeneration();
            sourceManager.Play();
            
            await RunGeneratorControl();
        }
        finally
        {
            StopGeneration();
            OwnAudio.Free();
        }
    }
    
    static void StartGeneration()
    {
        isGenerating = true;
        
        Task.Run(async () =>
        {
            double phase = 0;
            int bufferSize = 1024;
            
            while (isGenerating && realtimeSource.State != SourceState.Idle)
            {
                float[] buffer = GenerateSineWave(bufferSize, ref phase);
                realtimeSource.SubmitSamples(buffer);
                
                // Control timing for smooth playback
                await Task.Delay(10);
            }
        });
    }
    
    static float[] GenerateSineWave(int samples, ref double phase)
    {
        float[] buffer = new float[samples * 2]; // Stereo
        double phaseIncrement = 2.0 * Math.PI * frequency / sampleRate;
        
        for (int i = 0; i < samples; i++)
        {
            float sample = (float)(Math.Sin(phase) * amplitude);
            
            buffer[i * 2] = sample;     // Left channel
            buffer[i * 2 + 1] = sample; // Right channel
            
            phase += phaseIncrement;
            if (phase >= 2.0 * Math.PI)
                phase -= 2.0 * Math.PI;
        }
        
        return buffer;
    }
    
    static async Task RunGeneratorControl()
    {
        while (isGenerating)
        {
            Console.WriteLine("\n=== Sine Wave Controls ===");
            Console.WriteLine($"Frequency: {frequency:F1}Hz | Amplitude: {amplitude:F2}");
            Console.WriteLine("W/S: Frequency ±50Hz | A/D: Frequency ±10Hz");
            Console.WriteLine("Q/E: Volume ±0.1 | Space: Musical notes | X: Exit");
            
            var key = Console.ReadKey(true).Key;
            
            switch (key)
            {
                case ConsoleKey.W: frequency += 50f; break;
                case ConsoleKey.S: frequency -= 50f; break;
                case ConsoleKey.A: frequency -= 10f; break;
                case ConsoleKey.D: frequency += 10f; break;
                case ConsoleKey.Q: amplitude = Math.Max(0.0f, amplitude - 0.1f); break;
                case ConsoleKey.E: amplitude = Math.Min(1.0f, amplitude + 0.1f); break;
                case ConsoleKey.Spacebar: await PlayMusicalNotes(); break;
                case ConsoleKey.X: return;
            }
            
            // Clamp frequency to reasonable range
            frequency = Math.Clamp(frequency, 20f, 20000f);
            
            Console.WriteLine($"Updated - Freq: {frequency:F1}Hz, Vol: {amplitude:F2}");
        }
    }
    
    static async Task PlayMusicalNotes()
    {
        float[] notes = { 261.63f, 293.66f, 329.63f, 349.23f, 392.00f, 440.00f, 493.88f, 523.25f }; // C-C octave
        string[] noteNames = { "C4", "D4", "E4", "F4", "G4", "A4", "B4", "C5" };
        
        Console.WriteLine("\n🎼 Playing musical scale...");
        
        for (int i = 0; i < notes.Length; i++)
        {
            frequency = notes[i];
            Console.WriteLine($"♪ {noteNames[i]} ({frequency:F1}Hz)");
            await Task.Delay(500);
        }
        
        frequency = 440f; // Reset to A4
        Console.WriteLine("Scale complete!");
    }
    
    static void StopGeneration()
    {
        isGenerating = false;
    }
}

Music Analysis and Chord Detection

Analyze audio files for musical content including chords, key, and tempo.

MusicAnalyzer.cs Advanced
using Ownaudio;
using Ownaudio.Sources;
using Ownaudio.Utilities.Extensions;
using System;
using System.Threading.Tasks;

class MusicAnalyzer
{
    static async Task Main(string[] args)
    {
        try
        {
            OwnAudio.Initialize();
            var sourceManager = SourceManager.Instance;
            
            // Get audio file from user
            Console.WriteLine("🎼 Music Analyzer");
            Console.Write("Enter path to audio file: ");
            string filePath = Console.ReadLine();
            
            if (string.IsNullOrEmpty(filePath) || !System.IO.File.Exists(filePath))
            {
                Console.WriteLine("File not found. Using default: demo.mp3");
                filePath = "demo.mp3";
            }
            
            // Load audio file
            Console.WriteLine("Loading audio file...");
            await sourceManager.AddOutputSource(filePath, "AnalysisTrack");
            
            var track = sourceManager["AnalysisTrack"];
            Console.WriteLine($"✅ Loaded: {System.IO.Path.GetFileName(filePath)}");
            Console.WriteLine($"Duration: {track.Duration}");
            
            // Start analysis
            await PerformMusicAnalysis(sourceManager, "AnalysisTrack");
            
            // Optional playback with visualization
            await PlaybackWithAnalysis(sourceManager);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Analysis error: {ex.Message}");
        }
        finally
        {
            OwnAudio.Free();
        }
    }
    
    static async Task PerformMusicAnalysis(SourceManager manager, string trackName)
    {
        Console.WriteLine("\n🔍 Analyzing musical content...");
        Console.WriteLine("This may take a moment for longer tracks...");
        
        try
        {
            // Perform chord detection analysis
            var (timedChords, detectedKey, tempo) = manager.DetectChords(trackName, intervalSecond: 1.0f);
            
            // Display analysis results
            Console.WriteLine("\n📊 Analysis Results:");
            Console.WriteLine($"🎵 Detected Key: {detectedKey ?? "Unknown"}");
            Console.WriteLine($"🥁 Estimated Tempo: {tempo:F1} BPM");
            Console.WriteLine($"🎼 Total Chord Changes: {timedChords.Count}");
            
            // Display chord progression
            Console.WriteLine("\n🎹 Chord Progression:");
            Console.WriteLine("Time       | Chord      | Confidence");
            Console.WriteLine("-----------|------------|------------");
            
            foreach (var chord in timedChords)
            {
                string timeRange = $"{chord.StartTime:F1}s-{chord.EndTime:F1}s";
                string confidenceStr = GetConfidenceString(chord.Confidence);
                
                Console.WriteLine($"{timeRange,-10} | {chord.ChordName,-10} | {confidenceStr}");
            }
            
            // Musical analysis summary
            AnalyzeChordProgression(timedChords, detectedKey);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Chord detection failed: {ex.Message}");
        }
    }
    
    static string GetConfidenceString(float confidence)
    {
        return confidence switch
        {
            >= 0.9f => "🟢 Excellent",
            >= 0.7f => "🟡 Good", 
            >= 0.5f => "🟠 Fair",
            _ => "🔴 Poor"
        };
    }
    
    static void AnalyzeChordProgression(System.Collections.Generic.List chords, string key)
    {
        if (chords.Count == 0) return;
        
        Console.WriteLine("\n📈 Musical Analysis:");
        
        // Find most common chords
        var chordCounts = new System.Collections.Generic.Dictionary();
        foreach (var chord in chords)
        {
            if (chord.ChordName != "Unknown")
            {
                chordCounts[chord.ChordName] = chordCounts.GetValueOrDefault(chord.ChordName, 0) + 1;
            }
        }
        
        if (chordCounts.Count > 0)
        {
            Console.WriteLine("🏆 Most Common Chords:");
            var sortedChords = chordCounts.OrderByDescending(x => x.Value).Take(5);
            foreach (var (chord, count) in sortedChords)
            {
                double percentage = (count * 100.0) / chords.Count;
                Console.WriteLine($"  {chord}: {count} times ({percentage:F1}%)");
            }
        }
        
        // Calculate average confidence
        var validChords = chords.Where(c => c.ChordName != "Unknown").ToList();
        if (validChords.Count > 0)
        {
            double avgConfidence = validChords.Average(c => c.Confidence);
            Console.WriteLine($"🎯 Average Detection Confidence: {avgConfidence:F2} ({GetConfidenceString((float)avgConfidence)})");
        }
        
        // Detect key changes
        if (!string.IsNullOrEmpty(key))
        {
            Console.WriteLine($"🗝️  Primary Key: {key}");
            
            // Simple modulation detection (basic implementation)
            var keyChanges = DetectSimpleKeyChanges(chords);
            if (keyChanges.Count > 1)
            {
                Console.WriteLine("🔄 Possible Key Changes Detected:");
                foreach (var change in keyChanges)
                {
                    Console.WriteLine($"  {change.Time:F1}s: Modulation to {change.NewKey}");
                }
            }
        }
    }
    
    static System.Collections.Generic.List<(double Time, string NewKey)> DetectSimpleKeyChanges(
        System.Collections.Generic.List chords)
    {
        var changes = new System.Collections.Generic.List<(double, string)>();
        
        // This is a simplified key change detection
        // In a real application, you'd use more sophisticated harmonic analysis
        
        string previousKey = null;
        foreach (var chord in chords.Where(c => c.ChordName != "Unknown"))
        {
            string currentKey = EstimateKeyFromChord(chord.ChordName);
            if (currentKey != null && currentKey != previousKey && previousKey != null)
            {
                changes.Add((chord.StartTime, currentKey));
            }
            previousKey = currentKey;
        }
        
        return changes;
    }
    
    static string EstimateKeyFromChord(string chordName)
    {
        // Simplified key estimation based on chord root
        // This is a basic implementation for demonstration
        if (chordName.StartsWith("C")) return "C Major";
        if (chordName.StartsWith("G")) return "G Major";
        if (chordName.StartsWith("Am")) return "A Minor";
        if (chordName.StartsWith("F")) return "F Major";
        if (chordName.StartsWith("Dm")) return "D Minor";
        
        return null; // Unknown key
    }
    
    static async Task PlaybackWithAnalysis(SourceManager manager)
    {
        Console.WriteLine("\n🎵 Playback with Real-time Analysis");
        Console.WriteLine("Press P to play/pause, S to stop, Q to quit");
        
        bool isPlaying = false;
        var analysisTask = Task.CompletedTask;
        
        while (true)
        {
            var key = Console.ReadKey(true).Key;
            
            switch (key)
            {
                case ConsoleKey.P:
                    if (isPlaying)
                    {
                        manager.Pause();
                        Console.WriteLine("⏸️  Paused");
                    }
                    else
                    {
                        manager.Play();
                        Console.WriteLine("▶️  Playing");
                        analysisTask = ShowRealtimePosition(manager);
                    }
                    isPlaying = !isPlaying;
                    break;
                    
                case ConsoleKey.S:
                    manager.Stop();
                    Console.WriteLine("⏹️  Stopped");
                    isPlaying = false;
                    break;
                    
                case ConsoleKey.Q:
                    if (isPlaying) manager.Stop();
                    return;
            }
        }
    }
    
    static async Task ShowRealtimePosition(SourceManager manager)
    {
        while (manager.IsPlaying)
        {
            var position = manager.Position;
            var duration = manager.Duration;
            double progress = position.TotalSeconds / duration.TotalSeconds * 100;
            
            Console.Write($"\r🎵 {position:mm\\:ss} / {duration:mm\\:ss} ({progress:F1}%) ");
            
            await Task.Delay(1000);
        }
        Console.WriteLine();
    }
}

🎚️ Professional Audio Mastering

Use OwnAudioSharp's intelligent matching system to achieve professional sound quality.

AudioMastering.cs
using Ownaudio.Utilities.Matchering;

class AudioMastering
{
    static void Main(string[] args)
    {
        var analyzer = new AudioAnalyzer();
        
        // Professional matchering - one line of code!
        analyzer.ProcessEQMatching(
            "my_track.wav",      // Your audio
            "reference.wav",     // Professional reference
            "mastered.wav"       // Studio-quality output
        );
        
        // Optimize for different playback systems
        analyzer.ProcessWithPreset("mastered.wav", "streaming.wav", 
            PlaybackSystem.RadioBroadcast);
            
        Console.WriteLine("✅ Professional mastering complete!");
    }
}

Real-Time Synthesizer with Effects

Advanced example combining real-time synthesis with live effects processing.

RealtimeSynth.cs Advanced
using Ownaudio;
using Ownaudio.Sources;
using Ownaudio.Processors;
using System;
using System.Threading;
using System.Threading.Tasks;

class RealtimeSynth
{
    private static SourceSound synthSource;
    private static SourceManager sourceManager;
    private static bool isRunning = false;
    
    // Synthesis parameters
    private static float[] frequencies = new float[4]; // 4-voice polyphony
    private static float[] amplitudes = new float[4];
    private static double[] phases = new double[4];
    private static bool[] noteStates = new bool[4];
    
    // Effect parameters
    private static bool reverbEnabled = false;
    private static bool delayEnabled = false;
    private static float masterVolume = 0.5f;
    
    static async Task Main(string[] args)
    {
        try
        {
            OwnAudio.Initialize();
            sourceManager = SourceManager.Instance;
            
            // Create real-time synthesis source
            synthSource = sourceManager.AddRealTimeSource(1.0f, 2, "Synthesizer");
            
            Console.WriteLine("🎹 Real-Time Synthesizer");
            Console.WriteLine("Features: 4-voice polyphony, reverb, delay");
            
            // Start synthesis engine
            StartSynthEngine();
            sourceManager.Play();
            
            await RunSynthController();
        }
        finally
        {
            StopSynthEngine();
            OwnAudio.Free();
        }
    }
    
    static void StartSynthEngine()
    {
        isRunning = true;
        
        Task.Run(async () =>
        {
            int bufferSize = 512;
            int sampleRate = 44100;
            
            while (isRunning && synthSource.State != SourceState.Idle)
            {
                float[] buffer = GeneratePolyphonic(bufferSize, sampleRate);
                synthSource.SubmitSamples(buffer);
                
                await Task.Delay(5); // ~100 updates per second
            }
        });
    }
    
    static float[] GeneratePolyphonic(int samples, int sampleRate)
    {
        float[] buffer = new float[samples * 2]; // Stereo
        
        for (int i = 0; i < samples; i++)
        {
            float mixedSample = 0f;
            
            // Generate and mix all active voices
            for (int voice = 0; voice < 4; voice++)
            {
                if (noteStates[voice] && frequencies[voice] > 0)
                {
                    double phaseIncrement = 2.0 * Math.PI * frequencies[voice] / sampleRate;
                    
                    // Generate waveform (saw wave for richer harmonics)
                    float sample = GenerateSawWave(phases[voice]) * amplitudes[voice];
                    
                    mixedSample += sample;
                    
                    phases[voice] += phaseIncrement;
                    if (phases[voice] >= 2.0 * Math.PI)
                        phases[voice] -= 2.0 * Math.PI;
                }
            }
            
            // Apply master volume
            mixedSample *= masterVolume;
            
            // Store stereo
            buffer[i * 2] = mixedSample;     // Left
            buffer[i * 2 + 1] = mixedSample; // Right
        }
        
        return buffer;
    }
    
    static float GenerateSawWave(double phase)
    {
        // Sawtooth wave: ramp from -1 to 1
        return (float)(2.0 * (phase / (2.0 * Math.PI)) - 1.0);
    }
    
    static async Task RunSynthController()
    {
        Console.WriteLine("\n🎛️ Synthesizer Controls:");
        Console.WriteLine("Piano Keys: Q W E R (voices 1-4)");
        Console.WriteLine("Octaves: Z X C V (low to high)");
        Console.WriteLine("Effects: 1=Reverb 2=Delay 3=Clear");
        Console.WriteLine("Volume: + - (master volume)");
        Console.WriteLine("ESC: Exit");
        
        // Musical note frequencies (4th octave)
        var noteFrequencies = new System.Collections.Generic.Dictionary
        {
            { ConsoleKey.Q, 261.63f }, // C4
            { ConsoleKey.W, 293.66f }, // D4
            { ConsoleKey.E, 329.63f }, // E4
            { ConsoleKey.R, 349.23f }, // F4
            { ConsoleKey.T, 392.00f }, // G4
            { ConsoleKey.Y, 440.00f }, // A4
            { ConsoleKey.U, 493.88f }, // B4
        };
        
        float octaveMultiplier = 1.0f;
        
        while (isRunning)
        {
            var keyInfo = Console.ReadKey(true);
            var key = keyInfo.Key;
            
            switch (key)
            {
                case ConsoleKey.Escape:
                    return;
                    
                // Octave controls
                case ConsoleKey.Z: octaveMultiplier = 0.5f; Console.WriteLine("🎵 Low octave"); break;
                case ConsoleKey.X: octaveMultiplier = 1.0f; Console.WriteLine("🎵 Mid octave"); break;
                case ConsoleKey.C: octaveMultiplier = 2.0f; Console.WriteLine("🎵 High octave"); break;
                case ConsoleKey.V: octaveMultiplier = 4.0f; Console.WriteLine("🎵 Very high octave"); break;
                
                // Effect controls
                case ConsoleKey.D1: ToggleReverb(); break;
                case ConsoleKey.D2: ToggleDelay(); break;
                case ConsoleKey.D3: ClearEffects(); break;
                
                // Volume controls
                case ConsoleKey.OemPlus:
                case ConsoleKey.Add:
                    masterVolume = Math.Min(1.0f, masterVolume + 0.1f);
                    Console.WriteLine($"🔊 Volume: {masterVolume:F1}");
                    break;
                case ConsoleKey.OemMinus:
                case ConsoleKey.Subtract:
                    masterVolume = Math.Max(0.0f, masterVolume - 0.1f);
                    Console.WriteLine($"🔉 Volume: {masterVolume:F1}");
                    break;
                
                // Note triggers
                default:
                    if (noteFrequencies.ContainsKey(key))
                    {
                        TriggerNote(noteFrequencies[key] * octaveMultiplier);
                    }
                    break;
            }
        }
    }
    
    static void TriggerNote(float frequency)
    {
        // Find an available voice
        for (int i = 0; i < 4; i++)
        {
            if (!noteStates[i])
            {
                frequencies[i] = frequency;
                amplitudes[i] = 0.3f; // Volume per voice
                phases[i] = 0;
                noteStates[i] = true;
                
                Console.WriteLine($"🎹 Note ON: {frequency:F1}Hz (Voice {i + 1})");
                
                // Auto-release after 1 second
                Task.Delay(1000).ContinueWith(_ => ReleaseNote(i));
                return;
            }
        }
        
        Console.WriteLine("🚫 All voices busy!");
    }
    
    static void ReleaseNote(int voice)
    {
        if (voice >= 0 && voice < 4)
        {
            noteStates[voice] = false;
            Console.WriteLine($"🎹 Note OFF: Voice {voice + 1}");
        }
    }
    
    static void ToggleReverb()
    {
        reverbEnabled = !reverbEnabled;
        
        if (reverbEnabled)
        {
            var reverb = new Reverb(0.6f, 0.4f, 0.4f, 0.7f);
            sourceManager.CustomSampleProcessor = reverb;
            Console.WriteLine("✅ Reverb ON");
        }
        else
        {
            sourceManager.CustomSampleProcessor = null;
            Console.WriteLine("❌ Reverb OFF");
        }
    }
    
    static void ToggleDelay()
    {
        delayEnabled = !delayEnabled;
        
        if (delayEnabled)
        {
            var delay = new Delay(300, 0.4f, 0.3f, 44100);
            sourceManager.CustomSampleProcessor = delay;
            Console.WriteLine("✅ Delay ON");
        }
        else
        {
            sourceManager.CustomSampleProcessor = null;
            Console.WriteLine("❌ Delay OFF");
        }
    }
    
    static void ClearEffects()
    {
        sourceManager.CustomSampleProcessor = null;
        reverbEnabled = false;
        delayEnabled = false;
        Console.WriteLine("🧹 All effects cleared");
    }
    
    static void StopSynthEngine()
    {
        isRunning = false;
        
        // Release all notes
        for (int i = 0; i < 4; i++)
        {
            noteStates[i] = false;
        }
    }
}
Demo Application: For a complete Avalonia MVVM example with GUI controls, check out the OwnAudioSharp Demo repository. It demonstrates all features with a professional user interface.

Audio Visualization with Avalonia

Create interactive waveform displays for audio applications.

MainWindow.axaml
<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:audio="using:Ownaudio.Utilities"
        x:Class="AudioVisualizer.MainWindow"
        Title="Audio Visualizer" Height="600" Width="900">

    <Grid RowDefinitions="Auto,*,Auto">
        
        <!-- Controls -->
        <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="10">
            <Button Name="LoadButton" Content="Load Audio" Margin="5"/>
            <Button Name="PlayButton" Content="Play" Margin="5"/>
            <Button Name="PauseButton" Content="Pause" Margin="5"/>
            <Button Name="StopButton" Content="Stop" Margin="5"/>
        </StackPanel>
        
        <!-- Waveform Display -->
        <audio:WaveAvaloniaDisplay Grid.Row="1" 
                                  Name="WaveformDisplay"
                                  WaveformBrush="DodgerBlue"
                                  PlaybackPositionBrush="Red"
                                  VerticalScale="1.5"
                                  DisplayStyle="MinMax"
                                  Margin="10"/>
        
        <!-- Status Bar -->
        <TextBlock Grid.Row="2" Name="StatusText" 
                   Text="Ready" Margin="10" 
                   HorizontalAlignment="Center"/>
                   
    </Grid>
</Window>
MainWindow.axaml.cs
using Avalonia.Controls;
using Avalonia.Interactivity;
using Ownaudio;
using Ownaudio.Sources;
using System;
using System.Threading.Tasks;

namespace AudioVisualizer
{
    public partial class MainWindow : Window
    {
        private SourceManager sourceManager;
        
        public MainWindow()
        {
            InitializeComponent();
            InitializeAudio();
            SetupEventHandlers();
        }
        
        private void InitializeAudio()
        {
            try
            {
                OwnAudio.Initialize();
                sourceManager = SourceManager.Instance;
            }
            catch (Exception ex)
            {
                StatusText.Text = $"Audio initialization failed: {ex.Message}";
            }
        }
        
        private void SetupEventHandlers()
        {
            LoadButton.Click += LoadButton_Click;
            PlayButton.Click += PlayButton_Click;
            PauseButton.Click += PauseButton_Click;
            StopButton.Click += StopButton_Click;
            
            // Handle waveform position changes
            WaveformDisplay.PlaybackPositionChanged += OnPlaybackPositionChanged;
        }
        
        private async void LoadButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var dialog = new OpenFileDialog
                {
                    Title = "Select Audio File",
                    Filters = new[]
                    {
                        new FileDialogFilter { Name = "Audio Files", Extensions = { "mp3", "wav", "flac", "ogg" } },
                        new FileDialogFilter { Name = "All Files", Extensions = { "*" } }
                    }
                };
                
                var files = await dialog.ShowAsync(this);
                if (files?.Length > 0)
                {
                    await LoadAudioFile(files[0]);
                }
            }
            catch (Exception ex)
            {
                StatusText.Text = $"Load error: {ex.Message}";
            }
        }
        
        private async Task LoadAudioFile(string filePath)
        {
            StatusText.Text = "Loading audio file...";
            
            try
            {
                // Clear existing sources
                sourceManager.Stop();
                
                // Load new audio file
                await sourceManager.AddOutputSource(filePath, "MainTrack");
                
                // Load waveform data
                var audioData = sourceManager["MainTrack"].GetFloatAudioData(TimeSpan.Zero);
                WaveformDisplay.SetAudioData(audioData);
                
                StatusText.Text = $"Loaded: {System.IO.Path.GetFileName(filePath)} ({sourceManager["MainTrack"].Duration})";
            }
            catch (Exception ex)
            {
                StatusText.Text = $"Failed to load: {ex.Message}";
            }
        }
        
        private void PlayButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                sourceManager.Play();
                StatusText.Text = "Playing...";
                
                // Start position updates
                StartPositionUpdates();
            }
            catch (Exception ex)
            {
                StatusText.Text = $"Play error: {ex.Message}";
            }
        }
        
        private void PauseButton_Click(object sender, RoutedEventArgs e)
        {
            sourceManager.Pause();
            StatusText.Text = "Paused";
        }
        
        private void StopButton_Click(object sender, RoutedEventArgs e)
        {
            sourceManager.Stop();
            WaveformDisplay.PlaybackPosition = 0;
            StatusText.Text = "Stopped";
        }
        
        private void OnPlaybackPositionChanged(object sender, double position)
        {
            // User clicked/dragged on waveform - seek to position
            if (sourceManager.Sources.Count > 0)
            {
                var newTime = TimeSpan.FromSeconds(position * sourceManager.Duration.TotalSeconds);
                sourceManager.Seek(newTime);
            }
        }
        
        private async void StartPositionUpdates()
        {
            while (sourceManager.IsPlaying)
            {
                // Update waveform playback position
                if (sourceManager.Duration.TotalSeconds > 0)
                {
                    double position = sourceManager.Position.TotalSeconds / sourceManager.Duration.TotalSeconds;
                    WaveformDisplay.PlaybackPosition = position;
                }
                
                await Task.Delay(50); // 20 FPS updates
            }
        }
        
        protected override void OnClosed(EventArgs e)
        {
            sourceManager?.Stop();
            OwnAudio.Free();
            base.OnClosed(e);
        }
    }
}
More Examples: Visit the GitHub repository for additional examples, unit tests, and community contributions. The examples cover everything from basic audio playback to advanced real-time audio processing applications.