Skip to content

spike(rust/snr): port validate_peak to Rust - #105

Merged
missabawse merged 2 commits into
mainfrom
spike/issue-98-snr
Jul 14, 2026
Merged

spike(rust/snr): port validate_peak to Rust#105
missabawse merged 2 commits into
mainfrom
spike/issue-98-snr

Conversation

@natashaannn

Copy link
Copy Markdown
Member

Summary

  • Ports validatePeak from scripts/sync/AudioSyncer.js L218–235 to pub fn validate_peak(correlation: &[f64], lag_seconds: f64, sample_rate: u32) -> (f64, bool) in spike/audio-sync/src/lib.rs
  • Adds RELIABILITY_SNR_THRESHOLD = 3.0 constant (specified in the issue as coming from spike(rust/lag): port find_best_lag to Rust #97 but was absent from the merged code)
  • Adds # Preconditions doc note for the empty-slice panic (mirrors compute_cross_correlation)

Implementation notes

The port is a faithful replica of the JS:

  • Biased variance (sumSq/N - mean²) matches the JS formula exactly — not Bessel-corrected
  • Index reconstruction uses (x + 0.5).floor() twice (once for lagFrames, once for lagSamples) to replicate Math.round including negative half-frame tie-breaking
  • Modular wrap uses signed i64 arithmetic: ((lag_samples % n_i) + n_i) % n_i — identical to the JS ((lagSamples % N) + N) % N
  • Zero-std guard returns (0.0, false) without panicking, matching snr = std > 0 ? ... : 0

Test plan

  • validate_peak_high_snr_returns_reliable — sharp peak at idx 0 with lag 0.0 → (snr ≥ 3.0, true)
  • validate_peak_flat_array_returns_not_reliable — all-equal array → (0.0, false)
  • validate_peak_zero_std_no_panic — all-equal values, explicit zero-std guard → no panic, (0.0, false)
  • validate_peak_negative_lag_modular_wrap — symmetric correlation, ±1 frame lag yields identical SNR
  • validate_peak_length_one_no_panic — single-element slice → no panic
  • cargo test — 18/18 pass
  • npm test — 363/363 pass

Closes #98

🤖 Generated with Claude Code

Ports validatePeak from scripts/sync/AudioSyncer.js L218-235 to a
pub fn validate_peak(correlation, lag_seconds, sample_rate) -> (f64, bool)
in spike/audio-sync/src/lib.rs.

Replicates the JS SNR check exactly: biased (population) variance sumSq/N
- mean², index reconstruction via (x + 0.5).floor() to match JS Math.round
on both round operations, and modular wrap ((lagSamples % N) + N) % N for
negative lags. Returns (0.0, false) on std = 0 without panicking, matching
the JS `snr = std > 0 ? ... : 0` guard.

Also adds RELIABILITY_SNR_THRESHOLD = 3.0 constant (was specified in the
issue as already present from #97, but was not yet in lib.rs).

5 tests added: high-SNR reliable, flat/near-silence not-reliable, zero-std
guard, negative lag modular wrap, and length-1 no-panic.

AC: #1 (high-SNR reliable), #2 (near-silence not-reliable), #3 (zero-std guard)
An empty correlation slice causes lag_samples % n_i to be integer
division by zero — unconditional panic in both debug and release.
Mirrors the existing # Preconditions note on compute_cross_correlation.
@natashaannn
natashaannn requested a review from missabawse July 12, 2026 12:53

@missabawse missabawse left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests pass on my end

@missabawse
missabawse merged commit 1bc0e49 into main Jul 14, 2026
1 check passed
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.

spike(rust/snr): port validate_peak to Rust

2 participants