feat(7sense): real-time animal sound identification and acoustic visualization - #779
Draft
ruvnet wants to merge 2 commits into
Draft
feat(7sense): real-time animal sound identification and acoustic visualization#779ruvnet wants to merge 2 commits into
ruvnet wants to merge 2 commits into
Conversation
The example promised real-time identification and a manifold visualization that no code implemented. These four ADRs record how each gap is closed, and the first of them is now built. ADR-010 designs streaming ingestion: an AudioSource trait so cpal stays optional and WASM keeps building, a lock-free ring buffer with an explicit lossy-overwrite policy, and an EMA noise floor with hysteresis so segments can close before a recording ends. ADR-011 specifies interpretable acoustic descriptors, computed from a linear power spectrum rather than the mel path, since log-scaled perceptual bins do not yield a centroid in Hz. ADR-012 supersedes ADR-009's technology choices: PCA via randomized SVD as the default projection because it is deterministic and extends to new points in one matrix multiply, with UMAP opt-in over the existing HNSW graph. ADR-013 makes identification k-NN retrieval against a labelled index rather than classification. Perch emits embeddings, not logits, and retrieval is open-set, extensible without retraining, and evidence-backed. Implements ADR-011 as sevensense-audio::features: centroid, spread, skewness, rolloff, flatness, tonality, crest, entropy, slope, interpolated dominant frequency, plus amplitude and frequency modulation across frames. This populates CallSegment::spectral_centroid, whose builder previously had no callers anywhere in the workspace. Three details the tests pin down. Flatness uses exp(mean(ln p)) because the product of ~1000 bin powers underflows f32. Summary statistics cover voiced frames only, so silence cannot drag the centroid toward the noise floor. Modulation is None below 32 frames rather than a fabricated rate, and its search band is capped at envelope Nyquist -- 50 Hz at the default hop, which corrects an overstatement in the first draft of ADR-011. 23 new tests, all driven by signals with analytically known descriptors. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_018tPo7cc6trZB1eNJ3YrC7Q
Runtime lock state written by the task scheduler when this session acquired it. Kept in its own commit so it does not mix into the 7sense feature history. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_018tPo7cc6trZB1eNJ3YrC7Q
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.
Context
The
vibecast-7senseexample advertises real-time species identification and a manifold visualization. An audit of the code found neither exists, and several documented entry points resolve to nothing:ingest_file(&Path)decoding the whole file into aVec<f32>. TheAudioStream::new()in the crate README is not a real type./ws/streamis documented in two READMEs but no such route is registered, and the WebSocket receive task discards every inbound frame.POST /api/identifycould not have been served.sevensense-vizcrate that ADR-009 specifies was never created, and the API'sumap_urlpoints at an unregistered route.sevensense-apideclares all seven sibling crates as dependencies and imports none of them, reimplementing each stage as a stub that returns zero vectors and empty segments.This PR closes those gaps. It is being built incrementally; the checklist below tracks progress.
Architecture decisions
Four ADRs record the design before the code lands.
ADR-010 — Real-time streaming ingestion. An
AudioSourcetrait keepscpalbehind a non-default feature so WASM keeps building. A lock-free ring buffer with an explicit lossy-overwrite policy, because blocking a real-time audio callback causes device glitches and stale audio is worth less than current audio. An EMA noise floor with open/close hysteresis replaces global statistics, so a segment can close before the recording ends.ADR-011 — Acoustic feature extraction. Descriptors are computed from a linear-frequency power spectrum rather than the existing mel path, because log-scaled perceptually-spaced bins do not yield a centroid in Hz.
ADR-012 — Manifold projection. Supersedes ADR-009's technology choices. PCA via randomized SVD is the default rather than UMAP: it is deterministic, so saved viewports stay valid, and it extends to new points in one matrix multiply, which is what streaming needs. UMAP remains opt-in, implemented over the existing HNSW graph rather than via the unmaintained
umap-rs.ADR-013 — Retrieval-based identification. k-NN against a labelled reference index instead of a classifier. Open-set by construction, so unknown species are detectable rather than forced into the nearest class; extensible by adding reference recordings rather than retraining; and every result carries the neighbours that produced it, which is what makes it auditable.
Progress
sevensense-audio::features— interpretable acoustic descriptors (ADR-011)sevensense-apito the real crates; add/ws/stream,/projection,/featuresChanges so far
sevensense-audio::featurescomputes spectral centroid, spread, skewness, rolloff, flatness, tonality, crest, entropy, slope, and a parabolically-interpolated dominant frequency per frame, plus amplitude and frequency modulation across frames. This populatesCallSegment::spectral_centroid— a field whose builder previously had no callers anywhere in the workspace, leaving it permanentlyNone.Three details worth review:
exp(mean(ln p))rather than a direct product. The product of ~1000 bin powers underflowsf32immediately.Nonebelow 32 frames rather than a fabricated rate. Its search band is capped at envelope Nyquist — 50 Hz at the default 100 fps hop, which corrects an overstatement in the first draft of ADR-011 that the implementation disproved.Testing
23 new tests, each driven by a synthetic signal whose descriptors are known analytically, so a failure points at the maths rather than at a fixture: a 4 kHz tone must yield a 4 kHz centroid; a 5010 Hz tone must resolve to better than half a bin width; a 20 Hz amplitude-modulated carrier must report a 20 Hz rate; a 2→8 kHz sweep must show wide FM extent. Pathological inputs (DC, alternating full-scale, single impulse) are asserted finite across every descriptor.
Full crate suite: 59 passing, 0 failing.
Generated by Claude Code