Systems and subsystems

Handcrafted spectral and prosody features

Two hundred and thirty-four engineered features of the spectrum and the prosody of a clip, fed to gradient-boosted trees that are evaluated in plain numpy at inference. Interpretable by construction: every sentence it writes names the three features that moved it and by how many standard deviations from real speech.

In plain words

The handcrafted detectorEngineered spectral and prosody features (cepstral statistics, spectral shape, phase cues, pitch, loudness, pauses) fed to gradient-boosted trees, evaluated at inference in plain numpy. is the one a person can argue with. It measures things with names, such as how much the cepstral coefficients change from frame to frame, how the pitch moves, whether the phase behaves like a vocoder's, and learns which of them separate real from synthetic. It is the spectralFeatures of the frequency content of the audio over time: energy per band, roll-off, flatness, cepstral coefficients (MFCC, LFCC, CQCC) and how they change from frame to frame. and the prosodyThe rhythm and melody of speech: pitch movement, loudness changes, pauses, breaths. Synthetic speech tends to be more regular than a person. techniques of the rubric in one detector. It is excellent on generators it has seen and blind to web-sourced fakes, which is why it has a fifth of the vote and not half.

What goes in and comes out

In: the band-matched, trimmed, test-length-cropped, RMS-normalized clip. Out: a probability from the trees (the exported logit is its logit), the feature values, and a sentence of the form spectral/prosody features real-like (P=0.16): LFCC 16 frame-to-frame change 3.0 SD below real speech (toward synthetic); …, the three largest contributions in standard deviations from the real-speech mean of the inner rows.

Where it lives

The 75 base features and the augmentation in handcrafted.py; the six added families in hc_v4.py; extraction and training in extract_handcrafted.py and train_handcrafted.py; the detector wrapper in detectors/handcrafted.py over the shared learned base; the numpy tree evaluator in trees.py.

Parameters and where each is set

Status

Shipped as v5b at weight 0.2source: README.md, section how-it-decides: the v4 columns with augmented twins, trained with augmentation and validated on clean rows only.

Numbers

v3 (75 features): inner 0.614source: README.md, section numbers, holdout 0.254source: README.md, section numbers. v4a (234source: README.md, section the-eight-forensic-techniques features): inner 0.434source: README.md, section numbers, holdout 0.170source: README.md, section numbers; pro_diff went from 1.00source: README.md, section what-worked to 0.32source: README.md, section what-worked out of fold. v5b: inner 0.469source: README.md, section numbers, holdout 0.137source: README.md, section numbers (EER 3.1%source: README.md, section numbers), In-the-Wild false alarms 0.40%source: README.md, section numbers, test share above 0.5source: README.md, section numbers 45.1%source: README.md, section numbers; holdout-real false alarms fell from 9.1%source: README.md, section what-worked to 6.3%source: README.md, section what-worked. Trees beat the linear model on the same features, holdout 0.374source: README.md, section what-worked against 0.661source: README.md, section what-worked.

Known limits

In-the-Wild minDCF 1.00source: README.md, section what-did-not-work: it does not transfer to web-sourced fakes. Even band-matched, the columns tell training from test audio at AUCArea under the ROC curve: the probability that a random synthetic file scores above a random real one. 1.0 is perfect separation, 0.5 is chance. 0.99source: README.md, section what-did-not-work, and pruning the shifted columns made it worse. grad_tts is invisible to it when held out. At 20 dB white noise it loses almost all discrimination (AUC 0.998source: README.md, section what-did-not-work → 0.64source: README.md, section what-did-not-work), the shipped rule's weak spot.

Tests that pin it

tests/test_handcrafted_detector.py (contract, direction, the sentence names features and direction, memoization, a missing model is an error, the bundle's families are recomputed at inference), test_hc_v4.py (key sets, offset invariance, phase coherence, LFCC tilt, modulation sums, jitter), test_hc_augment.py (tilt darkens or brightens, reproducible draws, augmentation off by default), test_trees.py (matches LightGBM, contributions sum to the raw score, agrees with SHAP on top features, NaN handling, categorical splits rejected, no LightGBM import).

Sources

The CPU detectors report; the v4 and v5 report; the feature-engineering map; Architecture §7.