Skip to content

v1.5.2

Choose a tag to compare

@leesaenz leesaenz released this 22 Aug 02:14
· 20 commits to main since this release
25d62a2

Fixed

Stereo rating on the reference path

compare_to_reference rated stereo width and correlation on the dB scale.
The #56 fix in 1.5.1 corrected compare_to_profile only, so the reference path
still called _rate_deviation_ref with no thresholds and fell back to the dB
defaults (1.0/3.0/6.0).

Width gaps between two mixes top out near 1.2 and correlation gaps at 2.0, so
anything under 1.0 read on_target and, for correlation, the significant
ratings were unreachable by construction. A near-mono mix against a decorrelated
reference reported deviation 1.0 and rated on_target.

Width reuses _WIDTH_THRESHOLDS. Correlation gets _CORRELATION_THRESHOLDS,
anchored on _BASS_MONO_THRESHOLD — a 0.05 departure from fully mono is the
established just-detectable step — with 0.15/0.25 continuing the ladder.

GCC-PHAT delay on short inputs

_gcc_phat_delay built its lag region without checking the correlation was long
enough to hold it. max_shift is 2205 samples at 44.1 kHz, so once an input fell
below twice that the two halves overlapped, and once it fell below max_shift
the negative slice clamped to the whole array.

Measured with broadband noise: a 1000-sample pair with a true delay of 0
reported -2205 samples (-50.00 ms); the same pair at delay 100 reported -2105
(-47.73 ms). The reading tracked the real delay but sat a full window away from
it. Reachable from real files, since compare_phase truncates both signals to
the shorter one.

max_shift is now clamped to n // 2.

Other fixes

  • PHANTOM_MASKING_TOP_N rejects 0 and negatives. Pairs sort worst-first, so a
    negative slice dropped the most severe pairs rather than returning fewer.
  • fix --interactive --json keeps its prompt off stdout, so the document parses.
  • read_live_metrics returns the "no live metrics" message instead of a raw
    FileNotFoundError when a snapshot vanishes between listing and selection.
  • enforce_decode_limits honours its AudioLoadError contract in the size probe.
  • install.sh reports phantom's exit status, not grep's — two of three success
    cases previously printed a failure.
  • install.ps1 checks $LASTEXITCODE after phantom setup.
  • Commit hooks scan .ps1 and .bats, and block the Claude URL shapes actually
    handed out.
  • CI: the optional-extras job can fail the build and runs test_processing.py;
    the planning-docs gate fetches origin/main before diffing.

Added

mid_side_state

mid_side_ratio_db is undefined at both extremes and returned a bare None for
each — a mono file has no side energy, a fully inverted one has no mid. Those are
opposite conditions: mono is usually fine, fully inverted cancels on a mono fold.

StereoResult now carries mid_side_state, set to pure_mid or pure_side in
those cases and None when the ratio is a real measurement. Additive; the
existing field is unchanged.

Tests

Nine tests closing gaps confirmed by mutation testing: compare_phase
resampling (deleting align_sample_rates left all 43 phase tests passing), the
masking moderate/low severity branches (both threshold tests asserted inside
an if that never ran), and dynamic_complexity/loudness_db (replacing the
Essentia call with constants passed the entire suite).

Also rewritten to depend on what they name: band normalization call sites, the
problem sort order, and the analysis window truncation.

Known

Phantom still does not install on Windows. essentia has never published a
Windows wheel, so uv tool install phantom-audio fails at dependency
resolution. Tracked in #52. Phantom Studio, the plugin, is unaffected — it does
not use essentia and builds on Windows.

Full Changelog: v1.5.1...v1.5.2