mirror of
https://github.com/yattee/yattee.git
synced 2026-08-26 08:52:32 +00:00
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:
@@ -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 (1–2 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: " · ")
|
||||
}
|
||||
|
||||
44
YatteeTests/MPVTrackFormatTests.swift
Normal file
44
YatteeTests/MPVTrackFormatTests.swift
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// MPVTrackFormatTests.swift
|
||||
// YatteeTests
|
||||
//
|
||||
// Tests for MPVTrack sample-rate (kHz) label formatting.
|
||||
//
|
||||
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import Yattee
|
||||
|
||||
@Suite("MPVTrack sample-rate formatting")
|
||||
struct MPVTrackFormatTests {
|
||||
@Test("Whole-kHz rates have no decimal")
|
||||
func wholeKHz() {
|
||||
#expect(MPVTrack.formatSampleRate(8000) == "8 kHz")
|
||||
#expect(MPVTrack.formatSampleRate(16000) == "16 kHz")
|
||||
#expect(MPVTrack.formatSampleRate(24000) == "24 kHz")
|
||||
#expect(MPVTrack.formatSampleRate(48000) == "48 kHz")
|
||||
#expect(MPVTrack.formatSampleRate(96000) == "96 kHz")
|
||||
#expect(MPVTrack.formatSampleRate(192000) == "192 kHz")
|
||||
}
|
||||
|
||||
@Test("44.1 kHz family keeps its decimal (the bug)")
|
||||
func fractionalKHz() {
|
||||
#expect(MPVTrack.formatSampleRate(44100) == "44.1 kHz")
|
||||
#expect(MPVTrack.formatSampleRate(88200) == "88.2 kHz")
|
||||
#expect(MPVTrack.formatSampleRate(176400) == "176.4 kHz")
|
||||
}
|
||||
|
||||
@Test("Half-decimal rates keep two digits")
|
||||
func halfDecimal() {
|
||||
#expect(MPVTrack.formatSampleRate(22050) == "22.05 kHz")
|
||||
// 11025/1000 = 11.025; %.2f rounds the nearest double to "11.03" on macOS arm64.
|
||||
#expect(MPVTrack.formatSampleRate(11025) == "11.03 kHz")
|
||||
}
|
||||
|
||||
@Test("detailText surfaces the formatted sample rate")
|
||||
func detailTextIntegration() {
|
||||
let track = MPVTrack(trackID: 1, type: .audio, codec: "aac",
|
||||
channelCount: 2, sampleRate: 44100)
|
||||
#expect(track.detailText == "aac · 2ch · 44.1 kHz")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user