spike(rust/fft): port compute_cross_correlation to Rust (#96) - #103
Merged
Conversation
Implements the FFT cross-correlation core from AudioSyncer.js (L145-186) as a standalone Rust library function. Uses rustfft — no C FFT bindings. The division by N in the final normalization is explicit because rustfft's inverse transform does not normalize, unlike the JS fft library which normalizes implicitly. Omitting the division would scale SNR comparisons in validate_peak (#98) incorrectly. The impulse test documents that IFFT(FA * conj(FB)) places a lag-K peak at index N-K (the circular negative-lag form). This matches the JS formula exactly and is consistent with how find_best_lag (#97) will interpret the correlation array. AC: all acceptance criteria from #96
S1: assert corr.len() == 128 in the impulse test so the output-length AC is falsified for non-trivial inputs (previously only the single-sample case had an explicit length check). S2: document the len >= 1 precondition on compute_cross_correlation — empty slices cause usize underflow on `len_a + len_b - 1`, which is outside the AC scope but worth noting for callers.
natashaannn
force-pushed
the
spike/issue-96-fft
branch
from
July 12, 2026 10:45
8e98072 to
1d54990
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
next_power_of_twoandcompute_cross_correlationinspike/audio-sync/src/lib.rs, faithfully replicatingAudioSyncer.jsL145–186 usingrustfftspike/audio-sync/src/lib.rsper the hard constraintTests (5 inline
#[cfg(test)])next_power_of_two_known_valuescross_correlation_impulse_peak_at_kcross_correlation_identical_inputs_peak_at_zerocross_correlation_all_zeros_no_paniccross_correlation_single_sample_length_onecargo test --manifest-path spike/audio-sync/Cargo.toml— 5/5 pass.Notes
The impulse test asserts the peak at
N - K(notK).IFFT(FA × conj(FB))places a B-lags-A-by-K event at the circular negative-lag index N-K. The AC explicitly accepts this ("or N - K for negative lag"). A precondition doc comment notes that empty slices cause usize underflow.Closes #96
🤖 Generated with Claude Code