Ω-W1-T3: run the master meter on its own 60 FPS timer, and make a meter frame cost one rect
This commit is contained in:
@@ -260,21 +260,31 @@ against a performance budget — they are there because `VoiceEngine::applyLiveT
|
||||
detector's 4-sample group delay INSIDE that budget, not on top), bounded by one 500 ms tick.
|
||||
Narrowing it further means a second deferral mechanism (a posted window message) rather than
|
||||
the tick — deliberately not built.
|
||||
- **The MASTER meter's ballistics ride the sync tick, and that tick is 500 ms.** They run
|
||||
BEFORE the tick's in-flight-drag guard on purpose — a drag suppresses the reload poll, but
|
||||
the bus keeps sounding. Elapsed time is measured (`GetTickCount64`), never assumed from the
|
||||
timer's period, and the tick repaints only when `meterDrawEqual` says the picture changed.
|
||||
**The published block state is therefore ACCUMULATED, not sampled**: at 48 kHz / 512 frames
|
||||
~47 blocks elapse per tick, so the processor folds a per-channel max and a min limiter gain
|
||||
across them and `masterBusMeter()` clears the accumulators as it reads. A plain overwriting
|
||||
store displayed one block in ~47 and lost the rest — the specified "a peak displays on the
|
||||
first UI frame after it occurs" is what the fold restores. `masterBusMeter()` is CONSUMING,
|
||||
so exactly one caller may hold it; the embed strip reads its own non-consuming
|
||||
- **The MASTER meter has its OWN 16 ms timer, beside the 500 ms sync poll.** It runs outside
|
||||
that poll's in-flight-drag guard on purpose — a drag suppresses the reload poll, but the bus
|
||||
keeps sounding. Elapsed time is measured (`steady_clock`, whose resolution the rate needs —
|
||||
`GetTickCount64`'s ~15.6 ms quantized a frame's delta to 0 or 16), never assumed from the
|
||||
timer's period, a zero delta skips the advance, and the tick repaints only when
|
||||
`meterDrawEqual` says the picture changed. **The published block state is ACCUMULATED, not
|
||||
sampled**: the processor folds a per-channel max and a min limiter gain across every block
|
||||
since the last read and `masterBusMeter()` clears the accumulators as it reads. A plain
|
||||
overwriting store displayed one block per window and lost the rest — the specified "a peak
|
||||
displays on the first UI frame after it occurs" is what the fold restores. `masterBusMeter()`
|
||||
is CONSUMING, so exactly one caller may hold it — which is why the meter block MOVED to the
|
||||
meter tick rather than being copied there; the embed strip reads its own non-consuming
|
||||
`embedActivityLevel()`. **The tick's FIRST read is discarded**, because that caller is the
|
||||
only consumer: with no editor open the accumulators hold everything since the instance was
|
||||
created, and advancing off them would open the meter at the session's loudest peak. The clip
|
||||
latch is not discarded with them — it is a latch the user clears. A meter-rate timer remains a
|
||||
separate change and is not in.
|
||||
latch is not discarded with them — it is a latch the user clears.
|
||||
- **A meter frame repaints the bar FIELD, not the client area**, which is what makes the rate
|
||||
affordable: `paint` honours `ps.rcPaint` against the field rect `paintDeck` cached, composes
|
||||
into a RETAINED back buffer (so the rest of the face is still there from the last full
|
||||
compose) and blits the dirty region alone. The fast path is chosen GEOMETRICALLY, never by a
|
||||
flag — Windows unions a meter invalidate with any other pending one into a single rcPaint, so
|
||||
a flag would paint a meter frame over a face that had really changed. What stays outside the
|
||||
field stays on the full path: the static numeral gutter (AA text re-blended onto itself every
|
||||
frame thickens) and the GR lamp (drawn straight onto the deck group's gradient, which a
|
||||
sub-rect fill cannot reproduce), so a lamp transition takes a whole-client repaint.
|
||||
- The bake's availability probe runs on the SAME tick that paints the button, so the
|
||||
control can never be enabled on one tick and refuse on the next. The bake Hold control's
|
||||
applicability (`resolveBakeHoldNeeded`) rides the same tick for the same reason, and
|
||||
|
||||
Reference in New Issue
Block a user