From 949070ce7365d88f6fbb89a4c1be89e992604be4 Mon Sep 17 00:00:00 2001 From: dev Date: Sun, 14 Jun 2026 21:44:46 +0200 Subject: [PATCH] fix(quality): make "audiophile" preset truly 24-bit-only (no 16-bit/MP3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The audiophile preset (fallback_enabled=False) still shipped a "FLAC 16-bit" target in its ladder, so 16-bit FLAC matched and imported even though the name implies hi-res-only. Split the ladder: audiophile now uses a strict 24-bit FLAC list; balanced keeps 24-bit + 16-bit + MP3. Gives users a one-click strict "24-bit only" profile that actually rejects 16-bit/lossy. Not a matches_target bug — that correctly rejects 16-bit vs a 24-bit target; the leak was the preset's target LIST including 16-bit (+ fallback accepting off-list lossy like MP3-128). Co-Authored-By: Claude Opus 4.8 --- database/music_database.py | 9 ++++++-- tests/quality/test_quality_presets.py | 33 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/quality/test_quality_presets.py diff --git a/database/music_database.py b/database/music_database.py index 335dacf5..3f0b137b 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -8653,11 +8653,16 @@ class MusicDatabase: def get_quality_preset(self, preset_name: str) -> dict: """Get a predefined quality preset (v3 format with ranked_targets).""" - _FLAC_HI_RES_TARGETS = [ + # Strict 24-bit FLAC ladder — no 16-bit, no lossy. This is what + # "audiophile" means: only true hi-res passes. + _FLAC_24BIT_TARGETS = [ {"label": "FLAC 24-bit/192kHz", "format": "flac", "bit_depth": 24, "min_sample_rate": 192000}, {"label": "FLAC 24-bit/96kHz", "format": "flac", "bit_depth": 24, "min_sample_rate": 96000}, {"label": "FLAC 24-bit/48kHz", "format": "flac", "bit_depth": 24, "min_sample_rate": 48000}, {"label": "FLAC 24-bit/44.1kHz","format": "flac", "bit_depth": 24, "min_sample_rate": 44100}, + ] + # Lossless ladder used by "balanced" — hi-res first, then CD-quality 16-bit. + _FLAC_HI_RES_TARGETS = _FLAC_24BIT_TARGETS + [ {"label": "FLAC 16-bit", "format": "flac", "bit_depth": 16}, ] _MP3_TARGETS = [ @@ -8668,7 +8673,7 @@ class MusicDatabase: presets = { "audiophile": { "version": 3, "preset": "audiophile", "fallback_enabled": False, - "ranked_targets": _FLAC_HI_RES_TARGETS, + "ranked_targets": _FLAC_24BIT_TARGETS, }, "balanced": { "version": 3, "preset": "balanced", "fallback_enabled": True, diff --git a/tests/quality/test_quality_presets.py b/tests/quality/test_quality_presets.py new file mode 100644 index 00000000..2ffcfaa0 --- /dev/null +++ b/tests/quality/test_quality_presets.py @@ -0,0 +1,33 @@ +"""Quality presets — the built-in ranked-target ladders behind the preset +buttons. `audiophile` must be STRICT hi-res (no 16-bit, no lossy, fallback off) +so a user who wants "24-bit only" gets it in one click; `balanced` keeps the +fuller ladder (16-bit + MP3) with fallback on. +""" + +from database.music_database import MusicDatabase + + +def _preset(name): + # get_quality_preset doesn't touch self/DB — call unbound to avoid setup. + return MusicDatabase.get_quality_preset(None, name) + + +def _labels(profile): + return [t['label'] for t in profile['ranked_targets']] + + +def test_audiophile_is_strict_24bit_only(): + p = _preset('audiophile') + assert p['fallback_enabled'] is False + labels = _labels(p) + assert all('24-bit' in l for l in labels) # only 24-bit FLAC + assert 'FLAC 16-bit' not in labels + assert not any('MP3' in l for l in labels) + + +def test_balanced_still_includes_16bit_and_mp3(): + p = _preset('balanced') + labels = _labels(p) + assert 'FLAC 16-bit' in labels + assert any('MP3' in l for l in labels) + assert p['fallback_enabled'] is True