### Complete FileSource Example Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-sources.html A comprehensive example of initializing and configuring a FileSource, including setting volume, tempo, pitch, start offset, and handling state changes. ```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); ``` -------------------------------- ### C# Basic Setup and Usage Source: https://github.com/modernmube/ownaudiosharp/blob/master/index.html Demonstrates the basic setup for OwnAudioSharp, including initialization, starting the engine, creating a mixer, playing an audio file, adding a reverb effect, and proper cleanup. ```csharp using OwnaudioNET; using OwnaudioNET.Mixing; using OwnaudioNET.Sources; // Initialize (async — safe for all UI frameworks) await OwnaudioNet.InitializeAsync(); OwnaudioNet.Start(); // Create the mixer var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine); mixer.Start(); // Play a file var track = new FileSource("song.mp3"); mixer.AddSource(track); // Add reverb var reverb = new ReverbEffect { RoomSize = 0.7f, Mix = 0.3f }; mixer.AddMasterEffect(reverb); // Cleanup mixer.Dispose(); await OwnaudioNet.ShutdownAsync(); ``` -------------------------------- ### Basic NativeAudioEngine Usage Example Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Native/README.md Demonstrates how to initialize, start, send audio data to, stop, and dispose of the NativeAudioEngine. ```csharp using Ownaudio.Core; using Ownaudio.Native; // Create and initialize engine var engine = new NativeAudioEngine(); var config = AudioConfig.Default; // 48kHz, 2 channels, 512 frames/buffer int result = engine.Initialize(config); if (result != 0) { Console.WriteLine($"Failed to initialize: {result}"); return; } // Start playback engine.Start(); // Send audio data (non-blocking) float[] audioSamples = new float[config.FramesPerBuffer * config.Channels]; // ... fill audioSamples ... engine.Send(audioSamples); // Stop and cleanup engine.Stop(); engine.Dispose(); ``` -------------------------------- ### InputSource Setup and Playback Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-sources.html Shows how to initialize the audio engine to enable input, create an InputSource, and add it to 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(); ``` -------------------------------- ### Install Linux Dependencies Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Install required system libraries for audio and media processing on Ubuntu or Debian. ```bash sudo apt update sudo apt install portaudio19-dev ffmpeg ``` -------------------------------- ### Basic Engine Initialization and Playback Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Core/README.md Demonstrates how to create, initialize, start, send samples to, and stop the audio engine. ```csharp using Ownaudio.Core; // Create engine with factory var engine = AudioEngineFactory.CreateDefault(); // Initialize asynchronously await engine.InitializeAsync(AudioConfig.Default); // Start playback engine.Start(); // Send audio samples float[] samples = GenerateAudioSamples(512 * 2); // 512 frames * 2 channels engine.Send(samples); // Stop and cleanup await engine.StopAsync(); engine.Dispose(); ``` -------------------------------- ### Initialize OwnAudio on Linux Source: https://github.com/modernmube/ownaudiosharp/wiki/Home Install system dependencies before initializing the library. ```bash sudo apt update sudo apt install portaudio19-dev ffmpeg ``` ```csharp // Auto-detection - no path needed OwnAudio.Initialize(); ``` -------------------------------- ### Quick Start: Initialize and Play Audio Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Source/README.Basic.md Initializes the audio engine, creates a mixer, and plays an MP3 file. Ensure 'music.mp3' exists in the project. ```csharp using OwnaudioNET; // Initialize the audio engine OwnaudioNet.Initialize(); OwnaudioNet.Start(); // Create the audio mixer using the underlying engine var mixer = new AudioMixer(OwnaudioNet.Engine.UnderlyingEngine); mixer.Start(); // Play an audio file var music = new FileSource("music.mp3"); mixer.AddSource(music); ``` -------------------------------- ### Initialize and Play Audio Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Source/README.Mobile.md Initializes the audio engine, starts playback, and adds a file source to the mixer. Ensure OwnaudioNet is initialized and started before creating the mixer. ```csharp using OwnaudioNET; using OwnaudioNET.Features.Vocalremover; // Initialize the audio engine OwnaudioNet.Initialize(); OwnaudioNet.Start(); // Create the audio mixer using the underlying engine var mixer = new AudioMixer(OwnaudioNet.Engine.UnderlyingEngine); mixer.Start(); // Play an audio file var music = new FileSource("music.mp3"); mixer.AddSource(music); ``` -------------------------------- ### MIDI Keyboard Recorder Example Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-midi.html This full example shows how to record incoming MIDI events with timestamps and save them to a Standard MIDI File. It converts absolute ticks to delta times for the file. ```C# using OwnAudio.Midi.IO; using OwnAudio.Midi.File; var recordedEvents = new List<(long absoluteTick, MidiEvent evt)>(); var startTime = DateTimeOffset.UtcNow; const ushort TicksPerBeat = 480; const int Bpm = 120; int tempoUs = 60_000_000 / Bpm; double ticksPerMs = TicksPerBeat * Bpm / 60_000.0; using IMidiInputPort input = MidiPortFactory.OpenInput( MidiPortFactory.GetInputPortNames()[0]); input.MessageReceived += msg = { long ms = (long)(DateTimeOffset.UtcNow - startTime).TotalMilliseconds; long tick = (long)(ms * ticksPerMs); recordedEvents.Add((tick, new MidiEvent(0, msg.Status, msg.Data1, msg.Data2))); }; input.Start(); Console.WriteLine("Recording... press Enter to stop."); Console.ReadLine(); input.Stop(); // Convert absolute ticks to delta times recordedEvents.Sort((a, b) => a.absoluteTick.CompareTo(b.absoluteTick)); var midiEvents = new List(); byte[] tempoBytes = [(byte)(tempoUs >> 16), (byte)(tempoUs >> 8), (byte)tempoUs]; midiEvents.Add(new MidiEvent(0, 0x51, tempoBytes)); long prev = 0; foreach (var (tick, evt) in recordedEvents) { int delta = (int)(tick - prev); prev = tick; midiEvents.Add(new MidiEvent(delta, evt.Status, evt.Data1, evt.Data2)); } var midiFile = new MidiFile(0, TicksPerBeat, [new MidiTrack(midiEvents)]); MidiFileWriter.Write(midiFile, "recording.mid"); Console.WriteLine("Saved: recording.mid"); ``` -------------------------------- ### Install macOS Dependencies Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Use Homebrew to install PortAudio and FFmpeg on macOS. ```bash brew install portaudio brew install ffmpeg@6 ``` -------------------------------- ### Start Network Sync Server Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-network.html Initializes and starts the network sync server. This device will broadcast its MasterClock timeline to clients on the LAN. Ensure an AudioMixer is created and started before initiating server mode. ```csharp await OwnaudioNet.InitializeAsync(); OwnaudioNet.Start(); var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine); mixer.Start(); // Start server — broadcasts MasterClock to LAN await OwnaudioNet.StartNetworkSyncServerAsync(port: 9876, useLocalTimeOnly: true); // From this point, control playback normally: mixer.Seek(0); var track = new FileSource("backing.mp3"); track.AttachToClock(mixer.MasterClock); track.Play(); mixer.AddSource(track); // Stop network sync when done await OwnaudioNet.StopNetworkSyncAsync(); ``` -------------------------------- ### Recommended Startup Pattern Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-reference.html Initializes the audio engine with a default configuration, optionally setting the host type based on the OS, and starts the engine and mixer. Use async variants for initialization to avoid blocking UI threads. ```csharp protected override async Task OnInitializedAsync() { var config = OwnaudioNet.CreateDefaultConfig(); config.EnableInput = false; if (OperatingSystem.IsWindows()) config.HostType = EngineHostType.WASAPI; await OwnaudioNet.InitializeAsync(config); OwnaudioNet.Start(); _mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine, bufferSizeInFrames: 1024); _mixer.Start(); } ``` -------------------------------- ### Run Multi-Model Separator via CLI Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Examples/Ownaudio.Example.MultimodelSeparator/README.md Commands to execute the example project and pass arguments for input/output paths. ```bash cd OwnAudio/Examples/Ownaudio.Example.MultimodelSeparator dotnet run ``` ```bash # Run with custom input and output paths dotnet run "path/to/song.mp3" "path/to/output" # Show help dotnet run --help ``` -------------------------------- ### Install OwnAudioSharp via NuGet Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Use these commands in your package manager to add the library to your project. ```bash NuGet\Install-Package OwnAudioSharp ``` ```powershell Install-Package OwnAudioSharp ``` -------------------------------- ### Start Network Sync Client Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-network.html Initializes and starts the network sync client. This device will synchronize its MasterClock to a server's timeline, allowing it to play audio in sync with other clients. The client can optionally continue playback if the server disconnects. ```csharp await OwnaudioNet.InitializeAsync(); OwnaudioNet.Start(); var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine); mixer.Start(); // Connect to server (null = UDP auto-discovery) await OwnaudioNet.StartNetworkSyncClientAsync( serverAddress: "192.168.1.100", // or null for auto-discovery port: 9876, allowOfflinePlayback: true); // continue if server disconnects // Load client's own audio — clock is controlled by server var clientTrack = new FileSource("client-audio.mp3"); clientTrack.AttachToClock(mixer.MasterClock); clientTrack.Play(); mixer.AddSource(clientTrack); ``` -------------------------------- ### Setup Synchronized Playback Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Examples/Ownaudio.Example.Android/README.md Adds audio sources to the mixer, creates a sync group for sample-accurate playback, and configures tempo and drift correction. Playback is then started. ```csharp // Add all sources to mixer _mixer.AddSource(_fileSource0); _mixer.AddSource(_fileSource1); _mixer.AddSource(_fileSource2); _mixer.AddSource(_fileSource3Effect); // Create sync group for sample-accurate playback _mixer.CreateSyncGroup("Demo", _fileSource0, _fileSource1, _fileSource2, _fileSource3); _mixer.SetSyncGroupTempo("Demo", 1.0f); _mixer.CheckAndResyncAllGroups(toleranceInFrames: 30); _mixer.EnableAutoDriftCorrection = true; // Start mixer and sync group _mixer.Start(); _mixer.StartSyncGroup("Demo"); ``` -------------------------------- ### Install PortAudio on Fedora Linux Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Native/README.md Install PortAudio and its development packages on Fedora Linux. ```bash sudo dnf install portaudio portaudio-devel ``` -------------------------------- ### Install PortAudio on Arch Linux Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Native/README.md Install PortAudio on Arch Linux systems. ```bash sudo pacman -S portaudio ``` -------------------------------- ### Initialize OwnAudio on macOS Source: https://github.com/modernmube/ownaudiosharp/wiki/Home Install system dependencies via Homebrew before initializing the library. ```bash brew install portaudio brew install ffmpeg@6 ``` ```csharp // Auto-detection - no path needed OwnAudio.Initialize(); ``` -------------------------------- ### Build MultitrackPlayer Project Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Examples/Ownaudio.Example.MultitrackPlayer/README.md Use this command to build the MultitrackPlayer project from the command line. Ensure .NET 9.0 SDK is installed. ```bash dotnet build MultitrackPlayer.csproj ``` -------------------------------- ### OwnaudioNet Initialization and Lifecycle Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-core.html Provides examples for initializing and managing the audio engine synchronously and asynchronously. Includes options for custom configurations, unit testing with mock engines, and handling heavy DSP loads. ```APIDOC ## OwnaudioNet Initialization and Lifecycle ### Description Methods for initializing, starting, stopping, and shutting down the audio engine. ### Initialization & Lifecycle **Synchronous Initialization (Console Apps / Services)** ```csharp // Default config: 48kHz, stereo, 512 frames OwnaudioNet.Initialize(); // Custom config OwnaudioNet.Initialize(config); // Unit testing — no hardware required OwnaudioNet.Initialize(config, useMockEngine: true); // Heavy DSP load: 8+ sources or 2+ VST master effects (~170 ms headroom) OwnaudioNet.Initialize(config, bufferMultiplier: 16); ``` **Asynchronous Initialization (Recommended for UI Apps)** ```csharp // Default config await OwnaudioNet.InitializeAsync(); await OwnaudioNet.InitializeAsync(cancellationToken); // Custom config await OwnaudioNet.InitializeAsync(config); await OwnaudioNet.InitializeAsync(config, useMockEngine: false, cancellationToken: cancellationToken); // Heavy DSP load: 8+ sources or 2+ VST master effects await OwnaudioNet.InitializeAsync(config, bufferMultiplier: 16, cancellationToken: cancellationToken); // Pre-created engine (custom platform implementations) await OwnaudioNet.InitializeAsync(engine, config, bufferMultiplier: 16, cancellationToken: cancellationToken); ``` **Start, Stop, and Shutdown** ```csharp // Start and stop OwnaudioNet.Start(); OwnaudioNet.Stop(); // Full release of all resources OwnaudioNet.Shutdown(); // Asynchronous stop / shutdown await OwnaudioNet.StopAsync(cancellationToken); await OwnaudioNet.ShutdownAsync(cancellationToken); ``` **Note on `bufferMultiplier`**: Controls the size of the internal `CircularBuffer`. Default 8 provides ~85 ms headroom at 48 kHz / 512 frames. Use 16 for 8+ simultaneous sources or 2+ VST master effects to prevent audio dropouts. Pair with `AudioMixer.Create()` for output routing. ``` -------------------------------- ### Add OwnAudio.Midi NuGet Package Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Midi/README.md Install the OwnAudio.Midi library from NuGet once it is published. ```xml ``` -------------------------------- ### Install PortAudio on macOS Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Native/README.md Use Homebrew to install PortAudio on macOS systems. ```bash brew install portaudio ``` -------------------------------- ### Install PortAudio on Debian/Ubuntu Linux Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Native/README.md Install PortAudio development files and libraries on Debian-based Linux distributions. ```bash sudo apt-get install portaudio19-dev libportaudio2 ``` -------------------------------- ### Install APK using ADB Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Examples/Ownaudio.Example.Android/README.md Install the built Android application package (APK) onto a connected device or emulator using the Android Debug Bridge (adb) command-line tool. ```bash # Using adb (Android Debug Bridge) சனம் install bin/Debug/net9.0-android/com.ownaudio.androidtest-Signed.apk # Or deploy directly dotnet build -c Debug -f net9.0-android -t:Install ``` -------------------------------- ### Define Project Dependencies in CSPROJ Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Example configuration for a .NET 8.0 console application using the OwnAudioSharp NuGet package. ```xml Exe net8.0 enable ``` -------------------------------- ### Basic Audio Playback Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/quickstart.html Minimal C# code to initialize the audio engine, start playback, load a file, and clean up. ```csharp using OwnaudioNET; using OwnaudioNET.Mixing; using OwnaudioNET.Sources; // 1. Initialize (async is required in UI apps) await OwnaudioNet.InitializeAsync(); OwnaudioNet.Start(); // 2. Create the mixer var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine); mixer.Start(); // 3. Load and play var track = new FileSource("song.mp3"); mixer.AddSource(track); // 4. Cleanup on app exit mixer.Dispose(); await OwnaudioNet.ShutdownAsync(); ``` -------------------------------- ### Add OwnAudioSharp NuGet Packages Source: https://github.com/modernmube/ownaudiosharp/blob/master/README.md Install the appropriate OwnAudioSharp NuGet package using the .NET CLI. Choose 'OwnAudioSharp' for desktop with full features, 'OwnAudioSharp.Mobile' for mobile, or 'OwnAudioSharp.Basic' for a lightweight version without AI/ML. ```bash dotnet add package OwnAudioSharp ``` ```bash dotnet add package OwnAudioSharp.Mobile ``` ```bash dotnet add package OwnAudioSharp.Basic ``` -------------------------------- ### Heavy Load Setup: Initialize with Buffer Headroom Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-mixer.html Prepare for heavy loads by initializing OwnaudioNet with a larger buffer multiplier. This provides more headroom for the mix thread, especially when using 8+ sources or 2+ master effects. ```csharp // bufferMultiplier: 16 → ~170 ms headroom at 48 kHz / 512 frames // (default 8 → ~85 ms; increase further only if dropouts persist) await OwnaudioNet.InitializeAsync(config, bufferMultiplier: 16); ``` -------------------------------- ### VU Metering for Audio Levels Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-mixer.html Monitor real-time peak audio levels for VU metering. This example shows how to update master bus levels and per-track levels using a timer. ```csharp // Update at ~10Hz (100ms timer) _vuTimer = new Timer(_ => { // Master bus float leftDb = 20f * MathF.Log10(Math.Max(mixer.LeftPeak, 1e-6f)); float rightDb = 20f * MathF.Log10(Math.Max(mixer.RightPeak, 1e-6f)); MasterLeftDb = Math.Max(leftDb, -60f); MasterRightDb = Math.Max(rightDb, -60f); // Per-track (if source is BaseAudioSource) var (l, r) = source.OutputLevels; TrackLeftDb = 20f * MathF.Log10(Math.Max(l, 1e-6f)); }, null, 0, 100); ``` -------------------------------- ### SampleSource Initialization Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-sources.html Illustrates creating a SampleSource from pre-loaded audio samples and playing it. ```C# // Static sample float[] samples = LoadSamplesFromFile("click.wav"); var click = new SampleSource(samples, OwnaudioNet.CreateDefaultConfig()); mixer.AddSource(click); click.Play(); ``` -------------------------------- ### Configure OwnAudio Initialization Source: https://github.com/modernmube/ownaudiosharp/wiki/Home Demonstrates various initialization methods including default, host API specific, and custom path configurations. ```csharp // Simple initialization with default settings bool success = OwnAudio.Initialize(); // With specific host API bool success = OwnAudio.Initialize(OwnAudioEngine.EngineHostType.WASAPI); // With custom library path bool success = OwnAudio.Initialize(@"C:\libraries\", OwnAudioEngine.EngineHostType.ASIO); ``` -------------------------------- ### Implement a Simple Audio Player in C# Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Demonstrates the full lifecycle of an audio player, including initialization, loading a source, handling playback controls, and resource cleanup. ```csharp using System; using System.Threading.Tasks; using Ownaudio; using Ownaudio.Sources; namespace SimpleAudioPlayer { class Program { static async Task Main(string[] args) { Console.WriteLine("OwnAudioSharp Simple Audio Player"); Console.WriteLine("=================================="); try { // 1. Initialize OwnAudio if (!OwnAudio.Initialize()) { Console.WriteLine("Error: Failed to initialize audio system!"); return; } Console.WriteLine("Audio system successfully initialized."); // 2. Get SourceManager instance var sourceManager = SourceManager.Instance; // 3. Load audio file Console.Write("Enter the audio file path: "); string? audioPath = Console.ReadLine(); if (string.IsNullOrEmpty(audioPath)) { Console.WriteLine("Valid file path is required!"); return; } Console.WriteLine("Loading audio file..."); bool isLoaded = await sourceManager.AddOutputSource(audioPath, "MainTrack"); if (!isLoaded) { Console.WriteLine("Error: Failed to load audio file!"); return; } Console.WriteLine($"Successfully loaded! Duration: {sourceManager.Duration}"); // 4. Playback control await PlaybackControl(sourceManager); } catch (Exception ex) { Console.WriteLine($"Error occurred: {ex.Message}"); } finally { // 5. Free resources OwnAudio.Free(); Console.WriteLine("Resources freed. Press any key to exit..."); Console.ReadKey(); } } static async Task PlaybackControl(SourceManager sourceManager) { bool isRunning = true; Console.WriteLine("\nControls:"); Console.WriteLine("P - Play/Pause"); Console.WriteLine("S - Stop"); Console.WriteLine("R - Restart"); Console.WriteLine("+ - Volume up"); Console.WriteLine("- - Volume down"); Console.WriteLine("Q - Quit"); while (isRunning) { Console.Write($"\rState: {sourceManager.State} | " + $"Position: {sourceManager.Position:mm\\:ss}/{sourceManager.Duration:mm\\:ss} | " + $"Volume: {sourceManager.Volume:P0} | Command: "); var key = Console.ReadKey(true); switch (char.ToUpper(key.KeyChar)) { case 'P': if (sourceManager.State == SourceState.Playing) { sourceManager.Pause(); } else { sourceManager.Play(); } break; case 'S': sourceManager.Stop(); break; case 'R': sourceManager.Stop(); sourceManager.Seek(TimeSpan.Zero); sourceManager.Play(); break; case '+': case '=': sourceManager.Volume = Math.Min(1.0f, sourceManager.Volume + 0.1f); break; case '-': sourceManager.Volume = Math.Max(0.0f, sourceManager.Volume - 0.1f); break; case 'Q': sourceManager.Stop(); isRunning = false; break; } await Task.Delay(100); } } } } ``` -------------------------------- ### Build and Run Project Commands Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Standard CLI commands to build and execute the application. ```bash dotnet build dotnet run ``` -------------------------------- ### Perform Simple Audio Playback Source: https://github.com/modernmube/ownaudiosharp/wiki/Home Initializes the library, configures output options, plays an audio file, and cleans up resources. ```csharp // Initialize library if (!OwnAudio.Initialize()) return; // Get SourceManager instance var sourceManager = SourceManager.Instance; // Configure output SourceManager.OutputEngineOptions = new AudioEngineOutputOptions( device: OwnAudio.DefaultOutputDevice, channels: OwnAudioEngine.EngineChannels.Stereo, sampleRate: 44100, latency: OwnAudio.DefaultOutputDevice.DefaultHighOutputLatency ); // Add and play audio file await sourceManager.AddOutputSource("audio.mp3"); sourceManager.Play(); // Cleanup sourceManager.Reset(); OwnAudio.Free(); ``` -------------------------------- ### Troubleshoot Audio Initialization and Loading Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Provides checks for verifying system initialization and successful audio file loading. ```csharp // Check initialization if (!OwnAudio.Initialize()) { Console.WriteLine("Audio system initialization failed!"); return; } // Check source loading bool loaded = await sourceManager.AddOutputSource("test.mp3"); if (!loaded) { Console.WriteLine("Audio file loading failed!"); return; } ``` -------------------------------- ### Initialize and Use VST3 Plugin Host Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/quickstart.html Creates an asynchronous VST3 plugin host, initializes it with sample rate and block size, and adds its processor as a master effect. ```csharp using OwnaudioNET.Effects; var host = await VST3PluginHost.CreateAsync("/path/to/reverb.vst3"); int sr = OwnaudioNet.Engine!.Config.SampleRate; await host.InitializeAudioAsync(sr, maxBlockSize: 1024); // Use as master effect mixer.AddMasterEffect(host.GetProcessor()); ``` -------------------------------- ### Manage Real-Time Audio Sources Source: https://github.com/modernmube/ownaudiosharp/wiki/Home Demonstrates creating a real-time audio source and submitting samples to it. ```csharp // Create real-time source SourceSound source = sourceManager.AddRealTimeSource(0.4f, 1); // 40% volume, mono // Submit audio samples float[] samples = GetAudioSamples(); source.SubmitSamples(samples); ``` -------------------------------- ### Mixer Lifecycle Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-mixer.html Controls the overall lifecycle of the audio mixer, from starting and pausing to stopping and releasing resources. ```APIDOC ## Mixer Lifecycle ### Description Manages the audio processing lifecycle. ### Methods - `Start()`: Begin audio processing. - `Pause()`: Freeze the mix thread. - `Stop()`: Stop processing and clear all sources. - `Seek(double positionInSec)`: Seek the master clock and all attached sources to a specific position. - `Dispose()`: Release all resources associated with the mixer. ``` -------------------------------- ### Write New MIDI File From Scratch Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Midi/README.md Creates a new MIDI file with a tempo, a C major scale played on a piano, and saves it. ```csharp using OwnAudio.Midi.File; const ushort TicksPerBeat = 480; const int Bpm = 120; int tempoUs = 60_000_000 / Bpm; // 500_000 var events = new List(); // Tempo meta event (type 0x51, 3 bytes) byte[] tempoBytes = [(byte)(tempoUs >> 16), (byte)(tempoUs >> 8), (byte)tempoUs]; events.Add(new MidiEvent(0, 0x51, tempoBytes)); // Program Change channel 0, piano events.Add(new MidiEvent(0, 0xC0, 0, 0)); // Helper: ticks from beat position long T(double beats) => (long)(beats * TicksPerBeat); // Build a C major scale: C D E F G A B C int[] scale = [60, 62, 64, 65, 67, 69, 71, 72]; long cursor = 0; for (int i = 0; i < scale.Length; i++) { long noteOnTick = T(i); long noteOffTick = T(i + 0.9); int deltaOn = (int)(noteOnTick - cursor); cursor = noteOnTick; int deltaOff = (int)(noteOffTick - cursor); cursor = noteOffTick; events.Add(new MidiEvent(deltaOn, 0x90, (byte)scale[i], 80)); // Note On events.Add(new MidiEvent(deltaOff, 0x80, (byte)scale[i], 0)); // Note Off } // End of Track is appended automatically by MidiFileWriter if missing var midiFile = new MidiFile(0, TicksPerBeat, [new MidiTrack(events)]); MidiFileWriter.Write(midiFile, "c_major_scale.mid"); ``` -------------------------------- ### Getting SmartMasterEffect Measurement Status Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-effects.html Retrieves the current status information for the SmartMasterEffect's room measurement process. ```csharp MeasurementStatusInfo status = smartMaster.GetMeasurementStatus(); ``` -------------------------------- ### Generate Real-time Audio in C# Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Shows how to create a real-time source and submit generated sine wave samples to the audio engine. ```csharp // Create real-time source var realtimeSource = sourceManager.AddRealTimeSource(1.0f, 2, "Synthesizer"); // Generate sine wave await Task.Run(async () { int sampleRate = 44100; int frequency = 440; // A4 note float amplitude = 0.3f; double phase = 0; double phaseIncrement = 2.0 * Math.PI * frequency / sampleRate; for (int i = 0; i < 1000; i++) // 1000 buffers { float[] buffer = new float[1024 * 2]; // Stereo for (int j = 0; j < 1024; j++) { float sample = (float)(Math.Sin(phase) * amplitude); buffer[j * 2] = sample; // Left channel buffer[j * 2 + 1] = sample; // Right channel phase += phaseIncrement; if (phase >= 2.0 * Math.PI) phase -= 2.0 * Math.PI; } realtimeSource.SubmitSamples(buffer); await Task.Delay(10); } }); ``` -------------------------------- ### Error Handling with AudioException Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Core/README.md All errors are reported via exceptions derived from `AudioException`. This example shows how to catch and handle these exceptions. ```APIDOC ## Error Handling ### Description Exceptions derived from `AudioException` are used to report errors. This section demonstrates how to catch these exceptions and access error details. ### Exception Types - `PlatformNotSupportedException`: For platform-related issues. - `AudioException`: For audio-specific errors, including `ErrorCode`. ### Common Error Codes - `0`: Success - `-1`: Generic error - `-2`: Invalid configuration - `-3`: Device not found - `-4`: Device disconnected - `-5`: Buffer overflow/underrun ### Usage Example ```csharp try { var engine = AudioEngineFactory.Create(config); await engine.InitializeAsync(config); } catch (PlatformNotSupportedException ex) { // Platform not supported Console.WriteLine($"Platform error: {ex.Message}"); } catch (AudioException ex) { // Audio-specific error Console.WriteLine($"Audio error: {ex.Message}"); Console.WriteLine($"Error code: {ex.ErrorCode}"); } ``` ``` -------------------------------- ### Create and Use an Audio Decoder Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Core/README.md Demonstrates how to create a decoder for any supported audio format using the AudioDecoderFactory. Shows how to retrieve stream information and decode audio frame by frame or all at once. ```csharp using Ownaudio.Core; using Ownaudio.Decoders; // Create decoder for any supported format using var decoder = AudioDecoderFactory.Create( "music.mp3", targetSampleRate: 48000, targetChannels: 2 ); // Get stream information var info = decoder.StreamInfo; Console.WriteLine($"Duration: {info.Duration}"); Console.WriteLine($"Sample Rate: {info.SampleRate} Hz"); Console.WriteLine($"Channels: {info.Channels}"); // Decode frame by frame while (true) { var result = decoder.DecodeNextFrame(); if (result.IsEOF) break; // Process result.Frame.Samples (float[]) ProcessAudio(result.Frame.Samples); } // Or decode all at once decoder.TrySeek(TimeSpan.Zero, out _); var allFrames = decoder.DecodeAllFrames(TimeSpan.Zero); ``` -------------------------------- ### Internal MIDI Clock Usage Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Midi/README.md Demonstrates starting, stopping, and changing the BPM of an internal MIDI clock without an output port. ```csharp using OwnAudio.Midi.Clock; using OwnAudio.Midi.IO; // Clock without output port internal use only (e.g. driving a sequencer) using var clock = new MidiClock(bpm: 120.0); clock.Start(); await Task.Delay(4000); // run for 4 seconds clock.Bpm = 140.0; // change tempo while running await Task.Delay(4000); clock.Stop(); ``` -------------------------------- ### AudioEngineFactory Usage Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Core/README.md Demonstrates how to create an audio engine instance using the factory, which automatically detects the platform or accepts a custom configuration. ```csharp // Automatic platform detection var engine = AudioEngineFactory.CreateDefault(); // Or with custom configuration var config = new AudioConfig { SampleRate = 48000, Channels = 2, BufferSize = 512 }; var engine = AudioEngineFactory.Create(config); ``` -------------------------------- ### Initialize Audio Engine with Custom Configuration Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Examples/Ownaudio.Example.Android/README.md Initializes the OwnaudioNet audio engine with specific audio configuration parameters. Ensure the `EnableOutput` is set to true for playback. ```csharp // Initialize engine var config = new AudioConfig { SampleRate = 48000, Channels = 2, BufferSize = 512, EnableOutput = true, EnableInput = false }; await OwnaudioNet.InitializeAsync(config); // Get underlying engine for mixer (bypasses wrapper's pump thread) var engine = OwnaudioNet.Engine!.UnderlyingEngine; engine.Start(); // Create mixer _mixer = new AudioMixer(engine, bufferSizeInFrames: 512); _mixer.MasterVolume = 0.8f; ``` -------------------------------- ### Attaching Sources to the Clock Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-sync.html Demonstrates how to attach `FileSource` instances to the `MasterClock` for drift-free multi-track playback, including setting start offsets and initiating playback. ```APIDOC ## Attaching Sources to the Clock ### Description Demonstrates how to attach `FileSource` instances to the `MasterClock` for drift-free multi-track playback, including setting start offsets and initiating playback. ### Usage 1. **Attach to clock**: Call `AttachToClock()` on each `FileSource` instance *before* calling `Seek()` or `Play()`. 2. **Set offsets (optional)**: Use the `StartOffset` property on `FileSource` to define timeline offsets. 3. **Seek and play**: Call `Seek()` on sources and `SeekTo()` on the `MasterClock`, then call `Play()` on sources. 4. **Add to mixer and start**: Add the sources to the `AudioMixer` and start the mixer. ### Example ```csharp var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine, 1024); var vocals = new FileSource("vocals.wav", targetSampleRate: 48000, targetChannels: 2); var backing = new FileSource("backing.mp3", targetSampleRate: 48000, targetChannels: 2); // 1. Attach to clock (BEFORE Seek and Play) vocals.AttachToClock(mixer.MasterClock); backing.AttachToClock(mixer.MasterClock); // 2. Optional: timeline offsets (backing starts 2.5 seconds into the session) backing.StartOffset = 2.5; // 3. Seek and play mixer.MasterClock.SeekTo(0.0); vocals.Seek(0); backing.Seek(0); vocals.Play(); backing.Play(); mixer.AddSource(vocals); mixer.AddSource(backing); mixer.Start(); ``` ``` -------------------------------- ### Attach FileSource to MasterClock Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-sync.html Shows how to attach FileSource instances to an AudioMixer's MasterClock before playback. Includes setting optional start offsets for sources. ```C# var mixer = new AudioMixer(OwnaudioNet.Engine!.UnderlyingEngine, 1024); var vocals = new FileSource("vocals.wav", targetSampleRate: 48000, targetChannels: 2); var backing = new FileSource("backing.mp3", targetSampleRate: 48000, targetChannels: 2); vocals.AttachToClock(mixer.MasterClock); backing.AttachToClock(mixer.MasterClock); backing.StartOffset = 2.5; mixer.MasterClock.SeekTo(0.0); vocals.Seek(0); backing.Seek(0); vocals.Play(); backing.Play(); mixer.AddSource(vocals); mixer.AddSource(backing); mixer.Start(); ``` -------------------------------- ### Using Compressor Presets Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-effects.html Demonstrates how to set a preset for the CompressorEffect. Available presets include Default, VocalGentle, VocalAggressive, Drums, Bass, MasteringLimiter, and Vintage. ```csharp comp.SetPreset(CompressorPreset.VocalGentle); ``` -------------------------------- ### Dynamic SampleSource Update Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-sources.html Demonstrates creating a dynamic SampleSource for real-time audio generation and submitting new samples. ```C# // 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 synth.Clear(); // flush buffer ``` -------------------------------- ### Receive MIDI Messages Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-midi.html Subscribes to MIDI messages from an input port and processes them. Ensure the callback is marshalled to the UI thread if necessary. The port must be started after subscribing. ```csharp using IMidiInputPort input = MidiPortFactory.OpenInput("USB MIDI Interface"); input.MessageReceived += OnMidiMessage; input.Start(); Console.WriteLine("Listening... press Enter to stop."); Console.ReadLine(); input.Stop(); input.MessageReceived -= OnMidiMessage; void OnMidiMessage(MidiMessage msg) { if (msg.IsNoteOn) Console.WriteLine($"Note ON — pitch={msg.Data1} vel={msg.Data2} ch={msg.Channel}"); else if (msg.IsNoteOff) Console.WriteLine($"Note OFF — pitch={msg.Data1} ch={msg.Channel}"); else if (msg.IsControlChange) Console.WriteLine($"CC #{msg.Data1} = {msg.Data2} ch={msg.Channel}"); else if (msg.IsPitchBend) { int bend = (msg.Data2 << 7) | msg.Data1; // 0..16383, centre = 8192 Console.WriteLine($"Pitch Bend = {bend} ch={msg.Channel}"); } } ``` -------------------------------- ### Starting SmartMasterEffect Room Measurement Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-effects.html Initiates an asynchronous room measurement process for the SmartMasterEffect, which plays a test signal and auto-calibrates the EQ. Use CancelMeasurement() to stop the process. ```csharp // Auto room measurement await smartMaster.StartMeasurementAsync(); // plays test signal, auto-calibrates EQ ``` -------------------------------- ### Receive MIDI Data Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-midi.html Subscribes to MIDI messages received from an input port. The `MessageReceived` event fires on a background thread, and the `Start()` method must be called to begin listening. ```APIDOC ## Receive MIDI Data ### Description Subscribes to MIDI messages received from an input port. The `MessageReceived` event fires on a background thread, and the `Start()` method must be called to begin listening. ### Method ```csharp using IMidiInputPort input = MidiPortFactory.OpenInput("USB MIDI Interface"); input.MessageReceived += OnMidiMessage; input.Start(); Console.WriteLine("Listening... press Enter to stop."); Console.ReadLine(); input.Stop(); input.MessageReceived -= OnMidiMessage; void OnMidiMessage(MidiMessage msg) { if (msg.IsNoteOn) Console.WriteLine($"Note ON — pitch={msg.Data1} vel={msg.Data2} ch={msg.Channel}"); else if (msg.IsNoteOff) Console.WriteLine($"Note OFF — pitch={msg.Data1} ch={msg.Channel}"); else if (msg.IsControlChange) Console.WriteLine($"CC #{msg.Data1} = {msg.Data2} ch={msg.Channel}"); else if (msg.IsPitchBend) { int bend = (msg.Data2 << 7) | msg.Data1; // 0..16383, centre = 8192 Console.WriteLine($"Pitch Bend = {bend} ch={msg.Channel}"); } } ``` ### Parameters - **input**: An `IMidiInputPort` instance. - **OnMidiMessage**: A callback function that handles incoming `MidiMessage` objects. ### Response - `MidiMessage`: Contains details about the received MIDI message, including type, data, and channel. ``` -------------------------------- ### Network Synchronization Server Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Source/README.Mobile.md Starts the OwnAudioSharp.Mobile network synchronization server on a specified port. This device will act as the main source for synchronized audio playback across multiple devices. ```csharp // Network Synchronization - Multi-Device Audio // Perfect for: Party mode, car audio sync, wireless speakers // Server mode (main phone/tablet) await OwnaudioNet.StartNetworkSyncServerAsync(port: 9876); ``` -------------------------------- ### Async Initialization and Stop Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Core/README.md Use these async extensions to avoid blocking UI threads when initializing or stopping the audio engine. ```csharp await engine.InitializeAsync(config); await engine.StopAsync(); ``` -------------------------------- ### Async Initialization and Stop Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Core/README.md Recommended way to initialize and stop the audio engine asynchronously to avoid blocking UI threads. ```APIDOC ## Async Extensions ### Description Use these async methods to perform initialization and stopping operations without blocking the main thread. ### Methods - `InitializeAsync(AudioConfig config)` - `StopAsync()` ### Usage Example ```csharp await engine.InitializeAsync(config); await engine.StopAsync(); ``` ``` -------------------------------- ### Receive MIDI Messages with Event Handler Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Midi/README.md Open an input port, subscribe to the MessageReceived event, and start listening for MIDI data. Remember to marshal callbacks to the UI thread if necessary. ```csharp using OwnAudio.Midi.IO; using IMidiInputPort input = MidiPortFactory.OpenInput("USB MIDI Interface"); input.MessageReceived += OnMidiMessage; input.Start(); Console.WriteLine("Listening... press Enter to stop."); Console.ReadLine(); input.Stop(); input.MessageReceived -= OnMidiMessage; // ─── Handler ─────────────────────────────────────────────── void OnMidiMessage(MidiMessage msg) { if (msg.IsNoteOn) Console.WriteLine($"Note ON — pitch={msg.Data1} velocity={msg.Data2} ch={msg.Channel}"); else if (msg.IsNoteOff) Console.WriteLine($"Note OFF — pitch={msg.Data1} ch={msg.Channel}"); else if (msg.IsControlChange) Console.WriteLine($"CC #{msg.Data1} = {msg.Data2} ch={msg.Channel}"); else if (msg.IsPitchBend) { int bend = (msg.Data2 << 7) | msg.Data1; // 0..16383, centre = 8192 Console.WriteLine($"Pitch Bend = {bend} ch={msg.Channel}"); } } ``` -------------------------------- ### AudioConfig Creation Factories Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-core.html Demonstrates how to create `AudioConfig` objects with different latency and frame settings using factory methods. ```APIDOC ## AudioConfig Creation Factories ### Description Factory methods to create `AudioConfig` instances with predefined settings. ### Configuration Factories ```csharp // 48kHz · stereo · 512 frames (~10.6ms) AudioConfig config = OwnaudioNet.CreateDefaultConfig(); // 48kHz · stereo · 128 frames (~2.7ms) AudioConfig config = OwnaudioNet.CreateLowLatencyConfig(); // 48kHz · stereo · 2048 frames (~42.7ms) AudioConfig config = OwnaudioNet.CreateHighLatencyConfig(); ``` ``` -------------------------------- ### Network Synchronization Client Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudio/Source/README.Mobile.md Starts the OwnAudioSharp.Mobile network synchronization client, allowing devices to connect to a server for synchronized audio playback over WiFi. Auto-discovery is used if the server address is not specified. ```csharp // Client mode (other devices on WiFi) await OwnaudioNet.StartNetworkSyncClientAsync( serverAddress: null, // Auto-discovery on WiFi allowOfflinePlayback: true); // All devices play in perfect sync over WiFi // Automatic reconnection if WiFi drops ``` -------------------------------- ### Manage Multiple Audio Sources in C# Source: https://github.com/modernmube/ownaudiosharp/wiki/OwnAudioSharp-Beginner's-Guide Demonstrates adding audio files, adjusting individual volume, and modifying pitch or tempo for specific sources. ```csharp // Add multiple audio files await sourceManager.AddOutputSource("background.mp3", "Background"); await sourceManager.AddOutputSource("effects.wav", "Effects"); // Set individual volume for sources sourceManager["Background"].Volume = 0.6f; sourceManager["Effects"].Volume = 0.8f; // Pitch and tempo modification sourceManager["Background"].Pitch = -2.0; // 2 semitones down sourceManager["Effects"].Tempo = 10.0; // 10% faster ``` -------------------------------- ### Audio Channel Conversion Source: https://github.com/modernmube/ownaudiosharp/blob/master/OwnAudioEngine/Ownaudio.Core/README.md Provides examples of converting audio between different channel layouts, such as Mono to Stereo, Stereo to Mono (mix down), and downmixing from multi-channel formats like 5.1 to Stereo. ```csharp using Ownaudio.Core.Common; var converter = new AudioChannelConverter(); // Mono → Stereo float[] mono = new float[512]; float[] stereo = converter.MonoToStereo(mono); // Stereo → Mono (mix down) float[] monoMixed = converter.StereoToMono(stereo); // 5.1 → Stereo (downmix) float[] surround = new float[512 * 6]; float[] stereoDownmix = converter.DownmixToStereo(surround, channels: 6); ``` -------------------------------- ### Adding and Managing Audio Sources Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-mixer.html Add audio sources to the mixer. Sources can be added and started immediately, prepared for synchronized startup, or removed individually or all at once. Use GetSources() to retrieve all currently added sources. ```csharp // Add and immediately start mixer.AddSource(source); // Add without starting — launch all at once for tight sync mixer.AddSourcePrepared(vocals); mixer.AddSourcePrepared(backing); mixer.StartPreparedSources(startPosition: 0.0); // atomic start // Remove mixer.RemoveSource(source); // by reference mixer.RemoveSource(sourceGuid); // by ID mixer.ClearSources(); // remove + stop all // Query IAudioSource[] all = mixer.GetSources(); ``` -------------------------------- ### Initialize OwnAudio on Windows Source: https://github.com/modernmube/ownaudiosharp/wiki/Home Requires manual path specification for FFmpeg and Portaudio DLLs. ```csharp // Extract FFmpeg 6 and Portaudio 2 DLL to a folder, then: OwnAudio.Initialize(@"C:\path\to\libraries\"); ``` -------------------------------- ### Mixer Lifecycle Management Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-mixer.html Control the audio processing lifecycle of the mixer. Use Start() to begin, Pause() to freeze, Stop() to halt and clear, Seek() to reposition the master clock, and Dispose() to release resources. ```csharp mixer.Start(); // begin audio processing mixer.Pause(); // freeze mix thread mixer.Stop(); // stop and clear all sources mixer.Seek(double positionInSec); // seek master clock + all attached sources mixer.Dispose(); // release all resources ``` -------------------------------- ### Open MIDI Input and Output Ports Source: https://github.com/modernmube/ownaudiosharp/blob/master/documents/api-midi.html Demonstrates opening MIDI input and output ports by index or by name. Ports are IDisposable and should be managed accordingly. ```csharp // Open by index using IMidiInputPort input = MidiPortFactory.OpenInput(inputs[0]); // Open by name using IMidiOutputPort output = MidiPortFactory.OpenOutput("IAC Driver Bus 1"); ```