Skip to content

Feat/beat envelope transform - #2

Open
AnnieScigliano wants to merge 2 commits into
mainfrom
feat/beat-envelope-transform
Open

Feat/beat envelope transform#2
AnnieScigliano wants to merge 2 commits into
mainfrom
feat/beat-envelope-transform

Conversation

@AnnieScigliano

Copy link
Copy Markdown
Contributor

What

Adds a stateful route transform, beat_envelope, that turns a rising-edge
trigger into a decaying gain envelope. On each edge (input crossing
threshold)
the output snaps to peak and relaxes toward floor.

{ "type": "beat_envelope", "peak": 1.0, "floor": 0.8, "tau_ratio": 0.3, 
"min_interval_ms": 300.0 }

Why

The Latido heartbeat route used a gate rising_edge, which lifts master gain
for
a single evaluation — a flash. beat_envelope makes it breathe: each ECG
beat swells the field and decays, phase-locked to the heart. The time constant
auto-scales from the measured inter-beat interval (tau_ratio 0.3, matching
cymatic-control's HEARTBEAT_PULSE 0.3·60/bpm), so it needs no bpm channel.

How

- compiler.py: allow-list + compile validation (floor < peak, positive
tau/tau_ratio) + output range propagated as [floor, peak]; stateful
runtime in evaluate_route with per-transform state on RouteRuntime.beat_state
(value/beat_us/eval_us/last_in/tau_ms). Decay uses now_us deltas
(deterministic, like smoothing/phase_accumulator); edge detection prevents
re-firing on a sustained-high input. A min_interval_ms refractory guard
rejects double-fires.

Tests

tests/test_beat_envelope.py (8): compile/range, edge→peak, tau decay,
no-refire-while-held, refractory, tau auto-scale from interval, floor/peak
bounds.

Branch is merged up to date with main; the full combined suite passes: 82
passed, 2 skipped — beat_envelope, slew_limiter, and derivative all
coexist. (The test_harmocap_driver.py collection error is a pre-existing
hardcoded ~/Projects/HarMoCAP path, unrelated to this change.)

Docs

CORE_DESIGN.md transform table + stateful-transform note.

AnnieScigliano and others added 2 commits July 20, 2026 21:15
A stateful route transform that turns a rising-edge trigger into a decaying
gain envelope: on each edge (input crossing `threshold`) the output snaps to
`peak` and relaxes toward `floor` with a time constant that is either fixed
(`tau_ms`) or auto-scaled from the measured inter-beat interval (`tau_ratio`,
default 0.3 — matching the cymatic-control HEARTBEAT_PULSE `0.3·60/bpm`). A
`min_interval_ms` refractory guard rejects double-fires.

Why: the Latido heartbeat currently uses a `gate rising_edge`, which lifts the
master gain for a single evaluation — a flash. beat_envelope makes it *breathe*:
each ECG beat swells the field and decays, phase-locked to the heart, without
needing the bpm channel (it measures the interval itself).

How:
- compiler.py: allow-list + compile validation (floor < peak, positive
  tau/tau_ratio) + output range propagated as [floor, peak]; stateful runtime
  in evaluate_route with per-transform state on RouteRuntime.beat_state
  (value/beat_us/eval_us/last_in/tau_ms). Decay uses now_us deltas
  (deterministic, like smoothing/phase_accumulator); edge detection prevents
  re-firing on a sustained-high input.

Tests: tests/test_beat_envelope.py (8) — compile/range, edge→peak, tau decay,
no-refire-while-held, refractory, tau auto-scale from interval, floor/peak
bounds. Full suite: 65 passed, 2 skipped (test_harmocap_driver.py collection
error is the pre-existing hardcoded ~/Projects path).

Docs: CORE_DESIGN.md transform table + stateful-transform note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ansform

# Conflicts:
#	docs/CORE_DESIGN.md
#	src/harmonic_weaver/engine/compiler.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant