### Setup Audio Playback with Mixer Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/core-concepts.mdx This example demonstrates initializing an audio engine, creating a playback device, and adding SoundPlayer and Oscillator components to the MasterMixer for playback. Ensure the playback device is started and components are set to play. ```csharp using var engine = new MiniAudioEngine(); var format = AudioFormat.DvdHq; using var playbackDevice = engine.InitializePlaybackDevice(null, format); // Create a SoundPlayer and an Oscillator using var dataProvider = new StreamDataProvider(engine, File.OpenRead("audio.wav")); // Auto-detects format var player = new SoundPlayer(engine, format, dataProvider); var oscillator = new Oscillator(engine, format) { Frequency = 220, Type = Oscillator.WaveformType.Square }; // Add both components to the device's MasterMixer playbackDevice.MasterMixer.AddComponent(player); playbackDevice.MasterMixer.AddComponent(oscillator); // Start the device to enable its audio stream playbackDevice.Start(); player.Play(); oscillator.Play(); // ... ``` -------------------------------- ### Setup Project and Install SoundFlow Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-recording.mdx Creates a new console application and installs the SoundFlow package. This is the initial setup for a SoundFlow project. ```bash dotnet new console -o AuthenticatedRecording cd AuthenticatedRecording dotnet add package SoundFlow ``` -------------------------------- ### Create and Install SoundFlow Project Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-recording.mdx Creates a new console application, navigates into it, and adds the SoundFlow package. This is the initial setup for a SoundFlow project. ```bash dotnet new console -o CustomProcessing cd CustomProcessing dotnet add package SoundFlow ``` -------------------------------- ### Setup Looping Playback Project Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-playback.mdx Create a new console application and install the SoundFlow package using the dotnet CLI. This sets up the project for audio playback experiments. ```bash dotnet new console -o LoopingPlayback cd LoopingPlayback dotnet add package SoundFlow ``` -------------------------------- ### Setup Console App and Install SoundFlow Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-modifiers.mdx Creates a new C# console application and adds the SoundFlow NuGet package. ```bash dotnet new console -o Compression cd Compression dotnet add package SoundFlow ``` -------------------------------- ### Create and Install SoundFlow Project Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-modifiers.mdx Creates a new .NET console application and adds the SoundFlow package. This is the initial setup for using SoundFlow. ```bash dotnet new console -o Equalization cd Equalization dotnet add package SoundFlow ``` -------------------------------- ### Create and Install .NET Project Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-analysis.mdx Creates a new console application and installs the SoundFlow NuGet package. Navigate to the project directory after creation. ```bash dotnet new console -o LevelMeterVisualization cd LevelMeterVisualization dotnet add package SoundFlow ``` -------------------------------- ### Setup SoundFlow Project Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-playback.mdx Create a new console application and add the SoundFlow package. ```bash dotnet new console -o PlaybackControl cd PlaybackControl dotnet add package SoundFlow ``` -------------------------------- ### Create and Install SoundFlow Project Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-analysis.mdx Create a new console application and install the SoundFlow package using the dotnet CLI. ```bash dotnet new console -o VoiceActivityDetection cd VoiceActivityDetection dotnet add package SoundFlow ``` -------------------------------- ### Standalone MIDI File Player Example Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/synthesis-sequencer-component.mdx This example shows how to build a MIDI file player using the Sequencer, MidiDataProvider, and Synthesizer. Ensure you have valid paths for your MIDI and SoundFont files. ```csharp using SoundFlow.Abstracts; using SoundFlow.Backends.MiniAudio; using SoundFlow.Metadata.Midi; using SoundFlow.Providers; using SoundFlow.Structs; using SoundFlow.Synthesis; using SoundFlow.Synthesis.Banks; using System.IO; using System.Linq; public static class Program { public static void Main(string[] args) { Console.WriteLine("Standalone Sequencer MIDI Player Example"); // User Configuration // Replace with the path to your MIDI file and a SoundFont file. var midiFilePath = @"C:\path\to\your\song.mid"; var soundFontPath = @"C:\path\to\your\soundfont.sf2"; if (!File.Exists(midiFilePath) || !File.Exists(soundFontPath)) { Console.WriteLine("Error: Please provide valid paths for the MIDI and SoundFont files."); return; } // 1. Standard engine and device setup using var engine = new MiniAudioEngine(); var format = AudioFormat.DvdHq; using var device = engine.InitializePlaybackDevice(null, format); // 2. Load MIDI data and an instrument bank var midiFile = MidiFileParser.Parse(File.OpenRead(midiFilePath)); var midiDataProvider = new MidiDataProvider(midiFile); // The SoundFontBank is IDisposable and must be managed. using var instrumentBank = new SoundFontBank(soundFontPath, format); Console.WriteLine($"Loaded MIDI file: {Path.GetFileName(midiFilePath)}, Duration: {midiDataProvider.Duration:mm\\:ss}"); Console.WriteLine($"Loaded SoundFont with {instrumentBank.AvailablePresets.Count} presets."); // 3. Create the Synthesizer (the sound source) var synthesizer = new Synthesizer(engine, format, instrumentBank); // 4. Create the Sequencer (the MIDI event dispatcher) var sequencer = new Sequencer(engine, format, midiDataProvider, synthesizer) { IsLooping = true // Let's loop the playback }; // 5. Build the audio graph // The Synthesizer generates the audio. device.MasterMixer.AddComponent(synthesizer); // The Sequencer is also added so its GenerateAudio method is called for timing, even though it doesn't output audio itself. device.MasterMixer.AddComponent(sequencer); // 6. Start playback device.Start(); sequencer.Play(); // This enables the sequencer's processing. Console.WriteLine("\nPlayback started. Press any key to stop."); Console.ReadKey(); // 7. Clean up sequencer.Stop(); device.Stop(); synthesizer.Dispose(); } } ``` -------------------------------- ### Create Console Project and Install SoundFlow Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-analysis.mdx Commands to create a new .NET console application and add the SoundFlow NuGet package to it. This is the initial setup for using SoundFlow features. ```bash dotnet new console -o WaveformVisualization cd WaveformVisualization dotnet add package SoundFlow ``` -------------------------------- ### Example SqlFingerprintStore Implementation Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/security-acoustic-fingerprinting.mdx A pseudocode example demonstrating how to implement `IFingerprintStore` using a SQL database. Emphasizes the need for efficient bulk inserts and fast hash lookups. ```csharp public class SqlFingerprintStore : IFingerprintStore { private readonly string _connectionString; public async Task InsertAsync(AudioFingerprint fingerprint) { // Bulk insert is highly recommended here! // INSERT INTO Fingerprints (Hash, TrackId, TimeOffset) VALUES ... foreach(var h in fingerprint.Hashes) { await _db.ExecuteAsync( "INSERT INTO Fingerprints VALUES (@Hash, @TrackId, @TimeOffset)", new { h.Hash, fingerprint.TrackId, h.TimeOffset }); } } public async Task> QueryHashAsync(uint hash) { // SELECT TrackId, TimeOffset FROM Fingerprints WHERE Hash = @Hash // This query runs thousands of times per identification, so it MUST be fast. return await _db.QueryAsync( "SELECT TrackId, TimeOffset FROM Fingerprints WHERE Hash = @Hash", new { Hash = hash }); } } ``` -------------------------------- ### Start Recording with Different Modes Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/editing-recording-and-sequencing.mdx Demonstrates starting recording using both the default Normal mode and the OverdubMerge mode. The Normal mode creates a new segment, while OverdubMerge attempts to merge into an existing segment or creates a new one if none exists. ```csharp var transportTime = composition.Renderer.CurrentTime; // Example 1: Standard recording mode, which creates a new segment. composition.Recorder.StartRecording(transportTime, RecordingMode.Normal); // Let playback and recording continue... Console.WriteLine("Recording in Normal mode. Press Enter to stop."); Console.ReadLine(); await composition.Recorder.StopRecordingAsync(); Console.WriteLine("Recording stopped. New segment created."); // Example 2: Overdub recording mode, which merges into an existing segment. // Find a segment at the current transport time to overdub into. MidiSegment targetSegment = myMidiTrack.Segments.FirstOrDefault(s => s.Contains(transportTime)); // StartRecording will create a new segment if none is found, even in OverdubMerge mode. composition.Recorder.StartRecording(transportTime, RecordingMode.OverdubMerge, targetSegment); // Let playback and recording continue... Console.WriteLine("Recording in OverdubMerge mode. Press Enter to stop."); Console.ReadLine(); await composition.Recorder.StopRecordingAsync(); Console.WriteLine("Recording stopped. Notes merged into segment."); ``` -------------------------------- ### Start SoundFlow Docs Development Server Source: https://github.com/lsxprime/soundflow-docs/blob/master/README.md Start the Vite development server to view the SoundFlow documentation website locally. This command enables hot-reloading for code and content changes. ```bash npm run dev ``` -------------------------------- ### Install Dependencies for SoundFlow Docs Source: https://github.com/lsxprime/soundflow-docs/blob/master/README.md Install all necessary Node.js dependencies for the SoundFlow documentation website using npm. This command should be run after cloning the repository. ```bash npm install ``` -------------------------------- ### Create Console App and Install SoundFlow Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-recording.mdx Creates a new .NET console application and adds the SoundFlow package to it. ```bash dotnet new console -o MicrophonePlayback cd MicrophonePlayback dotnet add package SoundFlow ``` -------------------------------- ### StreamDataProvider Usage Example Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/core-concepts.mdx Demonstrates initializing and using StreamDataProvider with an MP3 file. The provider can auto-detect audio format from the stream. Requires an MiniAudioEngine instance. ```csharp using var engine = new MiniAudioEngine(); // The provider can now auto-detect the format from the stream for most common formats. // No AudioFormat object is needed here, but you can still pass it as a hint. using var dataProvider = new StreamDataProvider(engine, File.OpenRead("audio.mp3")); // You can inspect the discovered format Console.WriteLine($"Detected Sample Rate: {dataProvider.SampleRate}"); Console.WriteLine($"Detected Title: {dataProvider.FormatInfo?.Tags?.Title}"); // Use the provider with a player. You can create an AudioFormat from the provider's info. var format = new AudioFormat { SampleRate = dataProvider.SampleRate, Channels = dataProvider.FormatInfo.ChannelCount }; var player = new SoundPlayer(engine, format, dataProvider); // ... ``` -------------------------------- ### Create New Console App and Install SoundFlow Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-modifiers.mdx Commands to create a new .NET console application and add the SoundFlow package. Navigate to the project directory after creation. ```bash dotnet new console -o ChorusDelay cd ChorusDelay dotnet add package SoundFlow ``` -------------------------------- ### Sequencer Integration with SoundFontBank Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/synthesis-soundfont-support.mdx Shows how to replace the default `BasicInstrumentBank` with a `SoundFontBank` in the `Sequencer` example to create a MIDI file player using SoundFonts. ```csharp // In the Sequencer example... // using var instrumentBank = new BasicInstrumentBank(format); // BECOMES: using var instrumentBank = new SoundFontBank("path/to/your/soundfont.sf2", format); // The rest of the code remains the same. var synthesizer = new Synthesizer(engine, format, instrumentBank); var sequencer = new Sequencer(engine, format, midiDataProvider, synthesizer); // ... ``` -------------------------------- ### Initialize Audio Playback and Visualization Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-analysis.mdx Sets up the audio engine, selects the default playback device, and initializes audio playback with a specified format. It then configures a SoundPlayer, LevelMeterAnalyzer, and WaveformVisualizer, connecting them for playback and visualization. Remember to replace 'path/to/your/audiofile.wav' with the actual path to your audio file. ```csharp namespace WaveformVisualization; internal static class Program { private static void Main(string[] args) { // Standard setup using var audioEngine = new MiniAudioEngine(); var defaultDevice = audioEngine.PlaybackDevices.FirstOrDefault(d => d.IsDefault); if(defaultDevice.Id == IntPtr.Zero) return; var audioFormat = new AudioFormat { Format = SampleFormat.F32, SampleRate = 48000, Channels = 2 }; using var device = audioEngine.InitializePlaybackDevice(defaultDevice, audioFormat); using var dataProvider = new StreamDataProvider(audioEngine, audioFormat, File.OpenRead("path/to/your/audiofile.wav")); using var player = new SoundPlayer(audioEngine, audioFormat, dataProvider); // Create a LevelMeterAnalyzer or any analyzer you want. var levelMeterAnalyzer = new LevelMeterAnalyzer(); // Create a WaveformVisualizer. var waveformVisualizer = new WaveformVisualizer(); // Add the player to the master mixer. Mixer.Master.AddComponent(player); // Subscribe to the VisualizationUpdated event to trigger a redraw. waveformVisualizer.VisualizationUpdated += (sender, e) => { DrawWaveform(waveformVisualizer.Waveform); }; // Connect the player's output to the level meter analyzer's input. player.AddAnalyzer(levelMeterAnalyzer); // Add the player to the master mixer. Mixer.Master.AddComponent(player); // Start playback. player.Play(); // Start a timer to update the visualization. var timer = new System.Timers.Timer(1000 / 60); // Update at approximately 60 FPS timer.Elapsed += (sender, e) => { waveformVisualizer.Render(new ConsoleVisualizationContext()); // ConsoleVisualizationContext is just a placeholder }; timer.Start(); device.MasterMixer.AddComponent(player); device.Start(); player.Play(); Console.WriteLine("Playing audio and displaying waveform... Press any key to stop."); Console.ReadKey(); device.Stop(); waveformVisualizer.Dispose(); } // Helper method to draw a simple console-based waveform. private static void DrawWaveform(IReadOnlyList waveform) { Console.Clear(); int consoleWidth = Console.WindowWidth; int consoleHeight = Console.WindowHeight; if (waveform.Count == 0) return; for (int i = 0; i < consoleWidth; i++) { int waveformIndex = (int)(i * (waveform.Count / (float)consoleWidth)); waveformIndex = Math.Clamp(waveformIndex, 0, waveform.Count - 1); float sampleValue = waveform[waveformIndex]; int consoleY = (int)((sampleValue + 1) * 0.5 * (consoleHeight - 1)); consoleY = Math.Clamp(consoleY, 0, consoleHeight - 1); if (i < consoleWidth && (consoleHeight - consoleY - 1) < consoleHeight) { Console.SetCursorPosition(i, consoleHeight - consoleY - 1); Console.Write("*"); } } Console.SetCursorPosition(0, consoleHeight - 1); } } ``` ``` -------------------------------- ### Add Modifier and Playback Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/advanced-topics.mdx Example of adding a distortion modifier to a player and starting playback. ```csharp // 5. Add the modifier to a SoundComponent (like a player). player.AddModifier(distortion); // 6. Add the player to the device's master mixer. device.MasterMixer.AddComponent(player); // 7. Start the device and play. device.Start(); player.Play(); // ... ``` -------------------------------- ### Load and Play SoundFont Example Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/synthesis-soundfont-support.mdx Demonstrates the full workflow of loading an SF2 file, listing its presets, selecting an instrument, and playing it using the Synthesizer. Ensure the SoundFont path is correctly set. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Midi.Structs; using SoundFlow.Structs; using SoundFlow.Synthesis; using SoundFlow.Synthesis.Banks; using System; using System.IO; using System.Linq; using System.Threading; public static class Program { public static void Main() { Console.WriteLine("SoundFont Bank Example"); // Replace with the path to a SoundFont file on your system. var soundFontPath = @"C:\path\to\your\soundfont.sf2"; if (!File.Exists(soundFontPath)) { Console.WriteLine($"Error: SoundFont file not found at '{soundFontPath}'."); return; } // 1. Standard engine and device setup using var engine = new MiniAudioEngine(); var format = AudioFormat.DvdHq; using var device = engine.InitializePlaybackDevice(null, format); // 2. Load the .sf2 file into a SoundFontBank. This can take a moment. Console.WriteLine($"Loading SoundFont: {Path.GetFileName(soundFontPath)}..."); using var soundFontBank = new SoundFontBank(soundFontPath, format); Console.WriteLine("SoundFont loaded successfully."); // 3. List the available presets. Console.WriteLine("\n--- Available Presets ---"); foreach (var preset in soundFontBank.AvailablePresets) { Console.WriteLine($"Bank: {preset.Bank}, Program: {preset.Program}, Name: {preset.Name}"); } // 4. Create a Synthesizer and give it the loaded bank. var synthesizer = new Synthesizer(engine, format, soundFontBank); // 5. Add the synthesizer to the mixer and start the device. device.MasterMixer.AddComponent(synthesizer); device.Start(); // Select an instrument and play it // Let's choose the first available preset. var presetToPlay = soundFontBank.AvailablePresets.FirstOrDefault(); if (presetToPlay == null) { Console.WriteLine("No presets found in the SoundFont."); return; } Console.WriteLine($"\nSelecting preset: '{presetToPlay.Name}' (Bank: {presetToPlay.Bank}, Program: {presetToPlay.Program})"); int channel = 1; // MIDI Channel 1 // Bank Select MSB (CC 0) synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0xB0 + channel - 1), 0, (byte)(presetToPlay.Bank / 128))); // Bank Select LSB (CC 32) synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0xB0 + channel - 1), 32, (byte)(presetToPlay.Bank % 128))); // Program Change synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0xC0 + channel - 1), (byte)presetToPlay.Program, 0)); Console.WriteLine("Playing a C Major chord..."); synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0x90 + channel - 1), 60, 100)); // C4 synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0x90 + channel - 1), 64, 100)); // E4 synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0x90 + channel - 1), 67, 100)); // G4 Thread.Sleep(3000); // Hold the chord synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0x80 + channel - 1), 60, 0)); synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0x80 + channel - 1), 64, 0)); synthesizer.ProcessMidiMessage(new MidiMessage((byte)(0x80 + channel - 1), 67, 0)); Console.WriteLine("Playback finished."); Thread.Sleep(1000); // 6. Clean up device.Stop(); synthesizer.Dispose(); } } ``` -------------------------------- ### Initialize Synthesizer and Play a Note Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/synthesis-synthesizer-component.mdx Demonstrates the basic workflow of setting up the audio engine, synthesizer, and playing a middle C note. Requires initialization of the audio engine and playback device before creating the synthesizer. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Midi.Structs; using SoundFlow.Structs; using SoundFlow.Synthesis; using SoundFlow.Synthesis.Banks; using System.Linq; using System.Threading; public static class Program { public static void Main() { Console.WriteLine("Synthesizer Basic Usage Example"); // 1. Initialize the audio engine and a playback device. using var engine = new MiniAudioEngine(); var format = AudioFormat.DvdHq; using var device = engine.InitializePlaybackDevice(null, format); // Use default device // 2. Create an Instrument Bank. // The BasicInstrumentBank provides a few simple, hardcoded synth sounds. var instrumentBank = new BasicInstrumentBank(format); // 3. Create the Synthesizer instance. // It requires the engine, format, and an instrument bank. var synthesizer = new Synthesizer(engine, format, instrumentBank); // 4. Add the synthesizer to the device's master mixer to make it audible. device.MasterMixer.AddComponent(synthesizer); // 5. Start the audio device's processing thread. device.Start(); Console.WriteLine($"Audio device '{device.Info?.Name}' started."); // Playing Notes Programmatically // A Note On message: Command 0x90, Channel 1, Note 60 (Middle C), Velocity 127 var noteOn = new MidiMessage(0x90, 60, 127); // A Note Off message for the same note var noteOff = new MidiMessage(0x80, 60, 0); Console.WriteLine("\nPlaying Middle C (Note 60)..."); synthesizer.ProcessMidiMessage(noteOn); Thread.Sleep(1000); // Hold the note for 1 second synthesizer.ProcessMidiMessage(noteOff); Console.WriteLine("Note Off sent."); Thread.Sleep(1000); // Wait for the release tail to fade out // Switching Instruments // A Program Change message for Channel 1, Program 80 (Lead Synth in BasicInstrumentBank) var programChange = new MidiMessage(0xC0, 80, 0); Console.WriteLine("\nSwitching to Program 80 (Lead Synth)..."); synthesizer.ProcessMidiMessage(programChange); Console.WriteLine("Playing a higher note (A4, Note 69)..."); synthesizer.ProcessMidiMessage(new MidiMessage(0x90, 69, 110)); Thread.Sleep(1000); synthesizer.ProcessMidiMessage(new MidiMessage(0x80, 69, 0)); Console.WriteLine("Note Off sent."); Thread.Sleep(1000); // 6. Clean up. device.Stop(); synthesizer.Dispose(); } } ``` -------------------------------- ### Clone SoundFlow Docs Repository Source: https://github.com/lsxprime/soundflow-docs/blob/master/README.md Clone the repository to your local machine to start contributing or running the documentation website locally. Ensure you have Git installed. ```bash git clone https://github.com/LSXPrime/soundflow-docs.git cd soundflow-docs ``` -------------------------------- ### Punch-In/Out Recording Setup Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/editing-recording-and-sequencing.mdx Configures the recorder to automatically start and stop recording within a specified time window using PunchInTime and PunchOutTime. The recorder waits until PunchInTime to begin capturing MIDI events and stops at PunchOutTime. ```csharp // Example: Correct a section from measure 5 to measure 9. var measure5Time = TimeSpan.FromSeconds(10); var measure9Time = TimeSpan.FromSeconds(20); // Set up the punch-in and punch-out times. composition.Recorder.PunchInTime = measure5Time; composition.Recorder.PunchOutTime = measure9Time; // Start the recorder in "waiting" mode before playback reaches the punch-in point. // For example, start playback from measure 1 (TimeSpan.Zero). composition.Recorder.StartRecording(TimeSpan.Zero); // ... start playback of the composition's renderer from the beginning ... // The recorder will automatically handle the start and stop of MIDI capture // precisely between 10 and 20 seconds. ``` -------------------------------- ### Playing Multiple Instruments with Multitimbrality Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/synthesis-multi-timbrality-in-depth.mdx This example demonstrates controlling two different instruments on two separate MIDI channels using a single SoundFlow Synthesizer. It covers standard setup, creating a synthesizer with an instrument bank, and sending MIDI messages for note on/off and program changes to specific channels. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Midi.Structs; using SoundFlow.Structs; using SoundFlow.Synthesis; using SoundFlow.Synthesis.Banks; using System; using System.Linq; using System.Threading; public static class Program { public static void Main() { Console.WriteLine("Synthesizer Multitimbrality Example"); // 1. Standard setup using var engine = new MiniAudioEngine(); var format = AudioFormat.DvdHq; using var device = engine.InitializePlaybackDevice(null, format); // 2. Create a synthesizer with a bank that has multiple instruments. var instrumentBank = new BasicInstrumentBank(format); var synthesizer = new Synthesizer(engine, format, instrumentBank); device.MasterMixer.AddComponent(synthesizer); device.Start(); Console.WriteLine("Playing a C Major chord on Channel 1 (Default Piano)..."); // Status 0x90 = Note On, Channel 1 synthesizer.ProcessMidiMessage(new MidiMessage(0x90, 60, 100)); // C4 synthesizer.ProcessMidiMessage(new MidiMessage(0x90, 64, 100)); // E4 synthesizer.ProcessMidiMessage(new MidiMessage(0x90, 67, 100)); // G4 Thread.Sleep(1500); Console.WriteLine("\nNow, playing a melody on Channel 2 (Music Box)..."); // Control Channel 2 // Status 0xC1 = Program Change, Channel 2. Program 10 is the Music Box in BasicInstrumentBank. synthesizer.ProcessMidiMessage(new MidiMessage(0xC1, 10, 0)); // Status 0x91 = Note On, Channel 2 synthesizer.ProcessMidiMessage(new MidiMessage(0x91, 72, 120)); // C5 Thread.Sleep(500); synthesizer.ProcessMidiMessage(new MidiMessage(0x91, 74, 120)); // D5 Thread.Sleep(500); synthesizer.ProcessMidiMessage(new MidiMessage(0x91, 76, 120)); // E5 Thread.Sleep(500); Console.WriteLine("\nReleasing all notes..."); // Status 0x80 = Note Off, Channel 1 synthesizer.ProcessMidiMessage(new MidiMessage(0x80, 60, 0)); synthesizer.ProcessMidiMessage(new MidiMessage(0x80, 64, 0)); synthesizer.ProcessMidiMessage(new MidiMessage(0x80, 67, 0)); // Status 0x81 = Note Off, Channel 2 synthesizer.ProcessMidiMessage(new MidiMessage(0x81, 72, 0)); synthesizer.ProcessMidiMessage(new MidiMessage(0x81, 74, 0)); synthesizer.ProcessMidiMessage(new MidiMessage(0x81, 76, 0)); Thread.Sleep(2000); // Wait for release tails to fade device.Stop(); synthesizer.Dispose(); } } ``` -------------------------------- ### Initialize and Use Synthesizer with MIDI Source: https://context7.com/lsxprime/soundflow-docs/llms.txt Demonstrates how to initialize an audio engine, create a synthesizer, and send MIDI messages for note on/off and program changes. Ensure the MiniAudioEngine and necessary SoundFlow components are set up. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Midi.Structs; using SoundFlow.Structs; using SoundFlow.Synthesis; using SoundFlow.Synthesis.Banks; using System; using System.Threading; using var engine = new MiniAudioEngine(); var format = AudioFormat.DvdHq; using var device = engine.InitializePlaybackDevice(null, format); // Create instrument bank and synthesizer var instrumentBank = new BasicInstrumentBank(format); var synthesizer = new Synthesizer(engine, format, instrumentBank); device.MasterMixer.AddComponent(synthesizer); device.Start(); // Play Middle C (Note 60) var noteOn = new MidiMessage(0x90, 60, 127); // Note On, Channel 1 var noteOff = new MidiMessage(0x80, 60, 0); // Note Off synthesizer.ProcessMidiMessage(noteOn); Thread.Sleep(1000); synthesizer.ProcessMidiMessage(noteOff); // Switch to different instrument (Program Change) var programChange = new MidiMessage(0xC0, 80, 0); // Program 80 synthesizer.ProcessMidiMessage(programChange); // Play A4 (Note 69) synthesizer.ProcessMidiMessage(new MidiMessage(0x90, 69, 110)); Thread.Sleep(1000); synthesizer.ProcessMidiMessage(new MidiMessage(0x80, 69, 0)); device.Stop(); synthesizer.Dispose(); ``` -------------------------------- ### Start Playback Device Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/getting-started.mdx Explicitly start the device to begin its audio processing thread. ```csharp playbackDevice.Start() ``` -------------------------------- ### Initialize and Play Audio with SoundFlow Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/advanced-topics.mdx This snippet demonstrates the basic setup for initializing the audio engine, configuring a playback device, and playing an audio file using SoundFlow components. ```csharp using System.Linq; // 1. Create an instance of an audio engine. using var engine = new MiniAudioEngine(); // 2. Define the desired audio format. var audioFormat = new AudioFormat { Format = SampleFormat.F32, SampleRate = 48000, Channels = 2 }; // 3. Get the default playback device info from the engine. var deviceInfo = engine.PlaybackDevices.FirstOrDefault(d => d.IsDefault); // 4. Initialize a playback device. using var device = engine.InitializePlaybackDevice(deviceInfo, audioFormat); // 5. Create the player and your custom component, passing the engine and format. using var dataProvider = new StreamDataProvider(engine, audioFormat, File.OpenRead("audio.wav")); var player = new SoundPlayer(engine, audioFormat, dataProvider); var gainComponent = new CustomGainComponent(engine, audioFormat) { Gain = 0.5f }; // 6. Connect the player as an input to the gain component. gainComponent.ConnectInput(player); // 7. Add the final component in the chain to the device's master mixer. device.MasterMixer.AddComponent(gainComponent); // 8. Start the device and play the sound. device.Start(); player.Play(); // ... ``` -------------------------------- ### Install SoundFlow Package Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-analysis.mdx Installs the SoundFlow package into a new console application. Ensure you are in the project directory. ```bash dotnet new console -o SpectrumAnalysis cd SpectrumAnalysis dotnet add package SoundFlow ``` -------------------------------- ### Install SoundFlow Package Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-recording.mdx Install the SoundFlow package into your .NET console application using the dotnet CLI. ```bash dotnet new console -o BasicRecording cd BasicRecording dotnet add package SoundFlow ``` -------------------------------- ### Initialize Audio Engine and Playback Device Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-modifiers.mdx Sets up the MiniAudio engine and finds the default audio playback device. Exits if no default device is found. ```csharp using var audioEngine = new MiniAudioEngine(); var defaultDevice = audioEngine.PlaybackDevices.FirstOrDefault(d => d.IsDefault); if (defaultDevice.Id == IntPtr.Zero) { Console.WriteLine("No default playback device found."); return; } var audioFormat = new AudioFormat { ``` -------------------------------- ### Install SoundFlow Package Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-modifiers.mdx Installs the SoundFlow package into a new .NET console application. Ensure you are in the project directory before running. ```bash dotnet new console -o VocalExtractor cd VocalExtractor dotnet add package SoundFlow ``` -------------------------------- ### Install SoundFlow Package Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-modifiers.mdx Install the SoundFlow package for your C# console application. This is a prerequisite for using SoundFlow's audio functionalities. ```bash dotnet new console -o ReverbEffect cd ReverbEffect dotnet add package SoundFlow ``` -------------------------------- ### Initialize Data Provider and Sound Player Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/getting-started.mdx Components like ISoundDataProvider and SoundPlayer now require the engine and format contexts in their constructors. ```csharp using var dataProvider = ... var player = new SoundPlayer(...) ``` -------------------------------- ### Install SoundFlow via NuGet Package Manager Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/getting-started.mdx Use this command in the Package Manager Console to install the SoundFlow library and its dependencies into your project. ```bash Install-Package SoundFlow ``` -------------------------------- ### Initialize Audio Playback with Chorus and Delay Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/tutorials-modifiers.mdx Sets up an audio playback device and initializes a SoundPlayer. Replace `path/to/your/audiofile.wav` with the actual audio file path. ```csharp using SoundFlow.Abstracts; using SoundFlow.Abstracts.Devices; using SoundFlow.Backends.MiniAudio; using SoundFlow.Components; using SoundFlow.Enums; using SoundFlow.Modifiers; using SoundFlow.Providers; using SoundFlow.Structs; using System; using System.IO; using System.Linq; namespace ChorusDelay; internal static class Program { private static void Main(string[] args) { // Initialize the audio engine. using var audioEngine = new MiniAudioEngine(); var defaultDevice = audioEngine.PlaybackDevices.FirstOrDefault(d => d.IsDefault); if (defaultDevice.Id == IntPtr.Zero) { Console.WriteLine("No default playback device found."); return; } var audioFormat = new AudioFormat { Format = SampleFormat.F32, SampleRate = 48000, Channels = 2 }; using var device = audioEngine.InitializePlaybackDevice(defaultDevice, audioFormat); // Create a SoundPlayer and load an audio file. using var dataProvider = new StreamDataProvider(audioEngine, audioFormat, File.OpenRead("path/to/your/audiofile.wav")); using var player = new SoundPlayer(audioEngine, audioFormat, dataProvider); ``` -------------------------------- ### Full MIDI Recording Example in C# Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/editing-recording-and-sequencing.mdx This C# code demonstrates a complete MIDI recording workflow. It requires setting up the audio engine, MIDI backend, composition, and handling user input for recording control. Ensure a MIDI input device is connected. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Components; using SoundFlow.Editing; using SoundFlow.Midi.PortMidi; using SoundFlow.Midi.Routing.Nodes; using SoundFlow.Structs; using SoundFlow.Synthesis; using SoundFlow.Synthesis.Banks; using MidiTrack = SoundFlow.Editing.MidiTrack; namespace ConsoleApp1; public static class Program { /// /// The main entry point for the application. /// public static void Main() { Console.WriteLine("SoundFlow v1.4.0 - Full MIDI Recording Example"); Console.WriteLine("==============================================\n"); // 1. Setup Engine & MIDI Backend using var engine = new MiniAudioEngine(); engine.UseMidiBackend(new PortMidiBackend()); engine.UpdateAudioDevicesInfo(); engine.UpdateMidiDevicesInfo(); // 2. Prepare Composition & Instrument var format = AudioFormat.DvdHq; var composition = new Composition(engine, format, "Live Recording Session"); var midiTrack = new MidiTrack("My Performance"); composition.Editor.AddMidiTrack(midiTrack); var synthesizer = new Synthesizer(engine, format, new BasicInstrumentBank(format)) { Name = "Session Synth" }; composition.MidiTargets.Add(new MidiTargetNode(synthesizer)); midiTrack.Target = composition.MidiTargets.First(); // 3. Setup MIDI Input var inputDeviceInfo = engine.MidiInputDevices.FirstOrDefault(); if (inputDeviceInfo.Name == null) { Console.WriteLine("ERROR: No MIDI input device found. Please connect a device and restart."); Console.ReadKey(); return; } var inputNode = engine.MidiManager.GetOrCreateInputNode(inputDeviceInfo); var initializedDevice = inputNode.Device; // 4. Arm the Track composition.Recorder.ArmTrackForRecording(midiTrack, initializedDevice); Console.WriteLine($"Track '{midiTrack.Name}' is armed for recording.\n"); // 5. Setup Live MIDI Monitoring var monitorRoute = engine.MidiManager.CreateRoute(inputDeviceInfo, synthesizer); Console.WriteLine($"Live monitoring enabled: '{inputDeviceInfo.Name}' -> '{synthesizer.Name}'"); // 6. Initialize Audio Playback using var device = engine.InitializePlaybackDevice(null, format); Console.WriteLine($"Audio output initialized on: {device.Info?.Name}\n"); // 7. Add Components to MasterMixer device.MasterMixer.AddComponent(synthesizer); var compositionPlayer = new SoundPlayer(engine, format, composition.Renderer); device.MasterMixer.AddComponent(compositionPlayer); // 8. Interactive Session var isRecording = false; try { device.Start(); while (true) { Console.WriteLine("---"); Console.WriteLine("1. Start Recording (Normal)"); Console.WriteLine("2. Stop Recording"); Console.WriteLine("3. Playback Composition"); Console.WriteLine("4. Exit"); Console.Write("Select an option: "); var key = Console.ReadKey(true).Key; Console.WriteLine(key.ToString().Last()); switch (key) { case ConsoleKey.D1: if (isRecording) { Console.WriteLine("Already recording."); break; } Console.WriteLine("\n*** RECORDING STARTED ***\nPlay on your MIDI device. Press '2' to stop."); isRecording = true; compositionPlayer.Seek(0); composition.Recorder.StartRecording(composition.Renderer.CurrentTime, RecordingMode.Normal); compositionPlayer.Play(); break; case ConsoleKey.D2: if (!isRecording) { Console.WriteLine("Not currently recording."); break; } Console.WriteLine("\n*** RECORDING STOPPED ***"); isRecording = false; composition.Recorder.StopRecording(); compositionPlayer.Stop(); var recordedSegment = midiTrack.Segments.LastOrDefault(); if (recordedSegment != null) { Console.WriteLine($"A new MIDI segment '{recordedSegment.Name}' was created with a duration of {recordedSegment.SourceDuration:ss\\.fff}s."); } break; case ConsoleKey.D3: if (isRecording) ``` -------------------------------- ### Enable PortMidi Backend in Code Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/midi-io-and-device-management.mdx Initialize the audio engine and enable the PortMidi backend by calling the UsePortMidi() extension method. This must be done once during application startup. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Midi.PortMidi; // Import the extension method // 1. Initialize the audio engine. using var engine = new MiniAudioEngine(); // 2. Enable the PortMidi backend. // This activates all MIDI functionality in the engine. engine.UsePortMidi(); Console.WriteLine("MIDI backend enabled."); ``` -------------------------------- ### SoundFlow Engine Usage Example Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/advanced-topics.mdx Example of how to integrate custom components and backends into the SoundFlow engine. This snippet shows the necessary usings for engine and component integration. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Components; using SoundFlow.Providers; using SoundFlow.Structs; ``` -------------------------------- ### Synthesizer Basic Usage Example Source: https://github.com/lsxprime/soundflow-docs/blob/master/content/1.4.0/synthesis-synthesizer-component.mdx Demonstrates the fundamental steps to initialize the audio engine, create a synthesizer with a basic instrument bank, and play synthesized notes programmatically using MIDI messages. ```APIDOC ## Getting Started: Playing Your First Synthesized Note This example demonstrates the most basic usage: creating a synthesizer, giving it a simple instrument bank, and playing a note programmatically. ```csharp using SoundFlow.Backends.MiniAudio; using SoundFlow.Midi.Structs; using SoundFlow.Structs; using SoundFlow.Synthesis; using SoundFlow.Synthesis.Banks; using System.Linq; using System.Threading; public static class Program { public static void Main() { Console.WriteLine("Synthesizer Basic Usage Example"); // 1. Initialize the audio engine and a playback device. using var engine = new MiniAudioEngine(); var format = AudioFormat.DvdHq; using var device = engine.InitializePlaybackDevice(null, format); // Use default device // 2. Create an Instrument Bank. // The BasicInstrumentBank provides a few simple, hardcoded synth sounds. var instrumentBank = new BasicInstrumentBank(format); // 3. Create the Synthesizer instance. // It requires the engine, format, and an instrument bank. var synthesizer = new Synthesizer(engine, format, instrumentBank); // 4. Add the synthesizer to the device's master mixer to make it audible. device.MasterMixer.AddComponent(synthesizer); // 5. Start the audio device's processing thread. device.Start(); Console.WriteLine($"Audio device '{device.Info?.Name}' started."); // Playing Notes Programmatically // A Note On message: Command 0x90, Channel 1, Note 60 (Middle C), Velocity 127 var noteOn = new MidiMessage(0x90, 60, 127); // A Note Off message for the same note var noteOff = new MidiMessage(0x80, 60, 0); Console.WriteLine("\nPlaying Middle C (Note 60)..."); synthesizer.ProcessMidiMessage(noteOn); Thread.Sleep(1000); // Hold the note for 1 second synthesizer.ProcessMidiMessage(noteOff); Console.WriteLine("Note Off sent."); Thread.Sleep(1000); // Wait for the release tail to fade out // Switching Instruments // A Program Change message for Channel 1, Program 80 (Lead Synth in BasicInstrumentBank) var programChange = new MidiMessage(0xC0, 80, 0); Console.WriteLine("\nSwitching to Program 80 (Lead Synth)..."); synthesizer.ProcessMidiMessage(programChange); Console.WriteLine("Playing a higher note (A4, Note 69)..."); synthesizer.ProcessMidiMessage(new MidiMessage(0x90, 69, 110)); Thread.Sleep(1000); synthesizer.ProcessMidiMessage(new MidiMessage(0x80, 69, 0)); Console.WriteLine("Note Off sent."); Thread.Sleep(1000); // 6. Clean up. device.Stop(); synthesizer.Dispose(); } } ``` ```