Enforce FLAC bit depth preference and prioritize audio quality in sorting

Two changes to the Soulseek quality filter:

1. Sort candidates by effective bitrate first, peer quality second.
Previously a 16-bit FLAC from a fast peer could beat a 24-bit FLAC
from a slower peer. Now highest audio quality always wins within the
same format tier, with peer speed as tiebreaker.

2. Enforce the FLAC bit depth UI preference (Any/16-bit/24-bit) that
was previously cosmetic-only. Uses effective bitrate threshold of
1450 kbps to distinguish 16-bit (<1411 kbps theoretical) from 24-bit
(>2116 kbps theoretical). Respects the bit_depth_fallback toggle —
when enabled, gracefully accepts any FLAC if preferred depth is
unavailable. When disabled, strictly rejects non-matching depth.

Default bit_depth="any" — zero behavior change for existing users.
pull/253/head
Broque Thomas 2 weeks ago
parent cb008a2e61
commit 6820e2d4e3

@ -1617,14 +1617,49 @@ class SoulseekClient:
else:
logger.debug(f"Quality Filter: {quality_key} rejected via size fallback - {file_size_mb:.1f} MB outside {size_min}-{size_max} MB safety limits")
# Sort each bucket by quality score and effective bitrate
# Sort each bucket: effective bitrate first (prefer highest audio quality),
# then peer quality score as tiebreaker (prefer fastest peer at same quality)
for bucket in quality_buckets.values():
bucket.sort(key=lambda x: (x.quality_score, self._calculate_effective_kbps(x.size, x.duration) or 0), reverse=True)
bucket.sort(key=lambda x: (self._calculate_effective_kbps(x.size, x.duration) or 0, x.quality_score), reverse=True)
# Enforce FLAC bit depth preference from quality profile
flac_config = profile['qualities'].get('flac', {})
bit_depth_pref = flac_config.get('bit_depth', 'any')
bit_depth_fallback = flac_config.get('bit_depth_fallback', True)
if bit_depth_pref != 'any' and quality_buckets['flac']:
# 16-bit/44.1kHz FLAC theoretical max is 1411 kbps; 24-bit starts at ~2116 kbps
# Real-world compressed: 16-bit = 800-1400 kbps, 24-bit = 1500+ kbps
DEPTH_THRESHOLD = 1450
if bit_depth_pref == '24':
hi_res = [c for c in quality_buckets['flac']
if (self._calculate_effective_kbps(c.size, c.duration) or 0) > DEPTH_THRESHOLD]
if hi_res:
logger.info(f"Quality Filter: Bit depth 24-bit preference — {len(hi_res)}/{len(quality_buckets['flac'])} FLAC candidates are hi-res")
quality_buckets['flac'] = hi_res
elif not bit_depth_fallback:
logger.info(f"Quality Filter: No 24-bit FLAC found and fallback disabled — rejecting all FLAC")
quality_buckets['flac'] = []
else:
logger.info(f"Quality Filter: No 24-bit FLAC found — falling back to 16-bit")
elif bit_depth_pref == '16':
lo_res = [c for c in quality_buckets['flac']
if (self._calculate_effective_kbps(c.size, c.duration) or 0) <= DEPTH_THRESHOLD]
if lo_res:
logger.info(f"Quality Filter: Bit depth 16-bit preference — {len(lo_res)}/{len(quality_buckets['flac'])} FLAC candidates are standard")
quality_buckets['flac'] = lo_res
elif not bit_depth_fallback:
logger.info(f"Quality Filter: No 16-bit FLAC found and fallback disabled — rejecting all FLAC")
quality_buckets['flac'] = []
else:
logger.info(f"Quality Filter: No 16-bit FLAC found — falling back to 24-bit")
# Debug logging
for quality, bucket in quality_buckets.items():
if bucket:
logger.debug(f"Quality Filter: Found {len(bucket)} '{quality}' candidates (after bitrate filtering)")
logger.debug(f"Quality Filter: Found {len(bucket)} '{quality}' candidates (after bitrate + bit depth filtering)")
# Waterfall priority logic: try qualities in priority order
# Build priority list from enabled qualities

Loading…
Cancel
Save