Skip to content

Commit

Permalink
#12 Show RG info in Track Info module
Browse files Browse the repository at this point in the history
  • Loading branch information
kartik-venugopal committed Aug 24, 2024
1 parent ca414c1 commit f85ee91
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 44 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class ReplayGainScanner {
print("ReplayGainScanner.init() read \(self.trackGainCache.count) trackGain cache entries and \(self.albumGainCache.count) albumGain cache entries.")
}

func cachedReplayGainData(forTrack track: Track) -> ReplayGain? {
trackGainCache[track.file]
}

func scanTrack(file: URL, _ completionHandler: @escaping ReplayGainScanCompletionHandler) {

cancelOngoingScan()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,10 @@ class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUni

get {unit.mode}

// TODO: When the mode changes, if effective dataSource == .analysis and
// changing from album gain to track gain, need to perform a scan

// TODO: If dataSource == analysis and new mode is albumGain, perform an album scan
set {unit.mode = newValue}
set {
unit.mode = newValue
applyReplayGain(forTrack: playbackInfoDelegate.playingTrack)
}
}

var preAmp: Float {
Expand Down Expand Up @@ -118,22 +117,9 @@ class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUni
switch unit.mode {

case .preferAlbumGain:
return replayGain.albumGain != nil && (preventClipping ? replayGain.albumPeak != nil : true)

if preventClipping {
return replayGain.albumGain != nil ? replayGain.albumPeak != nil : replayGain.trackPeak != nil
}

return true

case .preferTrackGain:

if preventClipping {
return replayGain.trackGain != nil ? replayGain.trackPeak != nil : replayGain.albumPeak != nil
}

return true

case .trackGainOnly:
case .preferTrackGain, .trackGainOnly:
return replayGain.trackGain != nil && (preventClipping ? replayGain.trackPeak != nil : true)
}
}
Expand Down
9 changes: 7 additions & 2 deletions Source/Core/TrackIO/AVFoundation/Parsers/ID3AVFParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,13 @@ class ID3AVFParser: AVFMetadataParser {
if replaceableKeyFields.contains(key), let attrs = item.extraAttributes, !attrs.isEmpty {

// TXXX or COMM or WXXX
if let infoKey = mapReplaceableKeyField(attrs), !String.isEmpty(infoKey), !infoKey.lowercased().hasPrefix("replaygain") {
entryKey = infoKey
if let infoKey = attrs[.key_info] as? String, !String.isEmpty(infoKey) {

if infoKey.lowercased().hasPrefix("replaygain") {
continue
} else {
entryKey = infoKey
}
}

} else if keys_GEOB.contains(key), let attrs = item.extraAttributes, !attrs.isEmpty {
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/TrackIO/Model/AudioInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ struct AudioInfo {
// A description of the channel layout, eg. "5.1 Surround".
var channelLayout: String?

var replayGain: ReplayGain?
var replayGainFromMetadata: ReplayGain?
var replayGainFromAnalysis: ReplayGain?
}
1 change: 0 additions & 1 deletion Source/Core/TrackIO/Model/AuxiliaryMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@ import Foundation
///
struct AuxiliaryMetadata {

var fileSystemInfo: FileSystemInfo?
var audioInfo: AudioInfo?
}
9 changes: 2 additions & 7 deletions Source/Core/TrackIO/Model/Track.swift
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,10 @@ class Track: Hashable, PlaylistItem, PlayableItem {
}
}

func setAuxiliaryMetadata(_ metadata: AuxiliaryMetadata) {

// self.auxiliaryMetadata = metadata
self.audioInfo = metadata.audioInfo
self.auxMetadataLoaded = true
func setAudioInfo(_ audioInfo: AudioInfo) {
self.audioInfo = audioInfo
}

var auxMetadataLoaded: Bool = false

static func == (lhs: Track, rhs: Track) -> Bool {
return lhs.file == rhs.file
}
Expand Down
18 changes: 13 additions & 5 deletions Source/Core/TrackIO/TrackReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,19 @@ class TrackReader {
///
func loadAuxiliaryMetadata(for track: Track) {

if track.auxMetadataLoaded {return}
if track.audioInfo == nil {

let auxMetadata = fileReader.getAuxiliaryMetadata(for: track.file, loadingAudioInfoFrom: track.playbackContext)

if var audioInfo = auxMetadata.audioInfo {

audioInfo.replayGainFromMetadata = track.replayGain
track.setAudioInfo(audioInfo)
}

loadArtAsync(for: track)
}

let auxMetadata = fileReader.getAuxiliaryMetadata(for: track.file,
loadingAudioInfoFrom: track.playbackContext)
track.setAuxiliaryMetadata(auxMetadata)
loadArtAsync(for: track)
track.audioInfo?.replayGainFromAnalysis = replayGainScanner.cachedReplayGainData(forTrack: track)
}
}
57 changes: 49 additions & 8 deletions Source/UI/TrackInfo/Audio/AudioTrackInfoSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@ class AudioTrackInfoSource: TrackInfoSource {

trackInfo.removeAll()

let audioInfo = track.audioInfo

trackInfo.append(KeyValuePair(key: "Format",
value: track.audioInfo?.format?.capitalizingFirstLetter() ?? TrackInfoConstants.value_unknown))
value: audioInfo?.format?.capitalizingFirstLetter() ?? TrackInfoConstants.value_unknown))

if let codec = track.audioInfo?.codec {
if let codec = audioInfo?.codec {
trackInfo.append(KeyValuePair(key: "Codec", value: codec))
}

trackInfo.append(KeyValuePair(key: "Duration",
value: ValueFormatter.formatSecondsToHMS(track.duration)))

if let bitRate = track.audioInfo?.bitRate {
if let bitRate = audioInfo?.bitRate {

if bitRate < 1000 {
trackInfo.append(KeyValuePair(key: "Bit Rate",
Expand All @@ -48,7 +50,7 @@ class AudioTrackInfoSource: TrackInfoSource {
trackInfo.append(KeyValuePair(key: "Bit Rate", value: TrackInfoConstants.value_unknown))
}

if let sampleRate = track.audioInfo?.sampleRate {
if let sampleRate = audioInfo?.sampleRate {

trackInfo.append(KeyValuePair(key: "Sample Rate",
value: String(format: "%@ Hz", ValueFormatter.readableLongInteger(Int64(sampleRate)))))
Expand All @@ -57,15 +59,15 @@ class AudioTrackInfoSource: TrackInfoSource {
trackInfo.append(KeyValuePair(key: "Sample Rate", value: TrackInfoConstants.value_unknown))
}

if let sampleFormat = track.audioInfo?.sampleFormat {
if let sampleFormat = audioInfo?.sampleFormat {
trackInfo.append(KeyValuePair(key: "Sample Format", value: sampleFormat))
}

if let layout = track.audioInfo?.channelLayout {
if let layout = audioInfo?.channelLayout {
trackInfo.append(KeyValuePair(key: "Channel Layout", value: layout.capitalized))
} else {

if let numChannels = track.audioInfo?.numChannels {
if let numChannels = audioInfo?.numChannels {

trackInfo.append(KeyValuePair(key: "Channel Layout",
value: channelLayout(numChannels)))
Expand All @@ -74,13 +76,52 @@ class AudioTrackInfoSource: TrackInfoSource {
}
}

if let frameCount = track.audioInfo?.frames {
if let frameCount = audioInfo?.frames {

trackInfo.append(KeyValuePair(key: "Frames",
value: ValueFormatter.readableLongInteger(frameCount)))
} else {
trackInfo.append(KeyValuePair(key: "Frames", value: TrackInfoConstants.value_unknown))
}

if let replayGain = audioInfo?.replayGainFromMetadata {

let hasAnalysisData: Bool = audioInfo?.replayGainFromAnalysis != nil

trackInfo.append(KeyValuePair(key: "Replay Gain\(hasAnalysisData ? " (from metadata)" : "")",
value: replayGainString(for: replayGain)))
}

if let replayGain = audioInfo?.replayGainFromAnalysis {

let hasMetadata: Bool = audioInfo?.replayGainFromMetadata != nil

trackInfo.append(KeyValuePair(key: "Replay Gain\(hasMetadata ? " (from analysis)" : "")",
value: replayGainString(for: replayGain)))
}
}

private func replayGainString(for replayGain: ReplayGain) -> String {

var lines: [String] = []

if let trackGain = replayGain.trackGain {
lines.append("Track gain: \(String(format: "%.2f dB", trackGain))")
}

if let trackPeak = replayGain.trackPeak {
lines.append("Track peak: \(String(format: "%.2f", trackPeak))")
}

if let albumGain = replayGain.albumGain {
lines.append("Album gain: \(String(format: "%.2f dB", albumGain))")
}

if let albumPeak = replayGain.albumPeak {
lines.append("Album peak: \(String(format: "%.2f", albumPeak))")
}

return lines.joined(separator: "\n")
}

private func channelLayout(_ numChannels: Int) -> String {
Expand Down

0 comments on commit f85ee91

Please sign in to comment.