From 3df84f81e73fee8f8c8b3f617f0f7c46d3ff9ce3 Mon Sep 17 00:00:00 2001 From: vicrodh <103399283+vicrodh@users.noreply.github.com> Date: Mon, 6 Apr 2026 15:07:41 -0600 Subject: [PATCH] fix(quality): request track's actual quality instead of always UltraHiRes playTrack() was always sending the user's max quality setting (Hi-Res+) regardless of what the track actually offers. A 44.1kHz/24bit track would trigger 3 API fallback calls (UltraHiRes -> HiRes -> Lossless) and the cache was discarded as "lower quality" for re-download. New effectiveQuality() picks the minimum of user max and track metadata (bit_depth + sampling_rate), so a 24bit/96kHz track requests Hi-Res directly (1 API call) and cache matches perfectly. cc --- src/lib/services/playbackService.ts | 40 ++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/lib/services/playbackService.ts b/src/lib/services/playbackService.ts index 03764a747..bc08bff56 100644 --- a/src/lib/services/playbackService.ts +++ b/src/lib/services/playbackService.ts @@ -26,6 +26,44 @@ function getStreamingQuality(): string { if (typeof localStorage === 'undefined') return 'Hi-Res+'; return getUserItem('qbz-streaming-quality') || 'Hi-Res+'; } + +/** Quality tier ordering for min() comparison */ +const QUALITY_RANK: Record = { + 'MP3': 0, + 'CD Quality': 1, + 'Hi-Res': 2, + 'Hi-Res+': 3, +}; + +/** + * Determine the optimal quality for a track: the minimum of what the track + * offers and what the user's max setting allows. Avoids requesting UltraHiRes + * for a 44.1kHz/24bit track (which would cascade through API quality fallbacks). + */ +function effectiveQuality(track: PlayingTrack): string { + const userMax = getStreamingQuality(); + + // If no track metadata, use user preference + if (!track.bitDepth && !track.samplingRate) return userMax; + + // Determine what the track actually offers + let trackQuality: string; + const bd = track.bitDepth ?? 16; + const sr = track.samplingRate ?? 44.1; // kHz + + if (bd >= 24 && sr > 96) { + trackQuality = 'Hi-Res+'; + } else if (bd >= 24) { + trackQuality = 'Hi-Res'; + } else { + trackQuality = 'CD Quality'; + } + + // Return the lower of user max and track max + const userRank = QUALITY_RANK[userMax] ?? 3; + const trackRank = QUALITY_RANK[trackQuality] ?? 3; + return userRank <= trackRank ? userMax : trackQuality; +} import { setCurrentTrack, setIsPlaying, @@ -214,7 +252,7 @@ export async function playTrack( } else { const result = await invoke('v2_play_track', { trackId: track.id, - quality: getStreamingQuality(), + quality: effectiveQuality(track), durationSecs: track.duration ? Math.round(track.duration) : null, forceLowestQuality: forceLowestQuality || null });