// curve_tessellate.h — the staged envelope's TRACE: envelope_overlay's node vertices joined by // the curve each stage's exponent defines. Split from that module on the axis the two already // have — envelope_overlay decides where a node LANDS, this strokes the span BETWEEN two of // them over phi, so a re-scaled time axis changes nothing here. #pragma once #include #include "core/instrument/ui/envelope_overlay.h" #include "core/ui/stroke_aa.h" // StrokePoint — the stroker's own vertex type namespace reasampler::instrument::ui { // The exponent governing the segment that ENDS at `node`: attack, decay and release are the // three sloped stages. Every other node ends a plateau, whose straightness comes from its own // zero level span rather than from an exponent, so neutral is returned and no caller needs a // second rule to recognize one. double segmentCurve(const StageEnvelope& env, EnvNode endNode); // Replaces `out` with the polyline the shell strokes. Knot vertices are handles, not line // vertices, and are skipped; node vertices keep their exact INTEGER coordinates (clamped to // [xLo, xHi]) because those are the positions their draggable handles are drawn at. Only the // interior samples are sub-pixel, one per pixel column, which is what makes the density follow // the canvas width instead of a fixed count. // // A segment's level runs start + (end - start) * curveMap(phi, exponent) — the composition // envelopes.h's four evaluators use, so the trace cannot diverge from the sound. A neutral // exponent or a zero level span emits the two endpoints and nothing between: the straight // stroke, vertex for vertex. void buildEnvelopeTrace(const std::vector& poly, const StageEnvelope& env, int xLo, int xHi, std::vector& out); } // namespace reasampler::instrument::ui