Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Sources/SwiftTimecodeCore/Documentation.docc/Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ Value types and related logic for representing and working with SMPTE/EBU timeco
### Additional Value Types

- ``FeetAndFrames``

### Cross-Platform Types

- ``PlatformInt``
2 changes: 1 addition & 1 deletion Sources/SwiftTimecodeCore/Fraction/Fraction CMTime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extension Fraction {
return
}

self.init(Int(cmTime.value), Int(cmTime.timescale))
self.init(PlatformInt(cmTime.value), PlatformInt(cmTime.timescale))
}

/// Returns the fraction as a new `CMTime` instance.
Expand Down
34 changes: 17 additions & 17 deletions Sources/SwiftTimecodeCore/Fraction/Fraction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import Foundation
///
/// Used to convert to/from ``Timecode``, Core Media `CMTime`, or metadata encoding such as Final Cut Pro XML or AAF.
public struct Fraction {
public let numerator: Int
public let denominator: Int
public let numerator: PlatformInt
public let denominator: PlatformInt

private let _isReduced: Bool?

Expand Down Expand Up @@ -40,14 +40,14 @@ public struct Fraction {
// MARK: - Init

/// Initialize with literal values.
public init(_ numerator: Int, _ denominator: Int) {
public init(_ numerator: PlatformInt, _ denominator: PlatformInt) {
self.numerator = numerator
self.denominator = denominator
_isReduced = nil
}

/// Initialize by reducing and normalizing the fraction.
public init(reducing numerator: Int, _ denominator: Int) {
public init(reducing numerator: PlatformInt, _ denominator: PlatformInt) {
let reduced = reduce(n: numerator, d: denominator)
self.numerator = reduced.n
self.denominator = reduced.d
Expand All @@ -66,7 +66,7 @@ public struct Fraction {
}

/// Internal: Initialize with literal values and force the reduced flag.
init(_ numerator: Int, _ denominator: Int, isReduced: Bool?) {
init(_ numerator: PlatformInt, _ denominator: PlatformInt, isReduced: Bool?) {
self.numerator = numerator
self.denominator = denominator
_isReduced = isReduced
Expand Down Expand Up @@ -253,10 +253,10 @@ extension Double {
// clamp exponent to avoid overflow crashes
// Int.max = 9.22... x 10^18
let maxExponent = precision.clamped(to: 0 ... max(19 - integralDigitPlaces, 0))
let pad = Int(truncating: pow(10, maxExponent) as NSNumber)
let pad = PlatformInt(truncating: pow(10, maxExponent) as NSNumber)
let nFloat = absSelf * Double(pad)

let n = Int(truncating: nFloat as NSNumber)
let n = PlatformInt(truncating: nFloat as NSNumber)
let d = pad

return Fraction(reducing: isNegative ? -n : n, d)
Expand Down Expand Up @@ -285,7 +285,7 @@ extension Fraction {
if wholeSecsMatches.count == 3 {
let negativeSign = wholeSecsMatches[1] ?? ""
if let secondsString = wholeSecsMatches[2],
let seconds = Int(negativeSign + secondsString)
let seconds = PlatformInt(negativeSign + secondsString)
{
self.init(seconds, 1, isReduced: true)
return
Expand All @@ -298,9 +298,9 @@ extension Fraction {
if fracMatches.count == 4 {
let negativeSign = fracMatches[1] ?? ""
if let numeratorString = fracMatches[2],
let numerator = Int(negativeSign + numeratorString),
let numerator = PlatformInt(negativeSign + numeratorString),
let denominatorString = fracMatches[3],
let denominator = Int(denominatorString)
let denominator = PlatformInt(denominatorString)
{
self.init(numerator, denominator)
return
Expand Down Expand Up @@ -337,7 +337,7 @@ extension Fraction {
/// Normalize a fraction.
/// Fractions with two negative signs are normalized to two positive signs.
/// Fractions with negative denominator are normalized to negative numerator and positive denominator.
func normalize(n: Int, d: Int) -> (n: Int, d: Int) {
func normalize(n: PlatformInt, d: PlatformInt) -> (n: PlatformInt, d: PlatformInt) {
var n = n
var d = d
if n >= 0 && d >= 0 { return (n: n, d: d) }
Expand All @@ -351,9 +351,9 @@ func normalize(n: Int, d: Int) -> (n: Int, d: Int) {
/// Internal:
/// Reduce a fraction to its simplest form.
/// This also normalizes signs.
func reduce(n: Int, d: Int) -> (n: Int, d: Int) {
let (absN, signN) = n < 0 ? (-n, -1) : (n, 1)
let (absD, signD) = d < 0 ? (-d, -1) : (d, 1)
func reduce(n: PlatformInt, d: PlatformInt) -> (n: PlatformInt, d: PlatformInt) {
let (absN, signN): (PlatformInt, PlatformInt) = n < 0 ? (-n, -1) : (n, 1)
let (absD, signD): (PlatformInt, PlatformInt) = d < 0 ? (-d, -1) : (d, 1)
var v = n
var u = d

Expand All @@ -376,8 +376,8 @@ func reduce(n: Int, d: Int) -> (n: Int, d: Int) {

/// Internal:
/// Returns greatest common divisor of two numbers.
func greatestCommonDivisor(_ n1: Int, _ n2: Int) -> Int {
var x = 0
func greatestCommonDivisor(_ n1: PlatformInt, _ n2: PlatformInt) -> PlatformInt {
var x: PlatformInt = 0
var y = max(n1, n2)
var z = min(n1, n2)

Expand All @@ -392,7 +392,7 @@ func greatestCommonDivisor(_ n1: Int, _ n2: Int) -> Int {

/// Internal:
/// Returns least common multiple of two numbers and their respective multipliers.
func leastCommonMultiple(lhs: Int, rhs: Int) -> (denominator: Int, lhsMultiplier: Int, rhsMultiplier: Int) {
func leastCommonMultiple(lhs: PlatformInt, rhs: PlatformInt) -> (denominator: PlatformInt, lhsMultiplier: PlatformInt, rhsMultiplier: PlatformInt) {
let denominator = lhs * rhs / greatestCommonDivisor(lhs, rhs)
let lhsMultiplier = denominator / lhs
let rhsMultiplier = denominator / rhs
Expand Down
20 changes: 10 additions & 10 deletions Sources/SwiftTimecodeCore/Timecode/FrameCount/FrameCount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ extension Timecode {

extension Timecode.FrameCount {
init(
subFrameCount: Int,
subFrameCount: PlatformInt,
base: Timecode.SubFramesBase
) {
let converted = Timecode.subFramesToFrames(
Expand Down Expand Up @@ -225,7 +225,7 @@ extension Timecode.FrameCount {
public func multiplying(by factor: Double) -> Self {
let lhsTotalSubFrames = subFrameCount

let resultSubFrameCount = Int(Double(lhsTotalSubFrames) * factor)
let resultSubFrameCount = PlatformInt(Double(lhsTotalSubFrames) * factor)

let newFrames = Timecode.subFramesToFrames(
resultSubFrameCount,
Expand All @@ -241,7 +241,7 @@ extension Timecode.FrameCount {
public func dividing(by divisor: Double) -> Self {
let lhsTotalSubFrames = subFrameCount

let resultSubFrameCount = Int(Double(lhsTotalSubFrames) / divisor)
let resultSubFrameCount = PlatformInt(Double(lhsTotalSubFrames) / divisor)

let newFrames = Timecode.subFramesToFrames(
resultSubFrameCount,
Expand All @@ -268,7 +268,7 @@ extension Timecode.FrameCount {
}

extension Timecode.FrameCount {
var subFrameCount: Int {
var subFrameCount: PlatformInt {
Timecode.framesToSubFrames(
frames: wholeFrames,
subFrames: subFrames,
Expand All @@ -285,15 +285,15 @@ extension Timecode {
frames: Int,
subFrames: Int,
base: SubFramesBase
) -> Int {
(frames * base.rawValue) + subFrames
) -> PlatformInt {
(PlatformInt(frames) * PlatformInt(base.rawValue)) + PlatformInt(subFrames)
}

/// Internal utility
static func subFramesToFrames(_ subFrames: Int, base: SubFramesBase) -> (frames: Int, subFrames: Int) {
let outSubFrames = subFrames % base.rawValue
let outFrames = (subFrames - outSubFrames) / base.rawValue
static func subFramesToFrames(_ subFrames: PlatformInt, base: SubFramesBase) -> (frames: Int, subFrames: Int) {
let outSubFrames = subFrames % PlatformInt(base.rawValue)
let outFrames = (subFrames - outSubFrames) / PlatformInt(base.rawValue)

return (frames: outFrames, subFrames: outSubFrames)
return (frames: Int(outFrames), subFrames: Int(outSubFrames))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ extension Timecode {
if sfcNew > Double(maxSubFrameCountExpressible) { return nil }

let fcNew = FrameCount(
subFrameCount: Int(sfcNew),
subFrameCount: PlatformInt(sfcNew),
base: subFramesBase
)

Expand All @@ -333,7 +333,7 @@ extension Timecode {
base: subFramesBase
)

var sfcNew = Int(Double(fcOrigin.subFrameCount) * factor)
var sfcNew = PlatformInt(Double(fcOrigin.subFrameCount) * factor)

sfcNew = sfcNew.clamped(to: 0 ... maxSubFrameCountExpressible)

Expand All @@ -360,7 +360,7 @@ extension Timecode {
base: subFramesBase
)

var sfcNew = Int(Double(fcOrigin.subFrameCount) * factor)
var sfcNew = PlatformInt(Double(fcOrigin.subFrameCount) * factor)

let maxTotalSubFrames = frameRate.maxTotalSubFrames(
in: upperLimit,
Expand Down Expand Up @@ -401,7 +401,7 @@ extension Timecode {
base: subFramesBase
)

let sfcNew = Int(Double(fcOrigin.subFrameCount) * factor)
let sfcNew = PlatformInt(Double(fcOrigin.subFrameCount) * factor)

let fcNew = FrameCount(
subFrameCount: sfcNew,
Expand Down Expand Up @@ -434,7 +434,7 @@ extension Timecode {
if sfcNew > Double(maxSubFrameCountExpressible) { return nil }

let fcNew = FrameCount(
subFrameCount: Int(sfcNew),
subFrameCount: PlatformInt(sfcNew),
base: subFramesBase
)

Expand All @@ -456,7 +456,7 @@ extension Timecode {
base: subFramesBase
)

var sfcNew = Int(Double(fcOrigin.subFrameCount) / divisor)
var sfcNew = PlatformInt(Double(fcOrigin.subFrameCount) / divisor)

sfcNew = sfcNew.clamped(to: 0 ... maxSubFrameCountExpressible)

Expand All @@ -483,7 +483,7 @@ extension Timecode {
base: subFramesBase
)

var sfcNew = Int(Double(fcOrigin.subFrameCount) / divisor)
var sfcNew = PlatformInt(Double(fcOrigin.subFrameCount) / divisor)

let maxTotalSubFrames = frameRate.maxTotalSubFrames(
in: upperLimit,
Expand Down Expand Up @@ -524,7 +524,7 @@ extension Timecode {
base: subFramesBase
)

let sfcNew = Int(Double(fcOrigin.subFrameCount) / divisor)
let sfcNew = PlatformInt(Double(fcOrigin.subFrameCount) / divisor)

let fcNew = FrameCount(
subFrameCount: sfcNew,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ extension Timecode {
///
/// - Throws: ``ValidationError``
mutating func _setTimecode(exactly: CMTime) throws {
let fraction = Fraction(Int(exactly.value), Int(exactly.timescale))
let fraction = Fraction(PlatformInt(exactly.value), PlatformInt(exactly.timescale))
try _setTimecode(exactly: fraction)
}

Expand All @@ -92,7 +92,7 @@ extension Timecode {
/// - Note: Many AVFoundation and Core Media objects utilize `CMTime` as a way to represent
/// times and durations.
mutating func _setTimecode(clamping cmTime: CMTime) {
let fraction = Fraction(Int(cmTime.value), Int(cmTime.timescale))
let fraction = Fraction(PlatformInt(cmTime.value), PlatformInt(cmTime.timescale))
_setTimecode(clamping: fraction)
}

Expand All @@ -103,7 +103,7 @@ extension Timecode {
/// - Note: Many AVFoundation and Core Media objects utilize `CMTime` as a way to represent
/// times and durations.
mutating func _setTimecode(wrapping cmTime: CMTime) {
let fraction = Fraction(Int(cmTime.value), Int(cmTime.timescale))
let fraction = Fraction(PlatformInt(cmTime.value), PlatformInt(cmTime.timescale))
_setTimecode(wrapping: fraction)
}

Expand All @@ -114,7 +114,7 @@ extension Timecode {
/// - Note: Many AVFoundation and Core Media objects utilize `CMTime` as a way to represent
/// times and durations.
mutating func _setTimecode(rawValues cmTime: CMTime) {
let fraction = Fraction(Int(cmTime.value), Int(cmTime.timescale))
let fraction = Fraction(PlatformInt(cmTime.value), PlatformInt(cmTime.timescale))
_setTimecode(rawValues: fraction)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extension TimecodeSourceValue {
}

/// Numerical fraction containing a numerator and a denominator.
public static func rational(_ numerator: Int, _ denominator: Int) -> Self {
public static func rational(_ numerator: PlatformInt, _ denominator: PlatformInt) -> Self {
.init(value: Fraction(numerator, denominator))
}
}
Expand All @@ -51,7 +51,7 @@ extension Timecode {
public var rationalValue: Fraction {
let frFrac = frameRate.frameDuration
let n = frFrac.numerator * frameCount.subFrameCount
let d = frFrac.denominator * subFramesBase.rawValue
let d = frFrac.denominator * PlatformInt(subFramesBase.rawValue)

return Fraction(n, d).reduced()
}
Expand Down Expand Up @@ -85,7 +85,7 @@ extension Timecode {
/// fractions.)
mutating func _setTimecode(clamping rational: Fraction) {
let frameCount = frameCount(of: rational)
_setTimecode(clamping: .frames(frameCount))
_setTimecode(clamping: .frames(Int(clamping: frameCount)))
}

/// Sets the timecode from elapsed time expressed as a rational fraction.
Expand All @@ -98,7 +98,7 @@ extension Timecode {
/// fractions.)
mutating func _setTimecode(wrapping rational: Fraction) {
let frameCount = frameCount(of: rational)
_setTimecode(wrapping: .frames(frameCount))
_setTimecode(wrapping: .frames(Int(clamping: frameCount)))
}

/// Sets the timecode from elapsed time expressed as a rational fraction.
Expand All @@ -111,15 +111,15 @@ extension Timecode {
/// fractions.)
mutating func _setTimecode(rawValues rational: Fraction) {
let frameCount = frameCount(of: rational)
_setTimecode(rawValues: .frames(frameCount))
_setTimecode(rawValues: .frames(Int(clamping: frameCount)))
}

// MARK: Helper Methods

/// Internal:
/// Returns frame count of the rational fraction at current frame rate.
/// Truncates subframes if present.
func frameCount(of rational: Fraction) -> Int {
func frameCount(of rational: Fraction) -> PlatformInt {
let frFrac = frameRate.frameDuration
let frameCount = (rational.numerator * frFrac.denominator) /
(rational.denominator * frFrac.numerator)
Expand Down
10 changes: 6 additions & 4 deletions Sources/SwiftTimecodeCore/Timecode/Source/Timecode Samples.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ extension SamplesPayload: _TimecodeSource {

extension TimecodeSourceValue {
/// Audio samples at a given sample rate.
public static func samples(_ samples: Int, sampleRate: Int) -> Self {
public static func samples(_ samples: PlatformInt, sampleRate: Int) -> Self {
.init(value: SamplesPayload(samples: Double(samples), sampleRate: sampleRate))
}

// Disfavored overload avoids type ambiguity at call-site for integer literals on 32-bit platforms.
/// Audio samples at a given sample rate.
@_disfavoredOverload
public static func samples(_ samples: Double, sampleRate: Int) -> Self {
.init(value: SamplesPayload(samples: samples, sampleRate: sampleRate))
}
Expand All @@ -51,14 +53,14 @@ extension Timecode {
/// Returns the current timecode converted to a duration in audio samples
/// at the given sample rate, rounded to the nearest sample.
/// Sample rate is expressed in Hz. (ie: 48KHz would be passed as 48000)
public func samplesValue(sampleRate: Int) -> Int {
public func samplesValue(sampleRate: Int) -> PlatformInt {
let val = samplesDoubleValue(sampleRate: sampleRate).rounded()
// avoid crash if Double is too big
guard val <= Double(Int.max) else {
guard val <= Double(PlatformInt.max) else {
// assertionFailure("Timecode is too large to convert to audio samples. This will fail silently in a release build.")
return 0
}
return Int(val)
return PlatformInt(val)
}

/// (Lossy)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ extension Timecode {
}

/// Returns the `upperLimit` minus 1 subframe expressed as total subframes.
public var maxSubFrameCountExpressible: Int {
public var maxSubFrameCountExpressible: PlatformInt {
frameRate.maxSubFrameCountExpressible(
in: upperLimit,
base: subFramesBase
Expand Down
Loading
Loading