Skip to content

Commit 81e8d03

Browse files
committed
Use ranges where appropriate
1 parent 943d2cd commit 81e8d03

File tree

2 files changed

+56
-54
lines changed

2 files changed

+56
-54
lines changed

Source/FDWaveformRenderOperation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ struct FDWaveformRenderFormat {
1414
var type: FDWaveformType
1515

1616
/// The color of the waveform
17-
public var wavesColor: UIColor
17+
internal var wavesColor: UIColor
1818

1919
/// The scale factor to apply to the rendered image (usually the current screen's scale)
2020
public var scale: CGFloat

Source/FDWaveformView.swift

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ open class FDWaveformView: UIView {
5151
}
5252

5353
/// The samples to be highlighted in a different color
54-
/*@IBInspectable*/ open var highlightedSamples: CountableRange<Int>? = 0 ..< 0 {
54+
/*@IBInspectable*/ open var highlightedSamples: CountableRange<Int>? = nil {
5555
didSet {
5656
guard totalSamples > 0 else {
5757
return
@@ -68,10 +68,10 @@ open class FDWaveformView: UIView {
6868
@available(*, deprecated, message: "Use `zoomSamples` to set range")
6969
open var progressSamples: Int {
7070
get {
71-
return highlightedSamples?.last ?? 0
71+
return highlightedSamples?.upperBound ?? 0
7272
}
73-
set(newSamples) {
74-
highlightedSamples = 0 ..< newSamples
73+
set {
74+
highlightedSamples = 0 ..< newValue
7575
}
7676
}
7777

@@ -144,31 +144,29 @@ open class FDWaveformView: UIView {
144144
}
145145

146146

147-
//TODO MAKE PUBLIC
148-
149-
// Drawing a larger image than needed to have it available for scrolling
150-
fileprivate var horizontalMinimumBleed: CGFloat = 0.1
151-
fileprivate var horizontalMaximumBleed: CGFloat = 3.0
152-
fileprivate var horizontalTargetBleed: CGFloat = 0.5
153-
154-
/// Drawing more pixels than shown to get antialiasing, 1.0 = no overdraw, 2.0 = twice as many pixels
155-
fileprivate var horizontalMinimumOverdraw: CGFloat = 2.0
156-
157-
/// Drawing more pixels than shown to get antialiasing, 1.0 = no overdraw, 2.0 = twice as many pixels
158-
fileprivate var horizontalMaximumOverdraw: CGFloat = 5.0
159-
160-
/// Drawing more pixels than shown to get antialiasing, 1.0 = no overdraw, 2.0 = twice as many pixels
161-
fileprivate var horizontalTargetOverdraw: CGFloat = 3.0
162-
163-
/// Drawing more pixels than shown to get antialiasing, 1.0 = no overdraw, 2.0 = twice as many pixels
164-
fileprivate var verticalMinimumOverdraw: CGFloat = 1.0
165-
166-
/// Drawing more pixels than shown to get antialiasing, 1.0 = no overdraw, 2.0 = twice as many pixels
167-
fileprivate var verticalMaximumOverdraw: CGFloat = 3.0
147+
//TODO: MAKE PUBLIC
168148

169-
/// Drawing more pixels than shown to get antialiasing, 1.0 = no overdraw, 2.0 = twice as many pixels
170-
fileprivate var verticalTargetOverdraw: CGFloat = 2.0
149+
/// The portion of extra pixels to render left and right of the viewable region
150+
private var horizontalBleedTarget = 0.5
151+
152+
/// The required portion of extra pixels to render left and right of the viewable region
153+
/// If this portion is not available then a re-render will be performed
154+
private var horizontalBleedAllowed = 0.1 ... 3.0
171155

156+
/// The number of horizontal pixels to render per visible pixel on the screen (for antialiasing)
157+
private var horizontalOverdrawTarget = 3.0
158+
159+
/// The required number of horizontal pixels to render per visible pixel on the screen (for antialiasing)
160+
/// If this number is not available then a re-render will be performed
161+
private var horizontalOverdrawAllowed = 1.5 ... 5.0
162+
163+
/// The number of vertical pixels to render per visible pixel on the screen (for antialiasing)
164+
private var verticalOverdrawTarget = 2.0
165+
166+
/// The required number of vertical pixels to render per visible pixel on the screen (for antialiasing)
167+
/// If this number is not available then a re-render will be performed
168+
private var verticalOverdrawAllowed = 1.0 ... 3.0
169+
172170
/// The "zero" level (in dB)
173171
fileprivate let noiseFloor: CGFloat = -50.0
174172

@@ -341,36 +339,30 @@ open class FDWaveformView: UIView {
341339

342340
func isWaveformRenderOperationDirty(_ renderOperation: FDWaveformRenderOperation?) -> Bool? {
343341
guard let renderOperation = renderOperation else { return nil }
344-
345-
let imageSize = renderOperation.imageSize
346-
let sampleRange = renderOperation.sampleRange
347342

348343
if renderOperation.format.type != waveformRenderType {
349344
return true
350345
}
351346
if renderOperation.format.scale != desiredImageScale {
352347
return true
353348
}
354-
if sampleRange.lowerBound < (zoomSamples.startIndex - Int(CGFloat(sampleRange.count) * horizontalMaximumBleed)).clamped(from: 0, to: totalSamples) {
355-
return true
356-
}
357-
if sampleRange.lowerBound > (zoomSamples.startIndex - Int(CGFloat(sampleRange.count) * horizontalMinimumBleed)).clamped(from: 0, to: totalSamples) {
358-
return true
359-
}
360-
if sampleRange.upperBound < (zoomSamples.endIndex + Int(CGFloat(sampleRange.count) * horizontalMinimumBleed)).clamped(from: 0, to: totalSamples) {
349+
350+
let requiredSamples = zoomSamples.extended(byFactor: horizontalBleedAllowed.lowerBound).clamped(to: 0 ..< totalSamples)
351+
if requiredSamples.clamped(to: renderOperation.sampleRange) != requiredSamples {
361352
return true
362353
}
363-
if sampleRange.upperBound > (zoomSamples.endIndex + Int(CGFloat(sampleRange.count) * horizontalMaximumBleed)).clamped(from: 0, to: totalSamples) {
354+
355+
let allowedSamples = zoomSamples.extended(byFactor: horizontalBleedAllowed.upperBound).clamped(to: 0 ..< totalSamples)
356+
if renderOperation.sampleRange.clamped(to: allowedSamples) != renderOperation.sampleRange {
364357
return true
365358
}
366359

367-
let allowableWidths = frame.width * CGFloat(horizontalMinimumOverdraw) ... frame.width * CGFloat(horizontalMaximumOverdraw)
368-
if !allowableWidths.contains(imageSize.width) {
360+
let verticalOverdrawRequested = Double(renderOperation.imageSize.height / frame.height)
361+
if !verticalOverdrawAllowed.contains(verticalOverdrawRequested) {
369362
return true
370363
}
371-
372-
let allowableHeights = frame.height * CGFloat(verticalMinimumOverdraw) ... frame.height * CGFloat(verticalMaximumOverdraw)
373-
if !allowableHeights.contains(imageSize.height) {
364+
let horizontalOverdrawRequested = Double(renderOperation.imageSize.height / frame.height)
365+
if !horizontalOverdrawAllowed.contains(horizontalOverdrawRequested) {
374366
return true
375367
}
376368

@@ -418,15 +410,13 @@ open class FDWaveformView: UIView {
418410
guard let audioContext = audioContext else { return }
419411
guard !zoomSamples.isEmpty else { return }
420412

421-
let renderStartSamples = (zoomSamples.startIndex - Int(CGFloat(zoomSamples.count) * horizontalTargetBleed)).clamped(from: 0, to: totalSamples)
422-
let renderEndSamples = (zoomSamples.endIndex + Int(CGFloat(zoomSamples.count) * horizontalTargetBleed)).clamped(from: 0, to: totalSamples)
423-
let renderSampleRange = renderStartSamples ..< renderEndSamples
424-
let widthInPixels = floor(frame.width * horizontalTargetOverdraw)
425-
let heightInPixels = frame.height * horizontalTargetOverdraw
413+
let renderSamples = zoomSamples.extended(byFactor: horizontalBleedTarget).clamped(to: 0 ..< totalSamples)
414+
let widthInPixels = floor(frame.width * CGFloat(horizontalOverdrawTarget))
415+
let heightInPixels = frame.height * CGFloat(horizontalOverdrawTarget)
426416
let imageSize = CGSize(width: widthInPixels, height: heightInPixels)
427417
let renderFormat = FDWaveformRenderFormat(type: waveformRenderType, wavesColor: .black, scale: desiredImageScale)
428418

429-
let waveformRenderOperation = FDWaveformRenderOperation(audioContext: audioContext, imageSize: imageSize, sampleRange: renderSampleRange, format: renderFormat) { image in
419+
let waveformRenderOperation = FDWaveformRenderOperation(audioContext: audioContext, imageSize: imageSize, sampleRange: renderSamples, format: renderFormat) { image in
430420
DispatchQueue.main.async {
431421
self.renderForCurrentAssetFailed = (image == nil)
432422
self.waveformImage = image
@@ -544,13 +534,15 @@ extension FDWaveformView: UIGestureRecognizerDelegate {
544534
}
545535
}
546536
else if doesAllowScrubbing {
547-
highlightedSamples = 0 ..< zoomSamples.startIndex + Int(CGFloat(zoomSamples.startIndex) * recognizer.location(in: self).x / bounds.width)
537+
let rangeSamples = CGFloat(zoomSamples.count)
538+
highlightedSamples = 0 ..< Int((CGFloat(zoomSamples.startIndex) + rangeSamples * recognizer.location(in: self).x / bounds.width))
548539
}
549540
}
550541

551542
func handleTapGesture(_ recognizer: UITapGestureRecognizer) {
552543
if doesAllowScrubbing {
553-
highlightedSamples = 0 ..< zoomSamples.startIndex + Int(CGFloat(zoomSamples.startIndex) * recognizer.location(in: self).x / bounds.width)
544+
let rangeSamples = CGFloat(zoomSamples.count)
545+
highlightedSamples = 0 ..< Int((CGFloat(zoomSamples.startIndex) + rangeSamples * recognizer.location(in: self).x / bounds.width))
554546
}
555547
}
556548
}
@@ -578,8 +570,8 @@ extension FDWaveformView: UIGestureRecognizerDelegate {
578570

579571
//MARK -
580572

581-
extension Comparable
582-
{
573+
extension Comparable {
574+
583575
func clamped(from lowerBound: Self, to upperBound: Self) -> Self {
584576
return min(max(self, lowerBound), upperBound)
585577
}
@@ -595,3 +587,13 @@ extension Strideable where Self.Stride: SignedInteger
595587
return min(max(self, range.lowerBound), range.upperBound)
596588
}
597589
}
590+
591+
extension CountableRange where Bound: Strideable {
592+
593+
// Extend each bound away from midpoint by `factor`, a portion of the distance from begin to end
594+
func extended(byFactor factor: Double) -> CountableRange<Bound> {
595+
let theCount: Int = numericCast(count)
596+
let amountToMove: Bound.Stride = numericCast(Int(Double(theCount) * factor))
597+
return lowerBound - amountToMove ..< upperBound + amountToMove
598+
}
599+
}

0 commit comments

Comments
 (0)