fix: a crossing is counted with hysteresis, so noise is not counted as cycles
period, frequency and pulse duration counted every sign change about a single level, which is unusable on any real signal: the mid level is exactly where a waveform moves fastest, so an interferer faster than the fundamental recrosses it several times per true crossing. A 5 Hz sine with a 500 Hz tone at a tenth of the amplitude read 79 crossings for 9, period=0.025622 against 0.2. MeasureLevel gains a hysteresis band sized once in measure_set_level(): a tenth of the window's peak-to-peak, clamped to half the room to the nearer extreme so a threshold set near one stays usable. The band moves the edge decision only -- the sum/count split stays at the bare level, since that split is top/bottom and has a documented exact reading. The bucket fast path tests the band and the level separately rather than folding them, or it would refuse exactly the buckets a crossing passes through: clean cost is unchanged at raw=0.1% and 1.41 ms a recompute. tools/mock_udpstreamer.py gains --noise, defaulting to 0 so the exact probe assertions still hold. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
b4b26d3e31
commit
13574bfcef
7 files changed
+321
-76
No files matched your search
@@ -24,6 +24,17 @@ set, with <b>Save</b> and <b>Delete</b>.
|
||||
• An invalid pass keeps its <i>level</i> marks and drops its <i>time</i> marks. A level is a
|
||||
property of the signal and outlives the window; a position inside the window does not. That is
|
||||
what stops the rulers blinking off at a mode change.
|
||||
• A crossing is counted with <i>hysteresis</i>, not on a bare level: the thresholds are a tenth of
|
||||
the window's peak to peak either side of the share, and an edge is counted only once the signal
|
||||
has passed the far one. Period, frequency and pulse duration all depend on it. The mid level is
|
||||
exactly where a waveform moves fastest, so any interferer faster than the fundamental recrosses a
|
||||
single level several times per real crossing — a 5 Hz sine with a 500 Hz tone at a tenth of the
|
||||
amplitude reads 39 Hz without the band and 5 Hz with it. The band holds to an interferer a third
|
||||
of the waveform's own size.
|
||||
• The band is clamped to stay inside the data, which is what keeps a threshold set near an extreme
|
||||
usable: a fixed band there would sit above every sample and the measurement would read nothing.
|
||||
A share near an extreme still leaves the band little room, so it rejects less — which is one
|
||||
reason period and frequency offer no share to set.
|
||||
• A window with too few crossings reads <tt>invalid</tt> / <tt>--</tt> rather than a plausible
|
||||
invented number. Frequency over a window holding one edge is the usual case.
|
||||
• <tt>frequency</tt> is reported in Hz and <tt>period</tt>/<tt>pulse duration</tt> in seconds;
|
||||
|
||||
Reference in new issue
Block a user