Measurement Operators
〰️ Phase Feature
Section titled “〰️ Phase Feature”sim_add_phase_feature_operator(ctx, src, dst, opts)
Extract phase-aligned magnitude features from complex fields. Produces a complex output that preserves the phase direction while applying magnitude transformations. Useful for creating phase-preserving envelopes, spectral features, and instantaneous amplitude analysis.
Method Signature
Section titled “Method Signature”sim_add_phase_feature_operator(ctx, input, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”For a complex input :
where:
- is the magnitude
- is the phase
- is the
exponentparameter
Special cases:
exponent = 0: Output has unit magnitude with original phase:exponent = 1: Output equals input (identity for above-threshold samples)exponent = 2: Output has squared magnitude:
Parameters
Section titled “Parameters”| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
threshold | double | 0.0 | ≥0 | Magnitude gate; samples below are zeroed |
exponent | double | 0.0 | ≥0 | Power applied to magnitude (0 = unit magnitude) |
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
- Complex fields preserve phase; real fields treated as having zero phase
- Output is complex when input is complex
Stability & Convergence
Section titled “Stability & Convergence”- Unconditionally stable (bounded output for bounded input)
- Threshold acts as a noise gate; useful for suppressing low-amplitude noise
exponent > 1amplifies magnitude differences;exponent < 1compresses them
Performance Notes
Section titled “Performance Notes”- Requires magnitude calculation (square root) and phase extraction (atan2)
- Phase preservation requires sin/cos for reconstruction
threshold = 0skips the comparison;exponent = 1skips power computation
Examples
Section titled “Examples”-- Extract unit-magnitude phase directionooc.sim_add_phase_feature_operator(ctx, signal, phase_dir, { exponent = 0.0})
-- Magnitude gate with thresholdooc.sim_add_phase_feature_operator(ctx, signal, gated, { threshold = 0.1, exponent = 1.0})
-- Squared magnitude feature (energy-like)ooc.sim_add_phase_feature_operator(ctx, signal, energy, { exponent = 2.0})
-- Accumulate phase-aligned energy over timeooc.sim_add_phase_feature_operator(ctx, signal, accumulated, { exponent = 2.0, accumulate = true, scale_by_dt = true})
-- Square root compression (reduce dynamic range)ooc.sim_add_phase_feature_operator(ctx, signal, compressed, { exponent = 0.5, threshold = 0.01})🧩 Minimal Convolution
Section titled “🧩 Minimal Convolution”sim_add_minimal_convolution_operator(ctx, src, dst, opts)
Apply small odd-length convolution kernels for 1D or 2D fields. Supports axis-aligned, separable, and full 2D convolution modes with configurable boundary conditions. Efficient for gradient operators, smoothing, edge detection, and custom filters.
Method Signature
Section titled “Method Signature”sim_add_minimal_convolution_operator(ctx, input, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”1D Convolution (axis mode):
where is the kernel, is the kernel radius, is kernel_length, and is stride.
Separable Convolution:
Two-pass 1D convolution: first along X, then along Y (or vice versa):
where denotes 1D convolution along the specified axis.
2D Convolution (kernel_2d mode):
where is the 2D kernel in row-major order.
Parameters
Section titled “Parameters”Core Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
mode | enum | "axis" | see below | Convolution mode |
axis | enum | "x" | x, y | Axis for 1D convolution |
boundary | enum | "periodic" | see below | Boundary handling policy |
stride | integer | 1 | [1, 16] | Stride between sampled elements |
accumulate | boolean | false | — | Add to output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated writes by dt |
Mode options: axis, separable, kernel_2d
Boundary options: periodic, neumann, dirichlet, reflective
1D Kernel Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
kernel_length | integer | 3 | 3, 5, 7, 9 | Number of kernel coefficients |
kernel | double[] | — | — | Kernel coefficients (comma-separated string or array) |
2D Kernel Parameters (kernel_2d mode):
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
kernel_rows | integer | 3 | 3, 5, 7, 9 | Kernel height |
kernel_cols | integer | 3 | 3, 5, 7, 9 | Kernel width |
kernel_2d | double[] | — | — | Flattened row-major 2D kernel |
Deprecated:
| Parameter | Type | Default | Description |
|---|---|---|---|
wrap | boolean | true | Use boundary = "periodic" instead |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Periodic: Wraps around domain edges
- Neumann: Zero-derivative at boundaries (mirrors edge values)
- Dirichlet: Zero values outside domain
- Reflective: Mirror-reflects values at boundaries
Stability & Convergence
Section titled “Stability & Convergence”- Convolution is unconditionally stable for bounded kernels
- Kernel normalization affects output scale:
- Smoothing kernels should sum to 1.0
- Derivative kernels should sum to 0.0
stride > 1produces downsampled output; ensure output field is sized accordingly
Performance Notes
Section titled “Performance Notes”- Fixed kernel sizes (3, 5, 7, 9) enable compile-time optimization
- Separable convolution is O(2N·L) vs O(N·L²) for full 2D
- Kernel coefficients can be passed as Lua array or comma-separated string
- Memory access pattern is cache-friendly for axis-aligned convolution
Runtime Configuration
Section titled “Runtime Configuration”Read current configuration:
local cfg = ooc.sim_minimal_convolution_config(ctx, op_index)-- Returns: { kernel_length, stride, accumulate, wrap, boundary, kernel }Update configuration:
ooc.sim_minimal_convolution_update(ctx, op_index, { kernel_length = 5, kernel = {1, 4, 6, 4, 1}, stride = 2, boundary = "reflective"})Examples
Section titled “Examples”-- 1D gradient kernel (central difference)ooc.sim_add_minimal_convolution_operator(ctx, u, du_dx, { mode = "axis", axis = "x", kernel_length = 3, kernel = {-0.5, 0.0, 0.5}})
-- 1D gradient with 5-tap stencilooc.sim_add_minimal_convolution_operator(ctx, u, du_dx, { mode = "axis", axis = "x", kernel_length = 5, kernel = "-1,0,0,0,1" -- string format})
-- Separable Gaussian smoothingooc.sim_add_minimal_convolution_operator(ctx, u, smoothed, { mode = "separable", kernel_length = 3, kernel = {0.25, 0.5, 0.25}})
-- Separable 5-tap binomial filterooc.sim_add_minimal_convolution_operator(ctx, u, smoothed, { mode = "separable", kernel_length = 5, kernel = {1/16, 4/16, 6/16, 4/16, 1/16}})
-- Full 2D Laplacian (3x3)ooc.sim_add_minimal_convolution_operator(ctx, u, laplacian, { mode = "kernel_2d", kernel_rows = 3, kernel_cols = 3, kernel_2d = "0,1,0,1,-4,1,0,1,0", boundary = "neumann"})
-- 2D Sobel edge detection (X direction)ooc.sim_add_minimal_convolution_operator(ctx, image, edges_x, { mode = "kernel_2d", kernel_rows = 3, kernel_cols = 3, kernel_2d = {-1, 0, 1, -2, 0, 2, -1, 0, 1}})
-- Strided convolution for downsamplingooc.sim_add_minimal_convolution_operator(ctx, high_res, low_res, { mode = "separable", kernel_length = 5, kernel = {1, 4, 6, 4, 1}, stride = 2, boundary = "reflective"})
-- Runtime kernel swaplocal cfg = ooc.sim_minimal_convolution_config(ctx, op_index)ooc.log("conv: length=%d stride=%d boundary=%s", cfg.kernel_length, cfg.stride, cfg.boundary)
ooc.sim_minimal_convolution_update(ctx, op_index, { kernel_length = 7, kernel = {1, 6, 15, 20, 15, 6, 1}, -- Pascal's triangle row boundary = "periodic"})🧹 Sieve
Section titled “🧹 Sieve”sim_add_sieve_operator(ctx, src, dst, opts)
Apply spectral filtering and smoothing using various window functions and polynomial methods. Supports low-pass, high-pass, band-pass, and band-stop filters with Gaussian, Hann, Blackman, Tukey windows, and Savitzky-Golay polynomial filtering.
Method Signature
Section titled “Method Signature”sim_add_sieve_operator(ctx, input, output, [options]) -> operatorReturns: Operator handle (userdata)
Mathematical Formulation
Section titled “Mathematical Formulation”Gaussian Low-Pass:
where and .
Gaussian High-Pass:
where is the Dirac delta (identity for convolution).
Difference of Gaussians (DoG):
where creates a band-pass filter centered between the two scales.
Savitzky-Golay:
Fits a polynomial of order to a sliding window of taps samples, evaluating at the center (smoothing) or computing the derivative.
Windowed Filters (Hann, Blackman, Tukey):
where is the window function value at position . High-pass versions subtract from identity.
Parameters
Section titled “Parameters”Core Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
mode | enum | see below | Filtering method (required) | |
taps | integer | — | odd, ≥3 | Kernel length (required) |
gain | double | 1.0 | unbounded | Output gain multiplier |
accumulate | boolean | false | — | Add to output instead of overwriting |
scale_by_dt | boolean | true | — | Scale accumulated writes by dt |
Mode options:
- Gaussian:
low_pass,high_pass - DoG:
band_pass_dog,band_stop_dog - Savitzky-Golay:
savgol_smooth,savgol_derivative - Hann:
hann_low_pass,hann_high_pass - Blackman:
blackman_low_pass,blackman_high_pass - Tukey:
tukey_low_pass,tukey_high_pass
Gaussian Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
sigma | double | >0 | Gaussian standard deviation (samples) |
DoG Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
sigma | double | >0 | First Gaussian width | |
sigma2 | double | >0 | Second Gaussian width (should differ from sigma) |
Savitzky-Golay Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
poly_order | integer | — | < taps | Polynomial order for fitting |
Tukey Parameters:
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
sigma | double | [0, 1] | Tukey alpha parameter (0 = rectangular, 1 = Hann) |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Convolution-based; uses periodic boundaries by default
- Kernel is truncated to
tapssamples; ensure sufficient taps for the chosen sigma - Rule of thumb:
taps >= 6 * sigmafor Gaussian filters
Stability & Convergence
Section titled “Stability & Convergence”- All filters are unconditionally stable (bounded output for bounded input)
- Low-pass filters preserve DC component; high-pass filters remove it
- DoG filters are zero-sum (no DC response)
- Savitzky-Golay preserves polynomial moments up to order
poly_order
Performance Notes
Section titled “Performance Notes”- Pre-computed kernels; O(N × taps) per application
- Larger
tapsincreases accuracy but also computation - Savitzky-Golay requires polynomial coefficient computation (one-time)
- Consider
sim_add_minimal_convolution_operatorfor simple fixed-size kernels
Examples
Section titled “Examples”-- Gaussian low-pass smoothingooc.sim_add_sieve_operator(ctx, noisy, smooth, { mode = "low_pass", sigma = 1.2, taps = 7})
-- Gaussian high-pass (edge enhancement)ooc.sim_add_sieve_operator(ctx, image, edges, { mode = "high_pass", sigma = 2.0, taps = 13})
-- Difference of Gaussians band-passooc.sim_add_sieve_operator(ctx, signal, band, { mode = "band_pass_dog", sigma = 1.0, sigma2 = 3.0, taps = 19})
-- DoG notch filter (band-stop)ooc.sim_add_sieve_operator(ctx, signal, notched, { mode = "band_stop_dog", sigma = 2.0, sigma2 = 4.0, taps = 25})
-- Savitzky-Golay smoothing (preserves peaks)ooc.sim_add_sieve_operator(ctx, spectrum, smooth_spectrum, { mode = "savgol_smooth", taps = 11, poly_order = 3})
-- Savitzky-Golay derivative (noise-resistant)ooc.sim_add_sieve_operator(ctx, signal, derivative, { mode = "savgol_derivative", taps = 7, poly_order = 2})
-- Hann-windowed low-passooc.sim_add_sieve_operator(ctx, audio, filtered, { mode = "hann_low_pass", taps = 15})
-- Blackman high-pass (steep cutoff)ooc.sim_add_sieve_operator(ctx, signal, highpass, { mode = "blackman_high_pass", taps = 21})
-- Tukey window (adjustable taper)ooc.sim_add_sieve_operator(ctx, signal, tapered, { mode = "tukey_low_pass", taps = 17, sigma = 0.5 -- alpha parameter for Tukey})
-- Accumulate filtered output with gainooc.sim_add_sieve_operator(ctx, input, output, { mode = "low_pass", sigma = 1.5, taps = 9, gain = 2.0, accumulate = true})🔊 Sound Observation (Experimental)
Section titled “🔊 Sound Observation (Experimental)”sim_add_sound_observation_operator(ctx, input, [modulator], opts)
Sample a field and map features to audio control values or raw audio samples. Enables sonification of simulation state for monitoring, artistic expression, or accessibility.
Method Signature
Section titled “Method Signature”sim_add_sound_observation_operator(ctx, input, [modulator], [options]) -> operatorReturns: Operator handle (userdata)
Note: The optional modulator field provides an external modulation source for gain, pan, pitch, or FM synthesis.
Mathematical Formulation
Section titled “Mathematical Formulation”Sampling Modes:
For a field with samples:
- mean:
- rms:
- point:
- min/max: or
Feature Translation:
Extracted features are mapped to audio parameters through configurable translation chains:
where applies the selected feature extraction (amplitude, energy, phase, mean).
FM Synthesis:
When fm_source is active:
where is the modulation index controlled by fm_depth and the extracted feature.
Parameters
Section titled “Parameters”Output Configuration:
| Parameter | Type | Default | Description |
|---|---|---|---|
output_mode | enum | "controls" | Output type: controls (parameter values) or raw_samples (audio buffer) |
output_bus | integer | 0 | Target audio bus index |
output_send | double | 1.0 | Send level [0, 1] |
output_pre_fader | boolean | false | Send before fader processing |
Sampling Configuration:
| Parameter | Type | Default | Description |
|---|---|---|---|
sampling_mode | enum | "mean" | How to reduce field: mean, rms, point, min, max |
sampling_domain | enum | "physical" | Sample in physical or spectral domain |
window_type | enum | "rect" | Window function: rect, hann, hamming, blackman |
window_length | integer | 0 | Window size (0 = full field) |
window_offset | integer | 0 | Window start offset |
sample_index | integer | 0 | Index for point sampling mode |
Gain Translation:
| Parameter | Type | Default | Description |
|---|---|---|---|
gain_source | enum | "off" | Feature source: off, amplitude, energy, phase, mean_x, mean_y |
gain_modulator | enum | "none" | Modulation source: none, self_field, external_field |
gain_base | double | 1.0 | Base gain value |
gain_scale | double | 1.0 | Gain scaling factor |
gain_min | double | 0.0 | Minimum gain |
gain_max | double | 1.0 | Maximum gain |
Pan Translation:
| Parameter | Type | Default | Description |
|---|---|---|---|
pan_source | enum | "off" | Feature source for panning |
pan_modulator | enum | "none" | Modulation source |
pan_center | double | 0.0 | Pan center position [-1, 1] |
pan_width | double | 1.0 | Pan range width |
pan_law | enum | "linear" | Pan law: linear, sqrt, power |
Pitch Translation:
| Parameter | Type | Default | Description |
|---|---|---|---|
pitch_source | enum | "off" | Feature source for pitch |
pitch_modulator | enum | "none" | Modulation source |
pitch_base_hz | double | 440.0 | Base frequency in Hz |
pitch_range_octaves | double | 1.0 | Pitch range in octaves |
pitch_scale | enum | "linear_hz" | Scale mapping: linear_hz, log_semitone |
FM Translation:
| Parameter | Type | Default | Description |
|---|---|---|---|
fm_source | enum | "off" | Feature source for FM depth |
fm_modulator | enum | "none" | Modulation source |
fm_depth | double | 0.0 | Maximum modulation index |
fm_center | double | 0.0 | FM center frequency offset |
fm_ratio | double | 1.0 | Carrier-to-modulator frequency ratio |
fm_clip | double | 0.0 | FM output clipping (0 = no clip) |
Envelope:
| Parameter | Type | Default | Description |
|---|---|---|---|
attack_ms | double | 0.0 | Attack time in milliseconds |
release_ms | double | 0.0 | Release time in milliseconds |
smoothing_tau | double | 0.0 | Exponential smoothing time constant |
Raw Sampling Mode:
| Parameter | Type | Default | Description |
|---|---|---|---|
raw_source | enum | "real" | Component: real, imag, magnitude, phase |
raw_channel_mode | enum | "mono" | Channel mode: mono, stereo |
raw_gain | double | 1.0 | Raw output gain |
raw_clip | double | 1.0 | Hard clipping threshold |
raw_resample_mode | enum | "linear" | Resampling: linear, nearest |
Boundary & Initial Conditions
Section titled “Boundary & Initial Conditions”- Operates on field data; no spatial boundary handling
- Window parameters must fit within field bounds
- Initial envelope state starts at zero; transient during attack phase
Stability & Convergence
Section titled “Stability & Convergence”- Feature extraction is unconditionally stable
- Smoothing with large
smoothing_tauintroduces lag - FM synthesis can produce aliasing at high modulation depths; use
fm_clipto limit
Performance Notes
Section titled “Performance Notes”- Windowed sampling modes (
hann,hamming,blackman) require per-sample multiplication - Spectral domain sampling requires FFT (handled internally if field is physical)
- External modulator field adds a second field read per sample
- Raw sample mode may require resampling if field size differs from audio buffer
Examples
Section titled “Examples”-- Basic amplitude-to-gain sonificationooc.sim_add_sound_observation_operator(ctx, field, { gain_source = "amplitude", gain_base = 0.0, gain_scale = 2.0, gain_max = 1.0})
-- RMS-based pitch controlooc.sim_add_sound_observation_operator(ctx, field, { sampling_mode = "rms", pitch_source = "amplitude", pitch_base_hz = 220.0, pitch_range_octaves = 2.0, pitch_scale = "log_semitone"})
-- Stereo panning based on mean positionooc.sim_add_sound_observation_operator(ctx, field, { pan_source = "mean_x", pan_center = 0.0, pan_width = 2.0, pan_law = "sqrt"})
-- FM synthesis driven by field energyooc.sim_add_sound_observation_operator(ctx, carrier, modulator, { fm_source = "energy", fm_depth = 5.0, fm_ratio = 2.0, pitch_base_hz = 440.0})
-- Raw audio output from complex fieldooc.sim_add_sound_observation_operator(ctx, waveform, { output_mode = "raw_samples", raw_source = "real", raw_channel_mode = "stereo", raw_gain = 0.5, raw_clip = 0.95})
-- Windowed spectral observationooc.sim_add_sound_observation_operator(ctx, field, { sampling_mode = "rms", sampling_domain = "spectral", window_type = "hann", window_length = 256, gain_source = "amplitude", attack_ms = 10.0, release_ms = 100.0})
-- Point sampling at field centerlocal N = 512ooc.sim_add_sound_observation_operator(ctx, field, { sampling_mode = "point", sample_index = N / 2, gain_source = "amplitude", smoothing_tau = 0.01})