### Install Linux Build Dependencies Source: https://github.com/tiagolr/ripplerx/blob/master/README.md Install necessary development libraries for building RipplerX on Linux systems using apt. ```bash sudo apt update sudo apt-get install libx11-dev libfreetype-dev libfontconfig1-dev libasound2-dev libxrandr-dev libxinerama-dev libxcursor-dev ``` -------------------------------- ### MTS-ESP Microtuning Installation Source: https://context7.com/tiagolr/ripplerx/llms.txt Instructions for installing an MTS-ESP master plugin to enable scala/microtuning file integration. RipplerX supports MTS-ESP for resolving note frequencies. ```bash # Install an MTS-ESP master (e.g., MTS-ESP Mini by ODDSound): # https://oddsound.com/mtsespmini.php # Load a .scl tuning file into the master plugin. ``` -------------------------------- ### Build RipplerX on Linux Source: https://context7.com/tiagolr/ripplerx/llms.txt Install necessary system libraries and then use CMake to configure and build RipplerX for Linux. This process generates VST3 and LV2 plugin formats. ```bash # --- Linux (requires system libs) --- sudo apt update sudo apt-get install libx11-dev libfreetype-dev libfontconfig1-dev \ libasound2-dev libxrandr-dev libxinerama-dev libxcursor-dev cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -S . -B ./build cmake --build ./build --config Release # Output: build/RipplerX_artefacts/Release/VST3/RipplerX.vst3 # build/RipplerX_artefacts/Release/LV2/RipplerX.lv2 ``` -------------------------------- ### Clone RipplerX Repository Source: https://github.com/tiagolr/ripplerx/blob/master/README.md Clone the RipplerX repository including its submodules to get started with the build process. ```bash git clone --recurse-submodules https://github.com/tiagolr/ripplerx.git ``` -------------------------------- ### Limiter Initialization (`Limiter`) Source: https://context7.com/tiagolr/ripplerx/llms.txt Initializes the soft brick-wall limiter with specified parameters. Uses RMS detection with a 20:1 ratio. ```cpp // src/dsp/Limiter.h (port of FairlyChildish by Thomas Scott Stillwell) // Soft brick-wall limiter, ratio 20:1, RMS detection Limiter limiter; limiter.init( 44100.0, // sample rate 0.0, // threshold dBFS (default 0 = 0 dBFS ceiling) 70.0, // bias (softens knee, 0=hard, 100=very soft) 100.0, // RMS window µs 0.0 // makeup gain dB ); auto [outL, outR] = limiter.process(left, right); // Attack: 0.2ms, Release: 300ms // Gain reduction applied symmetrically to both channels based on RMS peak. ``` -------------------------------- ### Initialize and Process a Partial in C++ Source: https://context7.com/tiagolr/ripplerx/llms.txt Initializes a Partial object, sets its physical and acoustic properties, updates its frequency based on model parameters, and processes individual audio samples. Static LUT initialization must be called once before creating Partial instances. ```cpp // src/dsp/Partial.h / Partial.cpp // Static LUT initialization (once per session, at prepareToPlay): Partial::initA1LUT(44100.0); // builds the a1 coefficient lookup table Partial p(1); // k=1 (first partial) p.srate = 44100.0; p.decay = 1.0; p.damp = 0.0; p.tone = 0.0; p.hit = 0.26; p.inharm = 0.0001; p.rel = 1.0; // Set frequency from model ratio (220 Hz fundamental, ratio=1 for string k=1): p.update( 220.0, // fundamental frequency 1.0, // modal ratio for this partial (model[k-1]) 64.0, // max ratio in model (model[63]) 0.75, // velocity 1.0, // pitch bend false // isRelease ); // p.f_k is now set to ~220 Hz (with inharmonicity and hit position baked in) // Per-sample processing: double exciter = 0.01; double sample = p.process(exciter); // returns bandpass filtered + decaying output // Apply per-partial gain (for Bell/Marimba2 mesh2faust gains): p.applyGain(0.925507); // Pitch bend (scales f_k and recalculates filter coefficients): p.applyPitchBend(1.05); // shift up ~84 cents // Silence the partial: p.clear(); ``` -------------------------------- ### Stereoizer Initialization (`Comb`) Source: https://context7.com/tiagolr/ripplerx/llms.txt Initializes the Comb filter for the stereoizer effect. A 20ms comb delay creates L/R divergence. ```cpp // src/dsp/Comb.h // Stereoizer: 20ms comb delay creates L/R divergence Comb comb; comb.init(44100.0); // allocates 20ms delay buffer (882 samples at 44.1kHz) // Per-sample processing: auto [left, right] = comb.process(monoInput); // left = input + delayedSample * 0.33 // right = input - delayedSample * 0.33 // Disabled when "stereoizer" parameter is false (outputs mono to both channels). ``` -------------------------------- ### Mallet Generator: Load and Trigger Samples Source: https://context7.com/tiagolr/ripplerx/llms.txt Demonstrates loading built-in or user-provided audio samples into the Sampler and triggering the Mallet with these samples. Includes pitch transposition and filter application. ```cpp // src/dsp/Mallet.h / Mallet.cpp + Sampler.h / Sampler.cpp // --- Sampler: load built-in sample --- Sampler sampler; sampler.loadInternalSample(MalletType::kSample1); // loads click1.flac from binary data sampler.loadInternalSample(MalletType::kSample9); // loads Metal1.flac sampler.setPitch(-2.0); // transpose sample by -2 semitones (sets pitchfactor) ``` ```cpp // --- Sampler: load user audio file --- sampler.loadSample("/path/to/my_stick.wav"); // loads and resamples to internal waveform // sampler.isUserFile == true afterwards ``` ```cpp // --- Mallet: trigger on note-on --- Mallet mallet(sampler); mallet.trigger( MalletType::kImpulse, // type 44100.0, // sample rate 600.0, // impulse filter frequency (Hz) – mallet stiffness 60, // MIDI note (for key-tracking calculation) 0.5 // ktrack: 0=no tracking, 1=full key-track ); ``` ```cpp // For sample-based mallet: mallet.trigger(MalletType::kSample3, 44100.0, 600.0, 60, 0.0); ``` ```cpp // Apply filter to sample mallet (mallet_filter param, -1=LP, +1=HP): mallet.setFilter(0.5); // brightens sample timbre ``` ```cpp // Per-sample processing (returns 0.0 when mallet has finished): double malletOut = mallet.process(); // For kImpulse: outputs a filtered decaying impulse burst. // For sample types: reads waveform with cubic interpolation at playback speed. ``` ```cpp // Stop mallet output: mallet.clear(); ``` -------------------------------- ### Configure and Trigger a Voice in C++ Source: https://context7.com/tiagolr/ripplerx/llms.txt Initializes a Voice, configures its resonators, coupling, and pitch offsets, then triggers a note with specified parameters. This class manages multiple DSP components for sound generation. ```cpp // src/dsp/Voice.h / Voice.cpp // Voice holds: Mallet mallet, Noise noise, Resonator resA, Resonator resB // Constructed with shared Models and Sampler references: Voice voice(*models, *malletSampler); // Convert MIDI note to frequency (with optional MTS-ESP microtuning): double freq = voice.note2freq(60, nullptr); // middle C -> 261.63 Hz double freq_mts = voice.note2freq(60, mtsClientPtr); // MTS-ESP tuned frequency // Configure resonator pitch offsets (coarse in semitones, fine in cents): voice.setPitch(0.0, 0.0, 0.0, 0.0, 1.0); // a_coarse, b_coarse, a_fine, b_fine, pitchBend // Set model ratio for dynamic models (Beam/Membrane/Plate/Djembe): voice.setRatio(2.0, 0.78); // a_ratio, b_ratio // Set serial coupling and split strength: voice.setCoupling(true, 50.0); // couple=serial, split=50 // Update resonator frequencies/velocities after parameter or state change: voice.updateResonators(); // reads current model tables, applies pitch/coupling/gain // Trigger a note (note-on): voice.trigger( 1, // timestamp (monotonic counter for voice stealing priority) 44100.0, // sample rate 60, // MIDI note number 0.75, // velocity (0..1) MalletType::kSample1, // mallet type 600.0, // malletFreq (bandpass center Hz) 0.0, // mallet key-track amount false, // skip_fadeout (true = reuse voice without crossfade) nullptr // MTS-ESP client pointer (null = 12-TET) ); // Release note (note-off): voice.release(2); // timestamp counter // Apply pitch bend to all active partials/waveguides: voice.applyPitchBend(1.02); // Process one sample of oscillator output (used for noise OSC exciter): double oscOut = voice.processOscillators(true); // true = resonator A // Reset all voice DSP state: voice.clear(); ``` -------------------------------- ### Build RipplerX on Linux Source: https://github.com/tiagolr/ripplerx/blob/master/README.md Configure the build with CMake using Unix Makefiles and then build RipplerX in Release mode. ```bash cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -S . -B ./build cmake --build ./build --config Release ``` -------------------------------- ### Standalone Envelope Usage Source: https://context7.com/tiagolr/ripplerx/llms.txt Demonstrates the standalone usage of the Envelope component, including initialization, triggering attack and release phases, and processing sample by sample. ```cpp ---- Envelope standalone usage ---- Envelope env; env.init( 44100.0, // srate 10.0, // attack ms 200.0, // decay ms 0.5, // sustain level 300.0, // release ms 0.4, // attack tension 0.4, // decay tension 0.4 // release tension ); env.attack(1.0); // start envelope, scale=1.0 int state = env.process(); // advance one sample, returns state // env.env holds current envelope value (0..scale) env.release(); // trigger release phase ``` -------------------------------- ### Loading Factory Presets Source: https://context7.com/tiagolr/ripplerx/llms.txt Loads factory presets by their program index. The plugin exposes 28 factory programs loadable by hosts via the standard setCurrentProgram() API. ```cpp // --- Loading a factory preset by program index --- processor.setCurrentProgram(7); // loads "Bells" preset processor.setCurrentProgram(14); // loads "Marimba" preset processor.setCurrentProgram(0); // loads "Init" (default state) // --- Factory program names (index -> name) --- // 0:Init 1:Harpsi 2:Harp 3:Sankyo 4:Tubes 5:Stars 6:DoorBell // 7:Bells 8:Bells2 9:KeyRing 10:Sink 11:Cans 12:Gong 13:Bong // 14:Marimba 15:Fight 16:Tabla 17:Tabla2 18:Strings 19:OldClock // 20:Crystal 21:Ride 22:Ride2 23:Crash 24:Vibes 25:Flute 26:Fifths 27:Kalimba ``` -------------------------------- ### Build RipplerX on macOS Source: https://github.com/tiagolr/ripplerx/blob/master/README.md Configure the build with CMake for both x86_64 and arm64 architectures and then build RipplerX in Release mode. ```bash cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -S . -B ./build cmake --build ./build --config Release ``` -------------------------------- ### Build RipplerX on Windows Source: https://github.com/tiagolr/ripplerx/blob/master/README.md Use CMake with the Visual Studio 17 2022 generator to build RipplerX in Release mode on Windows. ```bash cmake -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE=Release -S . -B ./build ``` -------------------------------- ### Configure Resonator Parameters Source: https://context7.com/tiagolr/ripplerx/llms.txt Set the parameters for a Resonator instance, including sample rate, model type, decay, damping, and spectral tilt. This is typically called from Voice::updateResonators. ```cpp resA.setParams( 44100.0, true, ModalModels::Membrane, 32, 2.0, 0.2, -0.1, 0.26, 1.0, 0.001, 0.3, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0 ); ``` -------------------------------- ### Activate and Process Resonator Source: https://context7.com/tiagolr/ripplerx/llms.txt Activate a resonator before processing audio samples. The process method sums bandpass filters or runs a waveguide delay line and auto-silences after a period of low output. ```cpp resA.activate(); double exciterSignal = 0.05; double out = resA.process(exciterSignal); ``` -------------------------------- ### Configure Beam, Membrane, and Plate Models Source: https://context7.com/tiagolr/ripplerx/llms.txt Recalculate modal ratios for Beam, Membrane, and Plate models. These models are dynamically recalculated when the ratio parameter changes. ```cpp models.recalcBeam(true, 2.0); models.recalcMembrane(false, 1.5); models.recalcPlate(true, 0.78); ``` -------------------------------- ### Preset XML Format Source: https://context7.com/tiagolr/ripplerx/llms.txt Defines the structure of preset XML files, including parameter IDs and their corresponding values. ```xml // --- Preset XML format (resources/presets/*.xml) --- // // // // // // // ... // ``` -------------------------------- ### Noise Generator: Initialization and Processing Source: https://context7.com/tiagolr/ripplerx/llms.txt Initializes the Noise generator with various parameters including filter settings and ADSR envelope characteristics. Shows how to trigger the envelope and process output. ```cpp // src/dsp/Noise.h / Noise.cpp + Envelope.h / Envelope.cpp Noise noise; // Initialize with all parameters (called once per param change): noise.init( 44100.0, // sample rate 1, // filter mode: 0=LP, 1=BP, 2=HP 2000.0, // filter cutoff frequency (Hz) 1.5, // filter Q 10.0, // attack (ms) 200.0, // decay (ms) 0.0, // sustain (0..1) 300.0, // release (ms) 0.0, // vel_freq (velocity -> freq modulation) 0.0, // vel_q 0.4, // att tension (-1..1) 0.4, // dec tension (-1..1) 0.4, // rel tension (-1..1) 0.0, // vel_att 0.0, // vel_dec 0.0, // vel_sus 0.0 // vel_rel ); ``` ```cpp // Trigger envelope on note-on: noise.attack(0.75); // velocity 0..1 (scales envelope and modulates freq/Q) ``` ```cpp // Trigger release on note-off: noise.release(); ``` ```cpp // Per-sample processing: double noiseOut = noise.process(); // Returns filtered noise * envelope value; envelope state transitions automatically. // noise.env.state: 0=Off, 1=Attack, 2=Decay, 4=Sustain, 8=Release ``` ```cpp // Oscillator-based exciter mode (noise_osc > 0): // feeds the resonator's own sine oscillators back through the noise filter double oscInput = 0.05; // from voice.processOscillators() double filteredOsc = noise.processOSC(oscInput); ``` ```cpp // Reset all state: noise.clear(); ``` -------------------------------- ### Audio Processing Loop (`processBlockByType`) Source: https://context7.com/tiagolr/ripplerx/llms.txt The main DSP loop processes MIDI, advances pitch bend, runs each voice, mixes resonators, applies stereoizer and limiter, and writes output samples. Supports both float and double precision buffers. ```cpp // src/PluginProcessor.cpp – processBlockByType // Called by JUCE host every audio block (float or double buffer): // processor.processBlock(AudioBuffer&, MidiBuffer&) // processor.processBlock(AudioBuffer&, MidiBuffer&) // Supports double-precision (overrides supportsDoublePrecisionProcessing() = true) // Signal flow per sample: // // [MIDI queue] --> note-on/off/pitchbend/sustain events // | // [Mallet] --> direct out (mallet_mix) + resonator exciter (mallet_res) // [Audio In] --> resonator exciter (sidechain, while key held) // [Noise] --> direct out (noise_mix) + resonator exciter (noise_res) // | // [Resonator A] <-- exciter signal // [Resonator B] <-- exciter (or A output in serial mode) // | // Parallel: resOut = aOut * (1-ab_mix) + bOut * ab_mix // Serial: resOut = bOut // | // totalOut = directOut + resOut * gain (dB -> linear) // | // [Comb Stereoizer] --> (L, R) = (input + delayed*0.33, input - delayed*0.33) // [Limiter] --> soft brick-wall (FairlyChildish port, ratio=20:1) // | // Output buffer channels 0, 1 // Voice stealing priority (pickVoice): // 1. Reuse voice already playing same note (if reuse_voices=true) // 2. Prefer released voices over pressed voices // 3. Among released: pick oldest release timestamp // 4. Among pressed: pick oldest press timestamp // RMS metering (for UI level meter): float rms = processor.rmsValue.load(std::memory_order_acquire); ``` -------------------------------- ### Build RipplerX on macOS Source: https://context7.com/tiagolr/ripplerx/llms.txt Configure and build RipplerX for macOS using CMake, specifying universal binary architecture support for both x86_64 and arm64. This produces AU, VST3, and LV2 formats. ```bash # --- macOS (Universal Binary) --- cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -S . -B ./build cmake --build ./build --config Release # Output includes AU, VST3, LV2 ``` -------------------------------- ### Saving and Restoring Plugin State Source: https://context7.com/tiagolr/ripplerx/llms.txt Saves the full plugin state, including parameters and optional user sample data, to a memory block. Restores the plugin state from a memory block. ```cpp // --- Saving full plugin state (host calls this for DAW project save) --- juce::MemoryBlock stateData; processor.getStateInformation(stateData); // Serializes all AudioProcessorValueTreeState params + currentProgram index. // If mallet_type==kUserFile, encodes the waveform as base64 in the XML. // --- Restoring plugin state --- processor.setStateInformation(stateData.getData(), stateData.getSize()); // Parses XML, migrates legacy a_cut/b_cut values (Hz -> normalized), loads user sample. ``` -------------------------------- ### RipplerX Plugin Parameter Definitions Source: https://context7.com/tiagolr/ripplerx/llms.txt Lists all parameter IDs, their types (float, bool, Choice), ranges, and default values. These are used to register parameters in the AudioProcessorValueTreeState. ```cpp // Parameter IDs and their ranges (from PluginProcessor.cpp constructor) // --- Mallet Generator --- // "mallet_type" : Choice [Impulse, UserFile, Click1..6, Blip, Blop, Metal1/2, Wood, Strike, Perc1/2] // "mallet_pitch" : float [-24.0 .. 24.0] semitones, default 0 // "mallet_filter" : float [-1.0 .. 1.0] LP/HP filter cutoff, default 0 // "mallet_mix" : float [0.0 .. 1.0] direct output level, default 0 // "mallet_res" : float [0.0 .. 1.0] resonator excite level, default 0.8 // "mallet_stiff" : float [100 .. 5000 Hz] bandpass center freq (skewed), default 600 // "mallet_ktrack" : float [0.0 .. 1.0] key-tracking of stiffness, default 0 // --- Resonator A --- // "a_on" : bool enable resonator A, default true // "a_model" : Choice [String, Beam, Squared, Membrane, Plate, Drumhead, // Marimba, Open Tube, Closed Tube, Marimba2, Bell, Djembe] // "a_partials" : Choice [4, 8, 16, 32, 64, 1, 2], default 32 // "a_decay" : float [0.01 .. 100.0 s] (skewed), default 1.0 // "a_damp" : float [-1.0 .. 1.0] material/damping, default 0 // "a_tone" : float [-1.0 .. 1.0] spectral tilt, default 0 // "a_hit" : float [0.02 .. 0.5] strike position, default 0.26 // "a_rel" : float [0.001 .. 1.0] release damping, default 1.0 // "a_inharm" : float [0.0001 .. 1.0] inharmonicity (skewed), default 0.0001 // "a_ratio" : float [0.1 .. 10.0] modal frequency ratio (skewed), default 1.0 // "a_cut" : float [-1.0 .. 1.0] low/high-cut filter (neg=LP, pos=HP) // "a_radius" : float [0.0 .. 1.0] tube radius (OpenTube/ClosedTube only) // "a_coarse" : float [-48 .. 48] semitones pitch offset // "a_fine" : float [-99 .. 99] cents pitch offset // Resonator B has identical parameters prefixed with "b_" // --- Noise Generator --- // "noise_osc" : float [0.0 .. 1.0] oscillator-based exciter DC // "noise_mix" : float [0.0 .. 1.0] direct noise output level (skewed) // "noise_res" : float [0.0 .. 1.0] noise -> resonator feed level (skewed) // "noise_filter_mode" : Choice [LP, BP, HP] // "noise_filter_freq" : float [20 .. 20000 Hz] (skewed) // "noise_filter_q" : float [0.707 .. 4.0] // "noise_att/dec/sus/rel" : ADSR in ms (1..20000), sustain 0..1 // "noise_att_ten/dec_ten/rel_ten" : tension shape [-1..1] // --- Velocity Modulation (all -1..1, bipolar) --- // "vel_mallet_mix/res/stiff" // "vel_noise_mix/res/freq/att/dec/sus/rel/q" // "vel_a_decay/hit/inharm/damp/tone" // "vel_b_decay/hit/inharm/damp/tone" // --- Global --- // "couple" : Choice [A+B (parallel), A>B (serial)] // "ab_mix" : float [0.0 .. 1.0] A/B blend in parallel mode // "ab_split" : float [0.01 .. 1.0] coupling strength in serial mode (skewed) // "gain" : float [-24 .. 24 dB] resonator output gain // "bend_range" : int [1 .. 24] semitones // "stereoizer" : bool enable comb-filter stereo widener // "reuse_voices": bool retrigger same note on same voice // "fadeout_repeats": bool crossfade on note repeat ``` ```cpp // Reading a parameter value in audio thread: float decayVal = *processor.params.getRawParameterValue("a_decay"); // thread-safe atomic load ``` -------------------------------- ### Build RipplerX without Standalone App Source: https://context7.com/tiagolr/ripplerx/llms.txt Build RipplerX using CMake while explicitly disabling the standalone application. This is useful if only the plugin formats (VST3, LV2, AU) are required. ```bash # --- Build without standalone app --- cmake -DBUILD_STANDALONE=OFF -DCMAKE_BUILD_TYPE=Release -S . -B ./build ``` -------------------------------- ### MTS-ESP Integration for RipplerX Source: https://context7.com/tiagolr/ripplerx/llms.txt Integrates with the MTS-ESP microtuning system. Registration occurs in the constructor and deregistration in the destructor. The note2freq function handles standard tuning or MTS-tuned frequencies. ```cpp // MTS-ESP integration (src/PluginProcessor.cpp): // Registration in constructor: mtsClientPtr = MTS_RegisterClient(); // connects to any running MTS-ESP master // Deregistration in destructor: MTS_DeregisterClient(mtsClientPtr); // Used in Voice::note2freq (src/dsp/Voice.cpp): double Voice::note2freq(int _note, MTSClient* mts) { if (mts == nullptr) return 440.0 * pow(2.0, (_note - 69) / 12.0); // standard 12-TET else return MTS_NoteToFrequency(mts, static_cast(_note), -1); // MTS tuned } // Passing mtsClientPtr=nullptr falls back to standard equal temperament. // Channel -1 means channel-independent tuning. ``` -------------------------------- ### Compute Djembe Model Ratios Source: https://context7.com/tiagolr/ripplerx/llms.txt Compute the Djembe modal frequency ratios for a given fundamental frequency and ratio. The Djembe model is calculated per-voice per-note. ```cpp double freq = 220.0; std::array djembeModel = models.calcDjembe(freq, 1.0); ``` -------------------------------- ### Resonator Class Source: https://context7.com/tiagolr/ripplerx/llms.txt The Resonator class manages sound synthesis components, including partial filters or waveguide delay lines, and an optional filter for frequency shaping. It handles parameter configuration, note updates, and per-sample processing. ```APIDOC ## Resonator Class ### Description Manages sound synthesis for a voice, containing either modal partials or waveguide delay lines, plus optional filtering. Handles configuration, updates, and processing. ### Methods #### `setParams(double sampleRate, bool on, ModalModels model, int numPartials, double decay, double damp, double tone, double hitPos, double releaseDamp, double inharmonicity, double cut, double tubeRadius, double velDecay, double velHit, double velInharm, double velDamp, double velTone)` Configures the resonator parameters. This includes sample rate, model type, number of partials, decay, damping, spectral tilt, hit position, and other model-specific settings. #### `update(double fundamentalFreq, double velocity, bool isRelease, double pitchBendFactor, const std::array& modelFreqs, const std::array& modelGains)` Updates the resonator's frequencies and velocities when a note is triggered or released. Takes fundamental frequency, velocity, release status, pitch bend factor, and pre-computed modal frequencies and gains. #### `activate()` Marks the resonator as active, preparing it for audio processing. #### `process(double exciterSignal)` Performs per-sample processing. Sums bandpass filters for modal models or runs the waveguide delay line for tube models. Auto-silences after a period of low output. #### `applyPitchBend(double factor)` Applies a pitch bend to all active partials by the given factor. #### `clear()` Resets the resonator's internal state, effectively clearing filter history. ### Example Usage ```cpp Resonator resA; std::array modelFreqs = models.aModels[ModalModels::Membrane]; std::array modelGains = models.getGains(ModalModels::Membrane); resA.setParams(44100.0, true, ModalModels::Membrane, 32, 2.0, 0.2, -0.1, 0.26, 1.0, 0.001, 0.3, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0); resA.update(220.0, 0.8, false, 1.0, modelFreqs, modelGains); resA.activate(); double out = resA.process(exciterSignal); resA.applyPitchBend(1.02); resA.clear(); ``` ``` -------------------------------- ### Models Class - Acoustic Models Source: https://context7.com/tiagolr/ripplerx/llms.txt The Models class manages twelve modal frequency ratio tables that define the harmonic structure of resonators. It provides methods to recalculate specific models and compute modal data. ```APIDOC ## Models Class ### Description Manages acoustic modal definitions for resonators. Provides access to various modal models and methods for recalculation and computation. ### Methods #### `recalcBeam(bool resA, double ratio)` Recalculates the Beam modal ratios. `resA` specifies if it's for resonator A. `ratio` adjusts the inharmonic partials. #### `recalcMembrane(bool resA, double ratio)` Recalculates the Membrane modal ratios. `resA` specifies if it's for resonator A. `ratio` adjusts the inharmonic partials. #### `recalcPlate(bool resA, double ratio)` Recalculates the Plate modal ratios. `resA` specifies if it's for resonator A. `ratio` adjusts the inharmonic partials. #### `calcDjembe(double freq, double ratio)` Computes the Djembe modal model for a given fundamental frequency and ratio. Returns an array of modal frequencies. #### `getGains(ModalModels model)` Retrieves the per-partial gain array for models that use mesh2faust gains (e.g., Bell). Returns a uniform 1.0 array for models without special gains. ### Available Models (ModalModels enum) - String - Beam - Squared - Membrane - Plate - Drumhead - Marimba - OpenTube - ClosedTube - Marimba2 - Bell - Djembe ### Example Usage ```cpp Models models; models.recalcBeam(true, 2.0); std::array djembeModel = models.calcDjembe(220.0, 1.0); std::array gains = models.getGains(ModalModels::Bell); ``` ``` -------------------------------- ### Voice Class Source: https://context7.com/tiagolr/ripplerx/llms.txt The Voice class manages two resonators, a mallet, and a noise generator, handling note triggering, release, pitch, coupling, and output composition. The processor can maintain up to 16 Voice instances. ```APIDOC ## Voice Class Usage ### Description Demonstrates the configuration and operation of a `Voice` object for polyphonic synthesis, including note triggering, parameter adjustments, and sample processing. ### Initialization ```cpp // Voice holds: Mallet mallet, Noise noise, Resonator resA, Resonator resB // Constructed with shared Models and Sampler references: Voice voice(*models, *malletSampler); ``` ### Frequency Conversion ```cpp // Convert MIDI note to frequency (with optional MTS-ESP microtuning): double freq = voice.note2freq(60, nullptr); // middle C -> 261.63 Hz double freq_mts = voice.note2freq(60, mtsClientPtr); // MTS-ESP tuned frequency ``` ### Resonator Pitch Configuration ```cpp // Configure resonator pitch offsets (coarse in semitones, fine in cents): voice.setPitch(0.0, 0.0, 0.0, 0.0, 1.0); // a_coarse, b_coarse, a_fine, b_fine, pitchBend ``` ### Model Ratio and Coupling Settings ```cpp // Set model ratio for dynamic models (Beam/Membrane/Plate/Djembe): voice.setRatio(2.0, 0.78); // a_ratio, b_ratio // Set serial coupling and split strength: voice.setCoupling(true, 50.0); // couple=serial, split=50 ``` ### Updating Resonators ```cpp // Update resonator frequencies/velocities after parameter or state change: voice.updateResonators(); // reads current model tables, applies pitch/coupling/gain ``` ### Triggering and Releasing Notes ```cpp // Trigger a note (note-on): voice.trigger( 1, // timestamp (monotonic counter for voice stealing priority) 44100.0, // sample rate 60, // MIDI note number 0.75, // velocity (0..1) MalletType::kSample1, // mallet type 600.0, // malletFreq (bandpass center Hz) 0.0, // mallet key-track amount false, // skip_fadeout (true = reuse voice without crossfade) nullptr // MTS-ESP client pointer (null = 12-TET) ); // Release note (note-off): voice.release(2); // timestamp counter ``` ### Applying Pitch Bend and Processing Oscillators ```cpp // Apply pitch bend to all active partials/waveguides: voice.applyPitchBend(1.02); // Process one sample of oscillator output (used for noise OSC exciter): double oscOut = voice.processOscillators(true); // true = resonator A ``` ### Clearing Voice State ```cpp // Reset all voice DSP state: voice.clear(); ``` ``` -------------------------------- ### Partial Class Source: https://context7.com/tiagolr/ripplerx/llms.txt The Partial class represents a second-order bandpass filter, the fundamental DSP unit for modal synthesis in RipplerX. It handles per-partial decay, damping, tone shaping, and inharmonicity. ```APIDOC ## Partial Class Usage ### Description Demonstrates the initialization and processing of a `Partial` object for modal synthesis. ### Initialization ```cpp // Static LUT initialization (once per session, at prepareToPlay): Partial::initA1LUT(44100.0); // builds the a1 coefficient lookup table Partial p(1); // k=1 (first partial) p.srate = 44100.0; p.decay = 1.0; p.damp = 0.0; p.tone = 0.0; p.hit = 0.26; p.inharm = 0.0001; p.rel = 1.0; ``` ### Update Frequency and Parameters ```cpp // Set frequency from model ratio (220 Hz fundamental, ratio=1 for string k=1): p.update( 220.0, // fundamental frequency 1.0, // modal ratio for this partial (model[k-1]) 64.0, // max ratio in model (model[63]) 0.75, // velocity 1.0, // pitch bend false // isRelease ); // p.f_k is now set to ~220 Hz (with inharmonicity and hit position baked in) ``` ### Per-Sample Processing ```cpp // Per-sample processing: double exciter = 0.01; double sample = p.process(exciter); // returns bandpass filtered + decaying output ``` ### Applying Gain and Pitch Bend ```cpp // Apply per-partial gain (for Bell/Marimba2 mesh2faust gains): p.applyGain(0.925507); // Pitch bend (scales f_k and recalculates filter coefficients): p.applyPitchBend(1.05); // shift up ~84 cents ``` ### Clearing Partial State ```cpp // Silence the partial: p.clear(); ``` ``` -------------------------------- ### Retrieve Mesh2FAUST Model Gains Source: https://context7.com/tiagolr/ripplerx/llms.txt Retrieve the per-partial gain array for models that use mesh2faust gains, such as the Bell model. Returns a uniform 1.0 array for models without special gains. ```cpp std::array gains = models.getGains(ModalModels::Bell); ``` -------------------------------- ### Apply Pitch Bend to Resonator Source: https://context7.com/tiagolr/ripplerx/llms.txt Apply a pitch bend to a resonator mid-note. This function shifts the frequency of all partials by the specified factor. ```cpp resA.applyPitchBend(1.02); ``` -------------------------------- ### Clear Resonator State Source: https://context7.com/tiagolr/ripplerx/llms.txt Reset a resonator to its initial state, clearing all filter and delay line states. ```cpp resA.clear(); ``` -------------------------------- ### Remove macOS Quarantine Attribute Source: https://context7.com/tiagolr/ripplerx/llms.txt Required for unsigned macOS builds to load plugins. Use this command to remove the quarantine extended attribute from plugin files. ```bash # Remove quarantine flag (required for unsigned builds on macOS): sudo xattr -dr com.apple.quarantine /path/to/your/plugins/RipplerX.component sudo xattr -dr com.apple.quarantine /path/to/your/plugins/RipplerX.vst3 sudo xattr -dr com.apple.quarantine /path/to/your/plugins/RipplerX.lv2 # Verify removal: xattr /Library/Audio/Plug-Ins/VST3/RipplerX.vst3 # Should return empty output if quarantine is cleared. ``` -------------------------------- ### Remove macOS Quarantine Flag Source: https://github.com/tiagolr/ripplerx/blob/master/README.md Use these commands to remove the quarantine flag from downloaded plugins on macOS if they are unsigned. This is often necessary for unsigned applications to run. ```bash sudo xattr -dr com.apple.quarantine /path/to/your/plugins/RipplerX.component sudo xattr -dr com.apple.quarantine /path/to/your/plugins/RipplerX.vst3 sudo xattr -dr com.apple.quarantine /path/to/your/plugins/RipplerX.lv3 ``` -------------------------------- ### Update Resonator Frequencies and Velocities Source: https://context7.com/tiagolr/ripplerx/llms.txt Update resonator frequencies and velocities when a note triggers. This function requires the fundamental frequency, velocity, pitch bend factor, and pre-computed model frequencies and gains. ```cpp std::array modelFreqs = models.aModels[ModalModels::Membrane]; std::array modelGains = models.getGains(ModalModels::Membrane); resA.update( 220.0, 0.8, false, 1.0, modelFreqs, modelGains ); ``` -------------------------------- ### Remove Quarantine Flag from RipplerX VST3 Plugin Source: https://github.com/tiagolr/ripplerx/blob/master/doc/macos-readme.txt Execute this command to remove the quarantine flag from the RipplerX VST3 plugin on MacOS. This is required for unsigned builds. ```bash sudo xattr -dr com.apple.quarantine /path/to/your/plugin/RipplerX.vst3 ``` -------------------------------- ### Remove Quarantine Flag from RipplerX LV2 Plugin Source: https://github.com/tiagolr/ripplerx/blob/master/doc/macos-readme.txt Run this command to remove the quarantine flag from the RipplerX LV2 plugin on MacOS. This is a necessary step for unsigned builds. ```bash sudo xattr -dr com.apple.quarantine /path/to/your/plugin/RipplerX.lv2 ``` -------------------------------- ### Remove Quarantine Flag from RipplerX Component Source: https://github.com/tiagolr/ripplerx/blob/master/doc/macos-readme.txt Use this command to remove the quarantine flag from the RipplerX Component plugin on MacOS. This is necessary for unsigned builds. ```bash sudo xattr -dr com.apple.quarantine /path/to/your/plugin/RipplerX.component ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.