### Complete Synthesizer Setup Example Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer-settings.md A comprehensive example demonstrating how to load a SoundFont, configure synthesizer settings, create a synthesizer instance, and render audio. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings}; fn main() -> Result<(), Box> { // Load SoundFont let mut sf2_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf2_file)?); // Configure settings for 48 kHz with moderate polyphony let mut settings = SynthesizerSettings::new(48000); settings.block_size = 128; settings.maximum_polyphony = 96; settings.enable_reverb_and_chorus = true; // Create synthesizer let mut synth = Synthesizer::new(&sound_font, &settings)?; // Use synthesizer synth.note_on(0, 60, 100); // Render audio let sample_count = 48000; // 1 second let mut left = vec![0.0; sample_count]; let mut right = vec![0.0; sample_count]; synth.render(&mut left[..], &mut right[..]); Ok(()) } ``` -------------------------------- ### Complete SoundFont Workflow Example Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/soundfont.md Demonstrates the typical workflow for loading a SoundFont, inspecting its contents, creating a synthesizer, and rendering audio. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings}; fn main() -> Result<(), Box> { // Step 1: Load SoundFont let mut sf2_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf2_file)?); // Step 2: Inspect SoundFont (optional) let info = sound_font.get_info(); println!("Loaded: {}", info.get_bank_name()); println!("Presets: {}", sound_font.get_presets().len()); println!("Instruments: {}", sound_font.get_instruments().len()); println!("Samples: {}", sound_font.get_sample_headers().len()); // Step 3: Create synthesizer let settings = SynthesizerSettings::new(44100); let mut synth = Synthesizer::new(&sound_font, &settings)?; // Step 4: Use synthesizer synth.note_on(0, 60, 100); // Play middle C // Step 5: Render audio let sample_count = 44100; let mut left = vec![0.0; sample_count]; let mut right = vec![0.0; sample_count]; synth.render(&mut left, &mut right); Ok(()) } ``` -------------------------------- ### Programmatic Configuration Example Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/configuration.md Demonstrates that RustySynth requires all configuration to be done programmatically. Environment variables and configuration files are not supported. ```rust // This works let mut settings = SynthesizerSettings::new(44100); // This does NOT work (no env vars) // std::env::var("RUSTYSYNTH_SAMPLE_RATE") // Not supported ``` ```rust // Settings are in-memory only let mut settings = SynthesizerSettings::new(44100); settings.block_size = 256; // NOT loaded from file // settings.load_from_file("config.toml") // Not supported ``` -------------------------------- ### SynthesizerSettings Examples with Different Sample Rates Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer-settings.md Demonstrates creating SynthesizerSettings with various sample rates, from low quality for testing to high resolution for professional audio. ```rust // 44.1 kHz (CD quality) let settings = SynthesizerSettings::new(44100); // 48 kHz (professional audio) let settings = SynthesizerSettings::new(48000); // 96 kHz (high resolution) let settings = SynthesizerSettings::new(96000); // 22.05 kHz (low quality, for testing) let settings = SynthesizerSettings::new(22050); ``` -------------------------------- ### Basic MIDI Playback and Rendering Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md A complete workflow example demonstrating how to load a SoundFont and MIDI file, set up the synthesizer and sequencer, play the MIDI, and render the full audio output. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings, MidiFile, MidiFileSequencer}; fn main() -> Result<(), Box> { // Load SoundFont let mut sf2 = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf2)?); // Load MIDI let mut mid = File::open("song.mid")?; let midi = Arc::new(MidiFile::new(&mut mid)?); // Setup let settings = SynthesizerSettings::new(44100); let synth = Synthesizer::new(&sound_font, &settings)?; let mut sequencer = MidiFileSequencer::new(synth); // Play sequencer.play(&midi, false); // Render full file let sample_count = (settings.sample_rate as f64 * midi.get_length()) as usize; let mut left = vec![0.0; sample_count]; let mut right = vec![0.0; sample_count]; sequencer.render(&mut left[..], &mut right[..]); // Use audio data println!("Rendered {} samples", left.len()); Ok(()) } ``` -------------------------------- ### Synthesize a Simple Chord Source: https://github.com/sinshu/rustysynth/blob/main/rustysynth/README.md Example of loading a SoundFont, creating a synthesizer, and rendering a simple chord for 3 seconds. Ensure 'TimGM6mb.sf2' is available. ```rust // Load the SoundFont. let mut sf2 = File::open("TimGM6mb.sf2").unwrap(); let sound_font = Arc::new(SoundFont::new(&mut sf2).unwrap()); // Create the synthesizer. let settings = SynthesizerSettings::new(44100); let mut synthesizer = Synthesizer::new(&sound_font, &settings).unwrap(); // Play some notes (middle C, E, G). synthesizer.note_on(0, 60, 100); synthesizer.note_on(0, 64, 100); synthesizer.note_on(0, 67, 100); // The output buffer (3 seconds). let sample_count = (3 * settings.sample_rate) as usize; let mut left: Vec = vec![0_f32; sample_count]; let mut right: Vec = vec![0_f32; sample_count]; // Render the waveform. synthesizer.render(&mut left[..], &mut right[..]); ``` -------------------------------- ### Synthesize a MIDI File Source: https://github.com/sinshu/rustysynth/blob/main/rustysynth/README.md Example of loading a SoundFont and a MIDI file, creating a sequencer, and rendering the MIDI file's audio. Ensure 'TimGM6mb.sf2' and 'flourish.mid' are available. ```rust // Load the SoundFont. let mut sf2 = File::open("TimGM6mb.sf2").unwrap(); let sound_font = Arc::new(SoundFont::new(&mut sf2).unwrap()); // Load the MIDI file. let mut mid = File::open("flourish.mid").unwrap(); let midi_file = Arc::new(MidiFile::new(&mut mid).unwrap()); // Create the MIDI file sequencer. let settings = SynthesizerSettings::new(44100); let synthesizer = Synthesizer::new(&sound_font, &settings).unwrap(); let mut sequencer = MidiFileSequencer::new(synthesizer); // Play the MIDI file. sequencer.play(&midi_file, false); // The output buffer. let sample_count = (settings.sample_rate as f64 * midi_file.get_length()) as usize; let mut left: Vec = vec![0_f32; sample_count]; let mut right: Vec = vec![0_f32; sample_count]; // Render the waveform. sequencer.render(&mut left[..], &mut right[..]); ``` -------------------------------- ### Synthesizer Validation Error Examples Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer-settings.md Provides examples of invalid SynthesizerSettings that would cause errors when passed to Synthesizer::new(). These demonstrate out-of-range values for sample rate, block size, and maximum polyphony. ```rust let settings = SynthesizerSettings::new(8000); // Too low let synth = Synthesizer::new(&sound_font, &settings); // Returns Err(SynthesizerError::SampleRateOutOfRange(8000)) ``` ```rust let mut settings = SynthesizerSettings::new(44100); settings.block_size = 2048; // Too high let synth = Synthesizer::new(&sound_font, &settings); // Returns Err(SynthesizerError::BlockSizeOutOfRange(2048)) ``` ```rust let mut settings = SynthesizerSettings::new(44100); settings.maximum_polyphony = 512; // Too high let synth = Synthesizer::new(&sound_font, &settings); // Returns Err(SynthesizerError::MaximumPolyphonyOutOfRange(512)) ``` -------------------------------- ### Start Playing a MIDI File Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Begins playback of a specified MIDI file. Use `play_loop = true` to enable looping. This resets playback and clears previous states. ```rust let midi = Arc::new(MidiFile::new(&mut file)?); // Play once sequencer.play(&midi, false); // Play with looping sequencer.play(&midi, true); ``` -------------------------------- ### Progressive MIDI Rendering with Loop Detection Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Renders a MIDI file in chunks, allowing for real-time processing or streaming. This example also demonstrates playing the MIDI file twice by setting a total duration. ```rust let midi = Arc::new(MidiFile::new(&mut file)?); sequencer.play(&midi, true); let chunk_size = 4410; // 0.1 second chunks let total_time = midi.get_length() * 2.0; // Play twice let total_samples = (settings.sample_rate as f64 * total_time) as usize; for chunk_start in (0..total_samples).step_by(chunk_size) { let chunk_end = (chunk_start + chunk_size).min(total_samples); let chunk_len = chunk_end - chunk_start; let mut left = vec![0.0; chunk_len]; let mut right = vec![0.0; chunk_len]; sequencer.render(&mut left, &mut right); // Process chunk println!("Chunk at {:.2}s", sequencer.get_position()); } ``` -------------------------------- ### MidiFileSequencer::play Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Starts playing a specified MIDI file. Allows for looping playback if desired. ```APIDOC ## MidiFileSequencer::play ### Description Starts playing a MIDI file. The playback can be set to loop or stop at the end. ### Method `play` ### Parameters #### Path Parameters - **midi_file** (`&Arc`) - Required - MIDI file to play - **play_loop** (`bool`) - Required - If true, loop when reaching the end. If false, stop at end. ### Behavior - Resets playback position to the start - Clears all active voices from previous playback - Starts sending MIDI messages on next `render()` call - Loop points defined in MidiFile are respected if `play_loop` is true ### Example ```rust let midi = Arc::new(MidiFile::new(&mut file)?); // Play once sequencer.play(&midi, false); // Play with looping sequencer.play(&midi, true); ``` ``` -------------------------------- ### Start Playing a Note Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Initiates a note on a specified MIDI channel, key, and velocity. A velocity of 0 is treated as a note off event. The synthesizer determines the instrument based on channel state and falls back to the GM sound set if necessary. ```rust synth.note_on(0, 60, 100); // Play E and G (chord) synth.note_on(0, 64, 100); synth.note_on(0, 67, 100); ``` -------------------------------- ### Handling MIDI File Errors: InvalidTempoValue and UnsupportedFormat Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/errors.md This example shows how to handle specific errors during MIDI file loading, including invalid tempo data and unsupported MIDI formats. It provides user-friendly error messages for each case. ```rust match MidiFile::new(&mut file) { Ok(mid) => {}, // Successfully loaded MIDI file Err(MidiFileError::InvalidTempoValue) => { eprintln!("MIDI file has invalid tempo data"); }, Err(MidiFileError::UnsupportedFormat(fmt)) => { eprintln!("MIDI format {} not supported. Use format 0 or 1", fmt); }, _ => {}, // Handle other potential errors } ``` -------------------------------- ### MidiFileSequencer Structure Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/types.md Plays MIDI files using a synthesizer, automatically sending messages at correct times. Created with a Synthesizer instance. Use play() to start playback, render() to generate audio, stop() to stop. ```rust pub struct MidiFileSequencer { // Public API (methods documented separately) } ``` -------------------------------- ### Synthesizer::note_on Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Starts playing a note on the specified channel with a given key and velocity. Velocity 0 acts as a note off. Invalid channels are ignored. The function selects an instrument based on channel state and available presets, allocating a new voice or stealing the oldest if polyphony limits are reached. ```APIDOC ## Synthesizer::note_on ### Description Starts playing a note on the specified channel with a given key and velocity. Velocity 0 acts as a note off. Invalid channels are ignored. The function selects an instrument based on channel state and available presets, allocating a new voice or stealing the oldest if polyphony limits are reached. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method Rust function call ### Endpoint N/A ### Parameters #### Parameters - **channel** (i32) - Range: 0-15 - MIDI channel (0=channel 1, 9=percussion, 15=channel 16) - **key** (i32) - Range: 0-127 - MIDI note number (middle C = 60) - **velocity** (i32) - Range: 0-127 - Note velocity (dynamics). 0 = note off. ### Request Example ```rust // Play middle C on channel 0 with velocity 100 synth.note_on(0, 60, 100); // Play E and G (chord) synth.note_on(0, 64, 100); synth.note_on(0, 67, 100); ``` ### Response #### Success Response None (void function) #### Response Example None ``` -------------------------------- ### MidiFileSequencer::get_position Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Retrieves the current playback position in seconds from the start of the MIDI file. ```APIDOC ## MidiFileSequencer::get_position ### Description Returns the current playback position in seconds. ### Method `get_position` ### Returns `f64` — position from start of MIDI file ### Remarks - Continuous value accounting for playback speed - Useful for displaying playback progress - Resets to loop point when looping occurs ### Example ```rust let pos = sequencer.get_position(); println!("Position: {:.2} seconds", pos); println!("Progress: {:.1}%", pos / midi.get_length() * 100.0); ``` ``` -------------------------------- ### Get Sound Font Reference Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Returns a reference to the SoundFont currently used by the synthesizer. ```rust pub fn get_sound_font(&self) -> &SoundFont ``` -------------------------------- ### Initialize Synthesizer Settings Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/README.md Demonstrates how to create and configure SynthesizerSettings. The sample rate is a required parameter. Optional settings like block size, maximum polyphony, and effects can be adjusted. ```rust let mut settings = SynthesizerSettings::new(44100); // Sample rate required // Optional configuration settings.block_size = 256; // Default: 64 settings.maximum_polyphony = 128; // Default: 64 settings.enable_reverb_and_chorus = true; // Default: true ``` -------------------------------- ### Get Master Volume Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Returns the current master volume level of the synthesizer. The default value is 0.5. ```rust pub fn get_master_volume(&self) -> f32 ``` -------------------------------- ### Complete MidiFile Workflow with MidiFileSequencer Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midifile.md Demonstrates the typical workflow for loading a SoundFont and MIDI file, initializing a synthesizer and sequencer, playing the MIDI, and rendering the audio output. Ensure the SoundFont and MIDI files are accessible. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings, MidiFile, MidiFileSequencer}; fn main() -> Result<(), Box> { // Step 1: Load SoundFont let mut sf2_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf2_file)?); // Step 2: Load MIDI file let mut midi_file = File::open("song.mid")?; let midi = Arc::new(MidiFile::new(&mut midi_file)?); // Step 3: Create synthesizer let settings = SynthesizerSettings::new(44100); let synth = Synthesizer::new(&sound_font, &settings)?; // Step 4: Create sequencer let mut sequencer = MidiFileSequencer::new(synth); // Step 5: Start playback sequencer.play(&midi, false); // false = no looping // Step 6: Render audio let sample_count = (settings.sample_rate as f64 * midi.get_length()) as usize; let mut left = vec![0.0; sample_count]; let mut right = vec![0.0; sample_count]; sequencer.render(&mut left[..], &mut right[..]); Ok(()) } ``` -------------------------------- ### Basic Note Synthesis in Rust Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/INDEX.md Demonstrates how to load a SoundFont, configure a synthesizer, play individual notes, and render audio for a specified duration. Ensure the SoundFont file exists and is accessible. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings}; fn main() -> Result<(), Box> { // Load SoundFont let mut sf_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf_file)?); // Configure synthesizer let settings = SynthesizerSettings::new(44100); let mut synth = Synthesizer::new(&sound_font, &settings)?; // Play notes synth.note_on(0, 60, 100); // C synth.note_on(0, 64, 100); // E synth.note_on(0, 67, 100); // G // Render 3 seconds of audio let sample_count = (3 * 44100) as usize; let mut left = vec![0.0; sample_count]; let mut right = vec![0.0; sample_count]; synth.render(&mut left, &mut right); Ok(()) } ``` -------------------------------- ### MidiFileSequencer::end_of_sequence Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Checks if the playback has reached the end of the MIDI file. Returns true if playback has finished or never started. ```APIDOC ## MidiFileSequencer::end_of_sequence ### Description Returns whether playback has reached the end of the MIDI file. ### Method `end_of_sequence` ### Returns `bool` ### Behavior - Returns true if playback has reached the end - Returns true if `play()` has never been called - Always returns false if looping is enabled (continuously loops) - Useful for detecting completion in non-looping playback ### Example ```rust let midi = Arc::new(MidiFile::new(&mut file)?); sequencer.play(&midi, false); while !sequencer.end_of_sequence() { // Render a block sequencer.render(&mut left[..], &mut right[..]); // Do something with the audio } println!("Playback complete"); ``` ``` -------------------------------- ### MIDI File Playback in Rust Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/INDEX.md Shows how to load a SoundFont and a MIDI file, set up a synthesizer and sequencer, play the MIDI file without looping, and render the entire audio output. Ensure both the SoundFont and MIDI files are accessible. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings, MidiFile, MidiFileSequencer}; fn main() -> Result<(), Box> { // Load files let mut sf_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf_file)?); let mut mid_file = File::open("song.mid")?; let midi = Arc::new(MidiFile::new(&mut mid_file)?); // Setup sequencer let settings = SynthesizerSettings::new(44100); let synth = Synthesizer::new(&sound_font, &settings)?; let mut sequencer = MidiFileSequencer::new(synth); // Play MIDI file sequencer.play(&midi, false); // false = no looping // Render entire file let sample_count = (midi.get_length() * 44100.0) as usize; let mut left = vec![0.0; sample_count]; let mut right = vec![0.0; sample_count]; sequencer.render(&mut left, &mut right); Ok(()) } ``` -------------------------------- ### Get Current Playback Position Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Retrieves the current playback position in seconds. This value is continuous and accounts for playback speed. ```rust let pos = sequencer.get_position(); println!("Position: {:.2} seconds", pos); println!("Progress: {:.1}%", pos / midi.get_length() * 100.0); ``` -------------------------------- ### Load SoundFont and Synthesize Notes Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/README.md Demonstrates how to load a SoundFont file and synthesize audio for a specific MIDI note. Requires a SoundFont file (e.g., TimGM6mb.sf2) and the rustysynth crate. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings}; let mut sf_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf_file)?) ; let settings = SynthesizerSettings::new(44100); let mut synth = Synthesizer::new(&sound_font, &settings)?; synth.note_on(0, 60, 100); // Play middle C let mut left = vec![0.0; 44100]; let mut right = vec![0.0; 44100]; synth.render(&mut left, &mut right); ``` -------------------------------- ### Get Maximum Polyphony Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Returns the maximum number of concurrent voices the synthesizer can produce. This value typically ranges from 8 to 256. ```rust pub fn get_maximum_polyphony(&self) -> usize ``` -------------------------------- ### Get Sample Rate Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Returns the synthesizer's sample rate in Hertz (Hz). Common values include 44100 or 48000. ```rust pub fn get_sample_rate(&self) -> i32 ``` -------------------------------- ### Minimal Configuration for Real-Time Use Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/configuration.md Sets up the synthesizer with default values for block size, polyphony, and effects, using a CD-quality sample rate. Suitable for general real-time audio applications. ```rust let settings = SynthesizerSettings::new(44100); let synth = Synthesizer::new(&sound_font, &settings)?; ``` -------------------------------- ### Get Synthesizer Reference Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Retrieves a read-only reference to the underlying synthesizer. Modifications to the synthesizer should be done via MIDI messages through the sequencer. ```rust pub fn get_synthesizer(&self) -> &Synthesizer ``` ```rust let synth = sequencer.get_synthesizer(); println!("Sample rate: {}", synth.get_sample_rate()); println!("Active voices: estimated from rendering"); ``` -------------------------------- ### SynthesizerSettings::new Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer-settings.md Creates a new SynthesizerSettings instance with default values for most parameters, allowing customization of the sample rate. This is the primary way to initialize synthesizer settings. ```APIDOC ## SynthesizerSettings::new ### Description Creates a new SynthesizerSettings with default values for all parameters except sample rate. ### Signature ```rust pub fn new(sample_rate: i32) -> Self ``` ### Parameters #### Path Parameters - **sample_rate** (i32) - Required - Sample rate in Hz. Valid Range: 16000..=192000 ### Returns `Self` — A new `SynthesizerSettings` instance with defaults applied. ### Defaults Applied - `sample_rate`: As specified by the constructor argument. - `block_size`: 64 samples. - `maximum_polyphony`: 64 voices. - `enable_reverb_and_chorus`: true. ### Example ```rust // 44.1 kHz (CD quality) let settings = SynthesizerSettings::new(44100); // 48 kHz (professional audio) let settings = SynthesizerSettings::new(48000); ``` ``` -------------------------------- ### Get Render Block Size Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Returns the internal block size used for audio rendering. This value typically ranges from 8 to 1024 samples. ```rust pub fn get_block_size(&self) -> usize ``` -------------------------------- ### Synthesizer Initialization with Error Handling Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/configuration.md Demonstrates how to handle potential errors during synthesizer initialization, specifically for out-of-range values for sample rate, block size, and maximum polyphony. ```rust match Synthesizer::new(&sound_font, &settings) { Ok(synth) => { // Use synth }, Err(SynthesizerError::SampleRateOutOfRange(rate)) => { eprintln!("Invalid sample rate: {}", rate); eprintln!("Must be between 16000 and 192000 Hz"); }, Err(SynthesizerError::BlockSizeOutOfRange(size)) => { eprintln!("Invalid block size: {}", size); eprintln!("Must be between 8 and 1024 samples"); }, Err(SynthesizerError::MaximumPolyphonyOutOfRange(poly)) => { eprintln!("Invalid polyphony: {}", poly); eprintln!("Must be between 8 and 256 voices"); }, } ``` -------------------------------- ### Get Playback Speed Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Retrieves the current playback speed multiplier. A value of 1.0 is normal speed. Values other than 0.0 affect playback advance. ```rust let speed = sequencer.get_speed(); println!("Current playback speed: {:.1}x", speed); ``` -------------------------------- ### Real-time MIDI Synthesis with TinyAudio Source: https://github.com/sinshu/rustysynth/blob/main/README.md This snippet demonstrates real-time audio synthesis using the TinyAudio crate. It sets up an audio output device, loads a SoundFont and MIDI file, and continuously renders audio output. ```rust // Setup the audio output. let params = OutputDeviceParameters { channels_count: 2, sample_rate: 44100, channel_sample_count: 4410, }; // Buffer for the audio output. let mut left: Vec = vec![0_f32; params.channel_sample_count]; let mut right: Vec = vec![0_f32; params.channel_sample_count]; // Load the SoundFont. let mut sf2 = File::open("TimGM6mb.sf2").unwrap(); let sound_font = Arc::new(SoundFont::new(&mut sf2).unwrap()); // Load the MIDI file. let mut mid = File::open("flourish.mid").unwrap(); let midi_file = Arc::new(MidiFile::new(&mut mid).unwrap()); // Create the MIDI file sequencer. let settings = SynthesizerSettings::new(params.sample_rate as i32); let synthesizer = Synthesizer::new(&sound_font, &settings).unwrap(); let mut sequencer = MidiFileSequencer::new(synthesizer); // Play the MIDI file. sequencer.play(&midi_file, false); // Start the audio output. let _device = run_output_device(params, { move |data| { sequencer.render(&mut left[..], &mut right[..]); for (i, value) in left.iter().interleave(right.iter()).enumerate() { data[i] = *value; } } }) .unwrap(); // Wait for 10 seconds. std::thread::sleep(std::time::Duration::from_secs(10)); ``` -------------------------------- ### Synthesizer::new Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Initializes a new synthesizer with the specified SoundFont and settings. It requires a SoundFont and synthesis settings, and returns a Result containing the synthesizer instance or a SynthesizerError if settings are out of range. ```APIDOC ## Synthesizer::new ### Description Initializes a new synthesizer with the specified SoundFont and settings. It requires a SoundFont and synthesis settings, and returns a Result containing the synthesizer instance or a SynthesizerError if settings are out of range. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method Rust function call ### Endpoint N/A ### Request Example ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings}; let mut sf_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf_file)?); let settings = SynthesizerSettings::new(44100); let mut synth = Synthesizer::new(&sound_font, &settings)?; ``` ### Response #### Success Response - `Self`: A new instance of the Synthesizer. #### Error Response - `SynthesizerError::SampleRateOutOfRange`: if sample_rate < 16000 or > 192000 - `SynthesizerError::BlockSizeOutOfRange`: if block_size < 8 or > 1024 - `SynthesizerError::MaximumPolyphonyOutOfRange`: if maximum_polyphony < 8 or > 256 ``` -------------------------------- ### Play MIDI File with Sequencer Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/README.md Shows how to load a MIDI file and play it using the MidiFileSequencer. Requires a MIDI file (e.g., song.mid) and the rustysynth crate. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{MidiFile, MidiFileSequencer}; let mut mid_file = File::open("song.mid")?; let midi = Arc::new(MidiFile::new(&mut mid_file)?) ; let mut sequencer = MidiFileSequencer::new(synth); // Assuming 'synth' is already initialized sequencer.play(&midi, false); let sample_count = (midi.get_length() * 44100.0) as usize; let mut left = vec![0.0; sample_count]; let mut right = vec![0.0; sample_count]; sequencer.render(&mut left, &mut right); ``` -------------------------------- ### SynthesizerSettings Constructor Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/configuration.md Creates a new SynthesizerSettings instance with a specified sample rate. This is the primary way to initialize configuration. ```rust pub fn new(sample_rate: i32) -> Self ``` -------------------------------- ### Get SoundFont Metadata Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/soundfont.md Retrieves metadata about the SoundFont file, including version, bank name, author, and creation details. Useful for identifying or displaying information about the loaded SoundFont. ```rust let info = sound_font.get_info(); println!("Bank: {}", info.get_bank_name()); println!("Author: {}", info.get_author()); println!("Version: {}.{}", info.get_version().get_major(), info.get_version().get_minor()); ``` -------------------------------- ### Get MIDI File Duration Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midifile.md Retrieves the total duration of the MIDI file in seconds. This calculation accounts for all tempo changes within the file and is based on the timestamp of the last MIDI message. ```rust let length = midi.get_length(); println!("MIDI file duration: {:.2} seconds", length); println!("Duration: {:.1} minutes", length / 60.0); ``` -------------------------------- ### MidiFile Playback with Looping Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midifile.md Shows how to load a MIDI file with a specific loop point and enable looping during playback. This is useful for continuous music playback in games or applications. Ensure the MIDI file exists and the loop point is valid. ```rust use rustysynth::MidiFileLoopType; // Load MIDI with custom loop point let mut midi_file = File::open("battle_music.mid")?; let midi = Arc::new(MidiFile::new_with_loop_type( &mut midi_file, MidiFileLoopType::LoopPoint(960) // Loop from beat 2 (480 ticks/beat * 2) )?); // Play with looping sequencer.play(&midi, true); // true = loop enabled // Render more than one pass to demonstrate looping let render_samples = (settings.sample_rate as f64 * midi.get_length() * 3.0) as usize; let mut left = vec![0.0; render_samples]; let mut right = vec![0.0; render_samples]; sequencer.render(&mut left[..], &mut right[..]); ``` -------------------------------- ### Check for End of Sequence Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Determines if playback has reached the end of the MIDI file. Returns true if playback has never started or if looping is disabled and the end is reached. Always false if looping is enabled. ```rust let midi = Arc::new(MidiFile::new(&mut file)?); sequencer.play(&midi, false); while !sequencer.end_of_sequence() { // Render a block sequencer.render(&mut left[..], &mut right[..]); // Do something with the audio } println!("Playback complete"); ``` -------------------------------- ### Initialize MidiFileSequencer Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Creates a new MidiFileSequencer instance, taking ownership of the provided Synthesizer. Ensure the SoundFont and Synthesizer are set up before initialization. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings, MidiFileSequencer}; let mut sf2_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf2_file)?); let settings = SynthesizerSettings::new(44100); let synth = Synthesizer::new(&sound_font, &settings)?; let mut sequencer = MidiFileSequencer::new(synth); ``` -------------------------------- ### Get Current MIDI File Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Returns an optional reference to the currently playing MIDI file. This is useful for accessing properties like duration. Returns None if no MIDI file is loaded or if stop() was called. ```rust pub fn get_midi_file(&self) -> Option<&MidiFile> ``` ```rust if let Some(midi) = sequencer.get_midi_file() { let length = midi.get_length(); let pos = sequencer.get_position(); println!("Progress: {:.0}%", pos / length * 100.0); } ``` -------------------------------- ### MidiFileSequencer::new Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Initializes a new MIDI file sequencer with a provided synthesizer instance. This constructor takes ownership of the synthesizer. ```APIDOC ## MidiFileSequencer::new ### Description Initializes a new MIDI file sequencer with a synthesizer instance. The sequencer takes ownership of the synthesizer. ### Method `new` ### Parameters #### Path Parameters - **synthesizer** (`Synthesizer`) - Required - Synthesizer to receive MIDI messages and generate audio ### Returns `Self` — initialized sequencer ### Remarks - Takes ownership of the synthesizer (cannot be extracted later) - Sequencer manages all state including playback position and speed - Default playback speed is 1.0x (normal tempo) ### Example ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings, MidiFileSequencer}; let mut sf2_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf2_file)?); let settings = SynthesizerSettings::new(44100); let synth = Synthesizer::new(&sound_font, &settings)?; let mut sequencer = MidiFileSequencer::new(synth); ``` ``` -------------------------------- ### Initialize Synthesizer Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer.md Creates a new Synthesizer instance. Requires a SoundFont and SynthesizerSettings. Ensure the SoundFont is wrapped in an Arc for thread-safe sharing. ```rust use std::fs::File; use std::sync::Arc; use rustysynth::{SoundFont, Synthesizer, SynthesizerSettings}; let mut sf_file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut sf_file)?); let settings = SynthesizerSettings::new(44100); let mut synth = Synthesizer::new(&sound_font, &settings)?; ``` -------------------------------- ### Get and Set Master Volume Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/configuration.md Retrieve the current master volume of the synthesizer and set it to a new value at runtime. Values are multiplicative, with 1.0 being full volume. Values above 1.0 are supported but may cause clipping. ```rust let synth = Synthesizer::new(&sound_font, &settings)?; // Get current volume let volume = synth.get_master_volume(); // Returns 0.5 (default) // Set volume synth.set_master_volume(0.8); // 80% of maximum synth.set_master_volume(1.0); // Full volume synth.set_master_volume(0.0); // Silent ``` -------------------------------- ### MidiFile::new Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midifile.md Loads a MIDI file from a binary stream with default loop type. It supports MIDI formats 0 and 1, automatically merges tracks, and handles tempo changes. ```APIDOC ## MidiFile::new ### Description Loads a MIDI file from a binary stream with default loop type. It supports MIDI formats 0 and 1, automatically merges tracks, and handles tempo changes. ### Method `new` ### Parameters #### Type Parameters - **R** (`Read`): Any type implementing `std::io::Read` (File, buffer, etc.) #### Parameters - **reader** (`&mut R`): Required - Input stream positioned at the start of MIDI data ### Returns `Result` ### Throws - `MidiFileError::InvalidChunkType`: MIDI file header chunk (MThd) not found - `MidiFileError::InvalidChunkData`: MThd chunk size incorrect - `MidiFileError::UnsupportedFormat`: MIDI format not 0 or 1 - `MidiFileError::InvalidTempoValue`: Set Tempo meta event malformed - `MidiFileError::IoError`: I/O read error ### Remarks - Supports MIDI format 0 (single track) and format 1 (multiple tracks) - Automatically merges multiple tracks into a single timeline - Handles standard tempo changes (Meta Event FF 51) - Ignores non-fatal malformed events after End of Track ### Example ```rust use std::fs::File; use std::sync::Arc; use rustysynth::MidiFile; let mut midi_file = File::open("song.mid")?; let midi = Arc::new(MidiFile::new(&mut midi_file)?); ``` ``` -------------------------------- ### Import RustySynth Modules Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/README.md Lists all public exports from the root rustysynth crate, including core synthesizer, SoundFont, MIDI, and error types. ```rust use rustysynth::{ // Core synthesizer Synthesizer, SynthesizerSettings, // SoundFont SoundFont, SoundFontInfo, SoundFontVersion, Preset, PresetRegion, Instrument, InstrumentRegion, SampleHeader, LoopMode, // MIDI MidiFile, MidiFileSequencer, MidiFileLoopType, // Errors SynthesizerError, SoundFontError, MidiFileError, }; ``` -------------------------------- ### Real-Time Audio Playback Settings Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer-settings.md Use these settings for real-time synthesizer applications requiring minimal latency, suitable for interactive use. ```rust let settings = SynthesizerSettings::new(44100); // block_size: 64 (low latency) // maximum_polyphony: 64 // enable_reverb_and_chorus: true ``` -------------------------------- ### Controlling MIDI Playback Speed Over Time Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Demonstrates how to dynamically change the playback speed of a MIDI file during rendering. The speed is adjusted in a loop, and a second of audio is rendered at each speed. ```rust let midi = Arc::new(MidiFile::new(&mut file)?); sequencer.play(&midi, false); // Play at different speeds for speed in [0.5, 1.0, 1.5, 2.0].iter() { sequencer.set_speed(*speed); let chunk_size = 44100; // 1 second let mut left = vec![0.0; chunk_size]; let mut right = vec![0.0; chunk_size]; sequencer.render(&mut left, &mut right); println!("Played 1 second at speed {:.1}x", speed); } ``` -------------------------------- ### SynthesizerSettings Structure Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/types.md Defines the configuration parameters for initializing a synthesizer. Adjust sample rate, block size, and polyphony to optimize performance and audio quality. ```rust pub struct SynthesizerSettings { pub sample_rate: i32, pub block_size: usize, pub maximum_polyphony: usize, pub enable_reverb_and_chorus: bool, } ``` -------------------------------- ### Tracking MIDI Playback Progress Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/midi-file-sequencer.md Shows how to monitor the playback progress of a MIDI file by repeatedly rendering small chunks and calculating the percentage completion based on the current position and total duration. ```rust let midi = Arc::new(MidiFile::new(&mut file)?); sequencer.play(&midi, false); let total_duration = midi.get_length(); let chunk_size = 44100; while !sequencer.end_of_sequence() { let mut left = vec![0.0; chunk_size]; let mut right = vec![0.0; chunk_size]; sequencer.render(&mut left, &mut right); let progress = sequencer.get_position() / total_duration * 100.0; println!("Progress: {:.1}%", progress); } println!("Playback complete"); ``` -------------------------------- ### SoundFont::new Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/soundfont.md Loads a SoundFont file from a binary stream. It supports SoundFont 2 (SF2) format and performs validation during the loading process. ```APIDOC ## SoundFont::new ### Description Loads a SoundFont file from a binary stream. It supports SoundFont 2 (SF2) format and performs validation during the loading process. ### Method `new` ### Parameters #### Type Parameters - **R** (`Read`) - Any type implementing `std::io::Read` (File, buffer, etc.) #### Parameters - **reader** (`&mut R`) - Required - Input stream positioned at the start of SoundFont data ### Returns `Result` ### Throws - `SoundFontError::RiffChunkNotFound` — file doesn't start with RIFF header - `SoundFontError::InvalidRiffChunkType` — not a SoundFont (sfbk) RIFF file - `SoundFontError::ListChunkNotFound` — INFO chunk missing - `SoundFontError::SampleDataNotFound` — no sample data (smpl) chunk - `SoundFontError::UnsupportedSampleFormat` — SoundFont 3 (not supported) - `SoundFontError::InvalidPresetList` — malformed preset list - `SoundFontError::InvalidInstrumentList` — malformed instrument list - `SoundFontError::PresetNotFound` — no valid presets - `SoundFontError::InstrumentNotFound` — no valid instruments - `SoundFontError::SanityCheckFailed` — validation error on sample regions - `SoundFontError::IoError` — I/O read error ### Remarks - Only supports SoundFont 2 (SF2) format - Creates shared Arc wrapper: `let sound_font = Arc::new(SoundFont::new(&mut reader)?);` - SoundFont validation (sanity check) occurs during load, not after - Performs bounds checking on all sample references ### Example ```rust use std::fs::File; use std::sync::Arc; use rustysynth::SoundFont; let mut file = File::open("TimGM6mb.sf2")?; let sound_font = Arc::new(SoundFont::new(&mut file)?); // Now use sound_font with Synthesizer ``` ``` -------------------------------- ### Offline Rendering Settings Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/api-reference/synthesizer-settings.md Configure settings for offline rendering of MIDI files to disk. Latency is not a concern in this use case. ```rust let mut settings = SynthesizerSettings::new(44100); settings.block_size = 256; settings.maximum_polyphony = 128; // enable_reverb_and_chorus: true ``` -------------------------------- ### Default Synthesizer Settings Source: https://github.com/sinshu/rustysynth/blob/main/_autodocs/configuration.md Shows the default values for `SynthesizerSettings` when initialized with a sample rate, highlighting which parameters use defaults. ```rust // When created like this: let settings = SynthesizerSettings::new(44100); // Resulting configuration: SynthesizerSettings { sample_rate: 44100, block_size: 64, maximum_polyphony: 64, enable_reverb_and_chorus: true, } ```