Skip to content

Commit

Permalink
RG type caption, re-analysis on dataSource change
Browse files Browse the repository at this point in the history
  • Loading branch information
kartik-venugopal committed Aug 22, 2024
1 parent 024dcc1 commit 383611c
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 65 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ extension FFmpegReplayGainScanner {
try self.ebur128.addFramesAsInt16(framesPointer: pointer, frameCount: frame.intSampleCount)
self.consecutiveErrors = 0

} catch let err as EBUR128Error {
print(err.description)

} catch {
print("Unknown error: \(error.localizedDescription)")

consecutiveErrors.increment()
print((error as? EBUR128Error)?.description ?? error.localizedDescription)
}
}
}
Expand All @@ -46,11 +45,10 @@ extension FFmpegReplayGainScanner {
try self.ebur128.addFramesAsInt32(framesPointer: pointer, frameCount: frame.intSampleCount)
self.consecutiveErrors = 0

} catch let err as EBUR128Error {
print(err.description)

} catch {
print("Unknown error: \(error.localizedDescription)")

consecutiveErrors.increment()
print((error as? EBUR128Error)?.description ?? error.localizedDescription)
}
}
}
Expand All @@ -67,11 +65,10 @@ extension FFmpegReplayGainScanner {
try self.ebur128.addFramesAsFloat(framesPointer: pointer, frameCount: frame.intSampleCount)
self.consecutiveErrors = 0

} catch let err as EBUR128Error {
print(err.description)

} catch {
print("Unknown error: \(error.localizedDescription)")

consecutiveErrors.increment()
print((error as? EBUR128Error)?.description ?? error.localizedDescription)
}
}
}
Expand All @@ -88,11 +85,10 @@ extension FFmpegReplayGainScanner {
try self.ebur128.addFramesAsDouble(framesPointer: pointer, frameCount: frame.intSampleCount)
self.consecutiveErrors = 0

} catch let err as EBUR128Error {
print(err.description)

} catch {
print("Unknown error: \(error.localizedDescription)")

consecutiveErrors.increment()
print((error as? EBUR128Error)?.description ?? error.localizedDescription)
}
}
}
Expand All @@ -115,7 +111,7 @@ extension FFmpegReplayGainScanner {

guard let pkt = try ctx.readPacket(from: stream) else {

consecutiveErrors += 1
consecutiveErrors.increment()
continue
}

Expand All @@ -142,16 +138,16 @@ extension FFmpegReplayGainScanner {

if !err.isEOF {

consecutiveErrors += 1
consecutiveErrors.increment()
print("Error: \(err.code.errorDescription)")
}
}
}

} catch {
print("Error: \(error)")
print("Error: \(error.localizedDescription)")
}

