Fix audio sample rate label dropping the kHz decimal (#964)

MPVTrack.detailText built its sample-rate label with integer division
(`sampleRate / 1000`), which truncates the fractional kHz. The
second-most-common audio rate — 44100 Hz (CD quality, music videos) —
showed as "44 kHz", a label that denotes 44000 Hz (a different rate),
instead of the conventional "44.1 kHz" used by VLC, mpv and every DAW.
The same defect hit 88200 -> "88 kHz", 176400 -> "176 kHz" and
22050 -> "22 kHz". Whole-kHz rates (48000, 96000, ...) were already
correct and stay unchanged. The label is live in the quality selector's
advanced details, where EmbeddedTrackRowView renders track.detailText.

- Factor the formatting into MPVTrack.formatSampleRate(_:), a pure
  static helper: divide as Double, drop the decimal for whole kHz,
  otherwise keep 1-2 meaningful digits with the trailing zero stripped
  (44.1, 88.2, 22.05).
- detailText now appends Self.formatSampleRate(sampleRate); its structure
  (codec / channelCount parts, separator, nil-when-empty) is unchanged.
- Add YatteeTests/MPVTrackFormatTests covering whole-kHz rates, the
  44.1 kHz family (the bug), half-decimal rates and the detailText
  integration.
This commit is contained in:
Yuri Chukhlib
2026-08-23 12:21:57 +02:00
committed by GitHub
parent 11d370b3b8
commit 6c5c9915fe
2 changed files with 63 additions and 2 deletions

View File

@@ -148,7 +148,24 @@ struct MPVTrack: Equatable, Sendable, Identifiable, Decodable {
return preferred == baseLanguageCode
}
/// Secondary detail line for advanced mode, e.g. "eac3 · 6ch · 48 kHz".
/// Format a sample rate in Hz as the conventional kHz label.
/// 48000 "48 kHz", 44100 "44.1 kHz", 88200 "88.2 kHz",
/// 22050 "22.05 kHz", 176400 "176.4 kHz".
/// Whole-kHz rates drop the decimal; fractional rates keep their
/// meaningful digits (12 decimals, trailing zero stripped).
static func formatSampleRate(_ hz: Int) -> String {
let kHz = Double(hz) / 1000.0
if kHz == kHz.rounded() {
return "\(Int(kHz)) kHz"
}
var label = String(format: "%.2f", kHz)
if label.hasSuffix("0") {
label.removeLast()
}
return "\(label) kHz"
}
/// Secondary detail line for advanced mode, e.g. "aac · 2ch · 44.1 kHz".
var detailText: String? {
var parts: [String] = []
if let codec, !codec.isEmpty {
@@ -158,7 +175,7 @@ struct MPVTrack: Equatable, Sendable, Identifiable, Decodable {
parts.append("\(channelCount)ch")
}
if let sampleRate {
parts.append("\(sampleRate / 1000) kHz")
parts.append(Self.formatSampleRate(sampleRate))
}
return parts.isEmpty ? nil : parts.joined(separator: " · ")
}