Phantom’s analyzers are tunable. Every analysis threshold and frame size is a knob on a single settings object called AnalysisSettings (src/phantom/_settings.py), and every knob has an environment variable override with a documented default. The knobs fall into four groups: phase and dynamics thresholds, the problem-detection threshold block, masking severity splits, and the FFT/frame sizes.
This page explains how tuning works, what the typed result models are, and the one caveat that matters before you change frame sizes.
How tuning works
-
Defaults reproduce the original constants. With no env var set, results are identical to the built-in constants Phantom always used. Nothing changes until you tune.
-
Every knob is env-overridable. Each field on
AnalysisSettingsmaps to aPHANTOM_*variable. Setting one overrides the default for every analysis that reads it. The complete list is in the Environment Variables Reference. -
Settings resolve per call. Analyzers read the effective settings when they run, not at import. A change to an env var takes effect on the next analysis without a restart.
-
The cache keys on your settings. The analysis cache folds a fingerprint of the current settings into its cache key. A tuned run is never served a result computed under different settings, and reverting to defaults doesn’t break earlier cached results.
The knob groups
| Group | Knobs | What changes |
|---|---|---|
| Phase and dynamics | polarity_threshold, phat_window_s, crest_factor_low_db | Polarity flagging, GCC-PHAT window, over-compression detection |
| Problem detection | 14 thresholds (clipping, DC offset, ISP, noise floor, SNR, band excess, resonances, lossy shelf) | Where each detector starts flagging and at what severity |
| Masking severity | severity_high, severity_moderate, severity_low, masking_floor_db | Where masking overlap scores become high/moderate/low labels |
| FFT / frame sizes | 6 frame and hop sizes across the spectral, octave-band, flatness, and power-spectrum passes | The analysis geometry itself |
Typed result models
Every tool returns a typed result model, not free text: each analyzer is a function that returns a Pydantic model with a fixed field schema, and the tools serialize it to structured JSON. Your assistant receives the same fields with the same names on every call.
The six analysis dimensions each return their own model:
| Dimension | Result model | Carries |
|---|---|---|
| Spectral | SpectralResult | Centroid, rolloff, contrast, flatness, dissonance, octave band energy |
| Loudness | LoudnessResult | Integrated LUFS, true peak dBTP, loudness range, short-term and momentary LUFS |
| Dynamics | DynamicsResult | RMS, peak, crest factor, dynamic range, dynamic complexity |
| Stereo | StereoResult | Correlation, width, mid/side ratio, L/R balance, panorama distribution |
| Phase | PhaseResult | Overall and per-band correlation, polarity |
| Problems | ProblemsResult | Clipping, DC offset, ISP, noise, hum, sibilance, mud, harshness, resonances |
Composite tools combine these models into larger typed payloads:
full_diagnostic/batch_diagnosticreturn aStemDiagnosticResultper file: file metadata (name, duration, sample rate, channels) plus one typed field per dimension. The model rejects unknown fields, so output shape is stable by construction.batch_diagnosticwraps stems in aBatchDiagnosticResultwith astemsmap andstem_count; failed stems appear as error objects, not dropped entries.multi_stem_maskingreturns typedMaskingPairentries with severity scores per pair.read_live_metricsreturns aLiveMetricsResultwith instance metadata and the raw meter snapshot.load_profilereturns aReferenceProfilewith loudness, frequency, stereo, and spatial targets.
Because the models are typed, tuning a threshold changes values inside the same schema — never the output shape. An assistant that learned the schema once keeps working when you adjust a knob.
The FFT comparability caveat
Changing frame sizes changes the analysis geometry, so results are not numerically comparable with the built-in genre profiles or reference-target comparisons, both of which are calibrated to the default frame sizes. A different octave-band or spectral frame size produces different band energies and descriptors.
Two rules when you tune the frame-size knobs:
- Reset the knobs to defaults before comparing, or
- Re-run the comparison itself under the same tuned geometry.
$ tune and re-run comparisons under the same geometry
both analyses must share the same frame sizes to be comparable
PHANTOM_SPECTRAL_FRAME_SIZE=4096 phantom compare master.wav —reference ref.wav PHANTOM_SPECTRAL_FRAME_SIZE=4096 phantom compare master.wav —profile pop
Pro tip
The threshold knobs (problem detection, masking severity, crest factor) don’t change analysis geometry, so tuned thresholds stay comparable with profiles and references. Only the six frame-size knobs trigger the caveat.