return isCancelled || consecutiveErrors >= 3 ? nil : try ebur128.analyze()
return isCancelled || (consecutiveErrors >= 3) || (!eof) ? nil : try ebur128.analyze()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class FFmpegReplayGainScanner: EBUR128LoudnessScannerProtocol {
self.ctx = try FFmpegFileContext(for: file)

guard let theAudioStream = ctx.bestAudioStream else {
throw FormatContextInitializationError(description: "\nUnable to find audio stream in file: '\(file.path)'")
throw FormatContextInitializationError(description: "Unable to find audio stream in file: '\(file.path)'")
}

self.stream = theAudioStream
Expand Down Expand Up @@ -95,11 +95,8 @@ class FFmpegReplayGainScanner: EBUR128LoudnessScannerProtocol {

completionHandler(result)

} catch let err as EBUR128Error {
print("Error: \(err.description)")

} catch {
print("Error: \(error)")
print((error as? EBUR128Error)?.description ?? error.localizedDescription)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,12 @@ class ReplayGainScanner {
cancelOngoingScan()

// First, check the cache
// if let theResult = cache[file] {
//
// // Cache hit
// print("\nReplayGainScanner.init() CACHE HIT !!! \(theResult.replayGain) for file \(file.lastPathComponent)")
// completionHandler(ReplayGain(ebur128AnalysisResult: theResult))
// return
// }

print("\nReplayGainScanner.init() CACHE MISS for file \(file.lastPathComponent)")
if let theResult = cache[file] {

// Cache hit
completionHandler(ReplayGain(ebur128AnalysisResult: theResult))
return
}

// Cache miss, initiate a scan

Expand All @@ -61,8 +58,6 @@ class ReplayGainScanner {
// will prevent rogue completion handler execution.
guard self?.scanOp == finishedScanOp else {return}

print("Finished ? \(finishedScanOp.isFinished)")

if let theResult = ebur128Result {

// Scan succeeded, cache the result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,25 +80,36 @@ class ReplayGainUnit: EffectsUnit, ReplayGainUnitProtocol {

let replayGainDB: Float?

lazy var albumGain = computedAlbumGain
lazy var trackGain = computedTrackGain

switch mode {

case .preferAlbumGain:
replayGainDB = computedAlbumGain ?? computedTrackGain

replayGainDB = albumGain ?? trackGain
appliedGainType = albumGain != nil ? .albumGain : (trackGain != nil ? .trackGain : nil)

case .preferTrackGain:
replayGainDB = computedTrackGain ?? computedAlbumGain

replayGainDB = trackGain ?? albumGain
appliedGainType = trackGain != nil ? .trackGain : (albumGain != nil ? .albumGain : nil)

case .trackGainOnly:
replayGainDB = computedTrackGain

replayGainDB = trackGain
appliedGainType = trackGain != nil ? .trackGain : nil
}

node.replayGain = replayGainDB ?? 0
}

var appliedGain: Float {
node.replayGain
var appliedGain: Float? {
self.replayGain == nil ? nil : node.replayGain
}

private(set) var appliedGainType: ReplayGainType? = nil

var effectiveGain: Float {
node.globalGain
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@

import Foundation

// TODO: Caching of ReplayGain scan data

class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUnitDelegateProtocol {

static let cache: ConcurrentMap<URL, EBUR128AnalysisResult> = ConcurrentMap()

var dataSource: ReplayGainDataSource {

get {unit.dataSource}
set {unit.dataSource = newValue}

set {
unit.dataSource = newValue
applyReplayGain(forTrack: playbackInfoDelegate.playingTrack)
}
}

var maxPeakLevel: ReplayGainMaxPeakLevel {
Expand All @@ -31,6 +33,11 @@ class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUni
var mode: ReplayGainMode {

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}
}

Expand All @@ -50,10 +57,14 @@ class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUni
unit.replayGain = replayGain
}

var appliedGain: Float {
var appliedGain: Float? {
unit.appliedGain
}

var appliedGainType: ReplayGainType? {
unit.appliedGainType
}

var hasAppliedGain: Bool {
unit.replayGain != nil
}
Expand Down Expand Up @@ -84,7 +95,6 @@ class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUni

// Has metadata
unit.replayGain = replayGain
print("Found RG metadata: \(replayGain.trackGain ?? -100) for \(theTrack)")

} else {

Expand All @@ -93,17 +103,12 @@ class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUni

// Analyze
analyze(file: theTrack.file)
print("No RG metadata for \(theTrack), analyzing ...")
}

case .metadataOnly:

print("Applying RG metadata: \(theTrack.replayGain?.trackGain ?? -100) for \(theTrack)")
unit.replayGain = theTrack.replayGain

case .analysisOnly:

print("Analyzing \(theTrack)")
analyze(file: theTrack.file)
}
}
Expand All @@ -128,7 +133,7 @@ class ReplayGainUnitDelegate: EffectsUnitDelegate<ReplayGainUnit>, ReplayGainUni
} catch {

_isScanning.setFalse()
print("Scan failed: \(error.localizedDescription)")
Messenger.publish(.Effects.ReplayGainUnit.scanCompleted)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ protocol ReplayGainUnitDelegateProtocol: EffectsUnitDelegateProtocol {

var preventClipping: Bool {get set}

var appliedGain: Float {get}
var appliedGain: Float? {get}

var appliedGainType: ReplayGainType? {get}

var dataSource: ReplayGainDataSource {get set}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ protocol ReplayGainUnitProtocol: EffectsUnitProtocol {

var preventClipping: Bool {get set}

var appliedGain: Float {get}
var appliedGain: Float? {get}

var appliedGainType: ReplayGainType? {get}

var effectiveGain: Float {get}

Expand Down Expand Up @@ -63,6 +65,15 @@ enum ReplayGainMode: Int, Codable {
}
}

enum ReplayGainType {

case albumGain, trackGain

var description: String {
self == .albumGain ? "Album gain" : "Track gain"
}
}

enum ReplayGainDataSource: Int, Codable {

case metadataOrAnalysis, metadataOnly, analysisOnly
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/FFmpeg/Utils/FFmpegDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class FFmpegDecoder {
self.fileCtx = fileContext

guard let theAudioStream = fileContext.bestAudioStream else {
throw FormatContextInitializationError(description: "\nUnable to find audio stream in file: '\(fileContext.filePath)'")
throw FormatContextInitializationError(description: "Unable to find audio stream in file: '\(fileContext.filePath)'")
}

self.stream = theAudioStream
Expand Down
14 changes: 5 additions & 9 deletions Source/UI/Effects/ReplayGain/ReplayGainUnitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,7 @@ class ReplayGainUnitViewController: EffectsUnitViewController {
preAmpSlider.floatValue = replayGainUnit.preAmp

if !replayGainUnit.isScanning {

if replayGainUnit.hasAppliedGain {
lblGain.stringValue = "\(String(format: "%.2f", replayGainUnit.appliedGain)) dB (\(replayGainUnit.mode.description))"

} else {
lblGain.stringValue = "<None>"
}
updateGainLabel()
}

lblPreAmp.stringValue = "\(String(format: "%.2f", replayGainUnit.preAmp)) dB"
Expand All @@ -101,8 +95,8 @@ class ReplayGainUnitViewController: EffectsUnitViewController {

private func updateGainLabel() {

if replayGainUnit.hasAppliedGain {
lblGain.stringValue = "\(String(format: "%.2f", replayGainUnit.appliedGain)) dB (\(replayGainUnit.mode.description))"
if let appliedGain = replayGainUnit.appliedGain, let appliedGainType = replayGainUnit.appliedGainType {
lblGain.stringValue = "\(String(format: "%.2f", appliedGain)) dB (\(appliedGainType.description))"

} else {
lblGain.stringValue = "<None>"
Expand Down Expand Up @@ -215,7 +209,9 @@ extension ReplayGainUnitViewController {
}

@IBAction func dataSourceAction(_ sender: NSMenuItem) {

replayGainUnit.dataSource = .init(rawValue: sender.tag) ?? .metadataOrAnalysis
updateGainLabel()
}

@IBAction func maxPeakLevelAction(_ sender: NSMenuItem) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class FFmpegWaveformDecoder: WaveformDecoderProtocol {
self.fileCtx = try FFmpegFileContext(for: file)

guard let theAudioStream = fileCtx.bestAudioStream else {
throw FormatContextInitializationError(description: "\nUnable to find audio stream in file: '\(fileCtx.filePath)'")
throw FormatContextInitializationError(description: "Unable to find audio stream in file: '\(fileCtx.filePath)'")
}

self.stream = theAudioStream
Expand Down

0 comments on commit 383611c

Please sign in to comment.