Two real bugs found via code inspection against HF source:
1. candle's .gelu() is the tanh approximation; PyTorch's default 'gelu'
activation (used in WavLM via ACT2FN['gelu']) is the exact erf-based
version. Switched all 3 sites (feature extractor convs, pos_conv,
FFN) from .gelu() to .gelu_erf() to match the reference.
2. gru_rel_pos_const lookup used vb.pp("name").get(shape, "") which
resolves to "<prefix>.name." (trailing dot) and fails to find the
tensor. The .or_else(|_| zeros) silently swallowed the failure,
leaving all 12 layers' gating constants at zero instead of the
trained values. Fixed to attn.get(shape, "gru_rel_pos_const") which
resolves correctly.
examples/wavlm_sv_inspect.rs: utility for sanity-checking specific
tensors inside converted safetensors (e.g. layer_weights).
Same-content same-speaker cosine: 0.9985 -> 0.9963 (≈unchanged).
Cross-content same-speaker cosine: 0.4882 -> 0.4118 (still drifting).
Phase 5d (Python reference comparison) remains the gate for
identifying the residual numerical drift.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Single CLI ties together every capability shipped this session:
text -> CSM-1B (with optional LoRA) -> post-process (HPF/declick/LUFS)
-> AudioSeal watermark embed -> AudioSeal detect verify -> WavLM-SV
speaker embedding + optional reference scoring.
Verified on Metal: 4s speech generated + watermarked + detected
(mean_presence=0.9999, 16/16 bits decoded) + 512-d speaker embedding
extracted in ~30s.
Cross-content same-speaker cosine sits around 0.49 vs 0.998 for
same-content same-speaker — suggests the WavLM-SV port may leak content
into the speaker embedding more than the HF reference. Phase 5d numerical
parity work (Python sidecar comparison) would tighten this.
This is the canonical usage example for downstream callers
(clawsample-csm etc.) — copy the structure.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
End-to-end watermarker driver that handles any source sample rate by
resampling to AudioSeal's 16 kHz native, embedding, then resampling back.
Tested on 10s of real CSM 24 kHz speech: mean_presence=0.9988 detection,
12/16 message bits round-trip (4-bit erosion from double resample).
- examples/audioseal_apply.rs: --in/--out/--source-rate/--message; loads
source via audio_io::load_mono_at_rate, calls AudioSealWatermarker
through the public Watermarker trait, verifies via in-process detect.
- Fix bit-match counter overflow in audioseal_demo.rs and audioseal_apply.rs.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>