### 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.