Created
November 3, 2017 12:07
-
-
Save josipbernat/0991ba1de73c02da839883408fe0f428 to your computer and use it in GitHub Desktop.
AVAudioPlayer fade in and fade out operation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FadeOperation.swift | |
// SomeProject | |
// | |
// Created by Josip Bernat on 03/11/2017. | |
// Copyright © 2017 Josip's Home. All rights reserved. | |
// | |
import Foundation | |
import AVFoundation | |
class FadeOperation: Operation { | |
let player: AVAudioPlayer | |
let fade: Fade | |
fileprivate let fadeStep = 0.01 //0.01 step gives us fine fade in / out. | |
enum Fade: Int { | |
case anIn = 0 | |
case out | |
} | |
init(player: AVAudioPlayer, fade: Fade) { | |
self.player = player | |
self.fade = fade | |
super.init() | |
} | |
override var isAsynchronous: Bool { return true } | |
override var isExecuting: Bool { return state == .executing } | |
override var isFinished: Bool { return state == .finished } | |
var state = State.ready { | |
willSet { | |
willChangeValue(forKey: state.keyPath) | |
willChangeValue(forKey: newValue.keyPath) | |
} | |
didSet { | |
didChangeValue(forKey: state.keyPath) | |
didChangeValue(forKey: oldValue.keyPath) | |
} | |
} | |
enum State: String { | |
case ready = "Ready" | |
case executing = "Executing" | |
case finished = "Finished" | |
fileprivate var keyPath: String { return "is" + self.rawValue } | |
} | |
override func start() { | |
if self.isCancelled { | |
state = .finished | |
} else { | |
state = .ready | |
main() | |
} | |
} | |
override func main() { | |
if self.isCancelled { | |
state = .finished | |
} | |
else { | |
state = .executing | |
if fade == .anIn { | |
fadeIn() | |
} | |
else { | |
fadeOut() | |
} | |
} | |
} | |
func fadeIn() { | |
if isCancelled { | |
state = .finished | |
return | |
} | |
if player.volume == 1.0 { | |
player.volume = 0.0 | |
} | |
player.prepareToPlay() | |
player.play() | |
commitFadeIn() | |
} | |
deinit { | |
print("FadeOperation deinit") | |
} | |
func commitFadeIn() { | |
if isCancelled { | |
state = .finished | |
return | |
} | |
if player.volume < 1.0 { | |
// Fade | |
player.volume += Float(fadeStep) | |
if player.volume > 1.0 { | |
player.volume = 1.0 | |
} | |
DispatchQueue.global().asyncAfter(deadline: .now() + fadeStep, execute: { [weak self] in | |
if self?.isCancelled == false { | |
self?.commitFadeIn() | |
} | |
else { | |
self?.state = .finished | |
} | |
}) | |
} | |
else { | |
state = .finished | |
} | |
} | |
func fadeOut() { | |
if isCancelled { | |
state = .finished | |
return | |
} | |
commitFadeOut() | |
} | |
@objc fileprivate func commitFadeOut() { | |
if isCancelled { | |
state = .finished | |
return | |
} | |
if player.volume > 0.0 { | |
// Fade | |
player.volume -= Float(fadeStep) | |
if player.volume < 0.0 { | |
player.volume = 0.0 | |
} | |
DispatchQueue.global().asyncAfter(deadline: .now() + fadeStep, execute: { [weak self] in | |
if self?.isCancelled == false { | |
self?.commitFadeOut() | |
} | |
else { | |
self?.state = .finished | |
} | |
}) | |
} | |
else { | |
// Stop and get the sound ready for playing again | |
player.pause() | |
state = .finished | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This example is using one OperationQueue per player so | |
// cancel all operations if user clicks play / pause fast. | |
func play() { | |
queue.cancelAllOperations() | |
queue.addOperation(FadeOperation.init(player: player, fade: .anIn)) | |
} | |
func pause() { | |
queue.cancelAllOperations() | |
queue.addOperation(FadeOperation.init(player: player, fade: .out)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment