Coupling Operators
🎭 Mask
Section titled “🎭 Mask”sim_add_mask_operator(ctx, input, mask, out, opts)
Gate a field by a mask with optional feathering. Implements selective region processing, apertures, conditional field operations, and smooth spatial transitions.
Method Signature
Section titled “Method Signature”sim_add_mask_operator(ctx, input, mask, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”Hard threshold (feather = 0):
where is the mask value and is the threshold.
Soft feathering (feather > 0):
where is the feather half-width and smoothstep provides a smooth transition:
Inverted mode:
Swaps the active and inactive regions (mask < threshold becomes active).
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
mode | enum | "apply" | apply, invert | Mask application mode |
threshold | double | 0.5 | unbounded | Mask threshold for gating |
feather | double | 0.0 | ≥0 | Soft transition half-width |
fill_value | double | 0.0 | unbounded | Value when mask is inactive (real part) |
fill_value_im | double | 0.0 | unbounded | Imaginary fill value for complex output |
accumulate | boolean | false | — | Add to output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated writes by dt |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Operates elementwise; no boundary handling required
- Input and mask fields must have compatible dimensions
- Complex fields: fill value uses both
fill_valueandfill_value_im
Stability & Convergence
Section titled “Stability & Convergence”- Unconditionally stable (bounded output for bounded input)
- Hard threshold (feather = 0) produces discontinuous results
- Soft feathering (feather > 0) provides C¹ continuous transitions
- Larger feather values produce smoother but wider transition zones
Performance Notes
Section titled “Performance Notes”- Hard threshold: simple comparison, very fast
- Soft feathering: requires smoothstep computation per sample
- Inverted mode has no additional cost (threshold comparison is reversed)
Examples
Section titled “Examples”-- Hard threshold maskooc.sim_add_mask_operator(ctx, input, mask, out, { threshold = 0.5})
-- Soft feathered mask (smooth transitions)ooc.sim_add_mask_operator(ctx, input, mask, out, { threshold = 0.5, feather = 0.1})
-- Wide feather for gradient blendingooc.sim_add_mask_operator(ctx, input, mask, out, { threshold = 0.5, feather = 0.25})
-- Inverted mask (keep where mask < threshold)ooc.sim_add_mask_operator(ctx, input, mask, out, { mode = "invert", threshold = 0.25})
-- Custom fill value for inactive regionsooc.sim_add_mask_operator(ctx, input, mask, out, { threshold = 0.5, fill_value = -1.0})
-- Complex field with complex fill valueooc.sim_add_mask_operator(ctx, complex_field, mask, out, { threshold = 0.3, feather = 0.05, fill_value = 0.0, fill_value_im = 0.0})
-- Circular aperture (using radial mask)-- First create radial coordinate mask, then applyooc.sim_add_coordinate_operator(ctx, radial_mask, { mode = "coord", coord_mode = "radial", coord_center_x = 128, coord_center_y = 128, normalize = "unit"})ooc.sim_add_mask_operator(ctx, input, radial_mask, apertured, { mode = "invert", -- keep center, block edges threshold = 0.3, feather = 0.05})🥄 Mixer
Section titled “🥄 Mixer”sim_add_mixer_operator(ctx, lhs, rhs, out, opts)
Combine two input fields using various mixing formulas including linear blending, modulation, nonlinear operations, and feedback integration. Essential for signal processing, synthesis, and field coupling.
Method Signature
Section titled “Method Signature”sim_add_mixer_operator(ctx, lhs, rhs, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”Let and be the gain-scaled inputs.
Linear Modes:
- linear:
- sum:
- difference:
- abs_diff:
- average:
- crossfade: where is
mix
Multiplicative Modes:
- multiply:
- power: (complex power for complex fields)
Extrema:
- max:
- min:
Modulation Modes:
- am (amplitude modulation):
- fm (frequency modulation):
- pm (phase modulation):
- ring_mod: (removes DC component)
Feedback Mode:
Leaky integrator with configurable splitting:
Split modes affect the order of decay and injection:
- none: Combined update
- lie: Decay, then inject
- strang: Half decay, inject, half decay (symmetric)
Parameters
Section titled “Parameters”Core Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
mode | enum | "linear" | see below | Mixing formula |
lhs_gain | double | 1.0 | unbounded | Gain applied to left input |
rhs_gain | double | 1.0 | unbounded | Gain applied to right input |
bias | double | 0.0 | unbounded | Constant offset added after mixing |
accumulate | boolean | false | — | Add to output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated writes by dt |
Mode options: linear, multiply, crossfade, sum, power, am, fm, pm, ring_mod, max, min, average, difference, abs_diff, feedback
Crossfade Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
mix | double | 0.5 | [0, 1] | Crossfade weight (0 = lhs, 1 = rhs) |
Feedback Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
feedback_epsilon | double | 0.1 | [0, 1] | Feedback/injection strength |
feedback_epsilon_mode | enum | "input" | see below | How epsilon is applied |
feedback_split | enum | "none" | see below | Operator splitting strategy |
Epsilon mode options: input (scales injection), feedback (scales decay)
Split options: none, lie, strang
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Operates elementwise; no boundary handling required
- Both input fields must have compatible dimensions
- Feedback mode maintains internal state; initialize carefully
Stability & Convergence
Section titled “Stability & Convergence”- Linear modes: Unconditionally stable
- Multiply/power: Can produce large values; consider clamping
- FM/PM: Unitary for real modulation; preserves magnitude
- Feedback: Stable for ; larger values respond faster but may oscillate
- Strang splitting: Second-order accurate; preferred for feedback with varying inputs
Performance Notes
Section titled “Performance Notes”- Linear modes are highly optimized
- Modulation modes (fm, pm) require transcendental functions
- Power mode with complex fields uses cpow (expensive)
- Feedback requires internal state storage
Examples
Section titled “Examples”-- Linear combination with gainsooc.sim_add_mixer_operator(ctx, a, b, out, { mode = "linear", lhs_gain = 0.7, rhs_gain = 0.3, bias = 0.0})
-- Simple sumooc.sim_add_mixer_operator(ctx, a, b, sum, { mode = "sum"})
-- Element-wise productooc.sim_add_mixer_operator(ctx, a, b, product, { mode = "multiply"})
-- Crossfade (35% toward rhs)ooc.sim_add_mixer_operator(ctx, a, b, blended, { mode = "crossfade", lhs_gain = 1.0, rhs_gain = 1.0, mix = 0.35})
-- FM synthesisooc.sim_add_mixer_operator(ctx, carrier, modulator, out, { mode = "fm", lhs_gain = 1.0, rhs_gain = 0.2 -- modulation depth})
-- Amplitude modulationooc.sim_add_mixer_operator(ctx, carrier, envelope, am_signal, { mode = "am", lhs_gain = 1.0, rhs_gain = 0.8})
-- Phase modulationooc.sim_add_mixer_operator(ctx, signal, phase_mod, pm_signal, { mode = "pm", rhs_gain = 0.5 -- radians})
-- Ring modulationooc.sim_add_mixer_operator(ctx, a, b, ring, { mode = "ring_mod"})
-- Element-wise maximumooc.sim_add_mixer_operator(ctx, a, b, max_field, { mode = "max"})
-- Signed differenceooc.sim_add_mixer_operator(ctx, a, b, diff, { mode = "difference"})
-- Absolute differenceooc.sim_add_mixer_operator(ctx, a, b, abs_diff, { mode = "abs_diff"})
-- Power (a^b)ooc.sim_add_mixer_operator(ctx, base, exponent, power, { mode = "power"})
-- Feedback with input injection modeooc.sim_add_mixer_operator(ctx, input, state, state, { mode = "feedback", feedback_epsilon = 0.2, feedback_epsilon_mode = "input"})
-- Feedback with Strang splitting (higher accuracy)ooc.sim_add_mixer_operator(ctx, input, state, state, { mode = "feedback", feedback_epsilon = 0.1, feedback_epsilon_mode = "feedback", feedback_split = "strang"})
-- Accumulate average into running sumooc.sim_add_mixer_operator(ctx, a, b, running_avg, { mode = "average", accumulate = true, scale_by_dt = true})