Measurement Operators
On this page
Phase Feature ใฐ๏ธ
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
add_phase_feature_operator(ctx, input, output, [options]) -> operator
Returns: Operator handle (userdata)
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
| 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
- 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
- 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
- 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
-- Extract unit-magnitude phase direction
ooc.add_phase_feature_operator(ctx, signal, phase_dir, {
exponent = 0.0
})
-- Magnitude gate with threshold
ooc.add_phase_feature_operator(ctx, signal, gated, {
threshold = 0.1,
exponent = 1.0
})
-- Squared magnitude feature (energy-like)
ooc.add_phase_feature_operator(ctx, signal, energy, {
exponent = 2.0
})
-- Accumulate phase-aligned energy over time
ooc.add_phase_feature_operator(ctx, signal, accumulated, {
exponent = 2.0,
accumulate = true,
scale_by_dt = true
})
-- Square root compression (reduce dynamic range)
ooc.add_phase_feature_operator(ctx, signal, compressed, {
exponent = 0.5,
threshold = 0.01
})
Minimal Convolution ๐งฉ
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
add_minimal_convolution_operator(ctx, input, output, [options]) -> operator
Returns: Operator handle (userdata)
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
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
- 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
- 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
- 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
Read current configuration:
local cfg = ooc.minimal_convolution_config(ctx, op_index)
-- Returns: { kernel_length, stride, accumulate, wrap, boundary, kernel }
Update configuration:
ooc.minimal_convolution_update(ctx, op_index, {
kernel_length = 5,
kernel = {1, 4, 6, 4, 1},
stride = 2,
boundary = "reflective"
})
Examples
-- 1D gradient kernel (central difference)
ooc.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 stencil
ooc.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 smoothing
ooc.add_minimal_convolution_operator(ctx, u, smoothed, {
mode = "separable",
kernel_length = 3,
kernel = {0.25, 0.5, 0.25}
})
-- Separable 5-tap binomial filter
ooc.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.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.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 downsampling
ooc.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 swap
local cfg = ooc.minimal_convolution_config(ctx, op_index)
ooc.log("conv: length=%d stride=%d boundary=%s",
cfg.kernel_length, cfg.stride, cfg.boundary)
ooc.minimal_convolution_update(ctx, op_index, {
kernel_length = 7,
kernel = {1, 6, 15, 20, 15, 6, 1}, -- Pascal's triangle row
boundary = "periodic"
})
Sieve ๐งน
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
add_sieve_operator(ctx, input, output, [options]) -> operator
Returns: Operator handle (userdata)
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
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
- 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
- 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
- Pre-computed kernels; O(N ร taps) per application
- Larger
tapsincreases accuracy but also computation - Savitzky-Golay requires polynomial coefficient computation (one-time)
- Consider
add_minimal_convolution_operatorfor simple fixed-size kernels
Examples
-- Gaussian low-pass smoothing
ooc.add_sieve_operator(ctx, noisy, smooth, {
mode = "low_pass",
sigma = 1.2,
taps = 7
})
-- Gaussian high-pass (edge enhancement)
ooc.add_sieve_operator(ctx, image, edges, {
mode = "high_pass",
sigma = 2.0,
taps = 13
})
-- Difference of Gaussians band-pass
ooc.add_sieve_operator(ctx, signal, band, {
mode = "band_pass_dog",
sigma = 1.0,
sigma2 = 3.0,
taps = 19
})
-- DoG notch filter (band-stop)
ooc.add_sieve_operator(ctx, signal, notched, {
mode = "band_stop_dog",
sigma = 2.0,
sigma2 = 4.0,
taps = 25
})
-- Savitzky-Golay smoothing (preserves peaks)
ooc.add_sieve_operator(ctx, spectrum, smooth_spectrum, {
mode = "savgol_smooth",
taps = 11,
poly_order = 3
})
-- Savitzky-Golay derivative (noise-resistant)
ooc.add_sieve_operator(ctx, signal, derivative, {
mode = "savgol_derivative",
taps = 7,
poly_order = 2
})
-- Hann-windowed low-pass
ooc.add_sieve_operator(ctx, audio, filtered, {
mode = "hann_low_pass",
taps = 15
})
-- Blackman high-pass (steep cutoff)
ooc.add_sieve_operator(ctx, signal, highpass, {
mode = "blackman_high_pass",
taps = 21
})
-- Tukey window (adjustable taper)
ooc.add_sieve_operator(ctx, signal, tapered, {
mode = "tukey_low_pass",
taps = 17,
sigma = 0.5 -- alpha parameter for Tukey
})
-- Accumulate filtered output with gain
ooc.add_sieve_operator(ctx, input, output, {
mode = "low_pass",
sigma = 1.5,
taps = 9,
gain = 2.0,
accumulate = true
})
Sound Observation ๐
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
add_sound_observation_operator(ctx, input, [modulator], [options]) -> operator
Returns: Operator handle (userdata)
Note: The optional modulator field provides an external modulation source for gain, pan, pitch, or FM synthesis.
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
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
- 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
- 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
- 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
-- Basic amplitude-to-gain sonification
ooc.add_sound_observation_operator(ctx, field, {
gain_source = "amplitude",
gain_base = 0.0,
gain_scale = 2.0,
gain_max = 1.0
})
-- RMS-based pitch control
ooc.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 position
ooc.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 energy
ooc.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 field
ooc.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 observation
ooc.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 center
local N = 512
ooc.add_sound_observation_operator(ctx, field, {
sampling_mode = "point",
sample_index = N / 2,
gain_source = "amplitude",
smoothing_tau = 0.01
})