feat: implement audio fade in/out

This commit is contained in:
2024-07-28 17:08:01 +01:00
parent f4222c38bd
commit 390f9b2b09

View File

@@ -7,27 +7,37 @@ enum PlaybackState {
case loading
}
@MainActor
class PlaybackManager: ObservableObject {
@Published var playbackState: PlaybackState = .paused
@Published var hasError = false
private var audioPlayer = AVPlayer()
private var fadeInTimer: Timer?
private var fadeOutTimer: Timer?
private var scheduledFadeOutTimer: Timer?
func nextTrack() {
playbackState = .loading
Task {
try await loadCurrentTrack()
playbackState = .playing
try await loadAndPlayNextTrack()
await MainActor.run {
playbackState = .playing
}
}
}
func stop() {
playbackState = .paused
fadeInTimer?.invalidate()
fadeInTimer = nil
fadeOutTimer?.invalidate()
fadeOutTimer = nil
scheduledFadeOutTimer?.invalidate()
scheduledFadeOutTimer = nil
audioPlayer.pause()
}
private nonisolated func loadCurrentTrack() async throws {
private nonisolated func loadAndPlayNextTrack() async throws {
let now = Date().timeIntervalSince1970
guard let url = URL(string: "https://infinifi.cafe/current.mp3?t=\(now)") else {
return
@@ -41,11 +51,19 @@ class PlaybackManager: ObservableObject {
}
let playerItem = AVPlayerItem(asset: asset)
NotificationCenter.default.addObserver(self, selector: #selector(playbackFinished), name: AVPlayerItem.didPlayToEndTimeNotification, object: playerItem)
await audioPlayer.replaceCurrentItem(with: playerItem)
audioPlayer.volume = 0.0
audioPlayer.replaceCurrentItem(with: playerItem)
await audioPlayer.play()
DispatchQueue.main.async {
self.fadeInAudio()
self.scheduledFadeOutTimer = Timer.scheduledTimer(withTimeInterval: 55, repeats: false) { _ in
self.fadeOutAudio()
}
}
}
@objc
@@ -55,4 +73,22 @@ class PlaybackManager: ObservableObject {
nextTrack()
}
}
private func fadeInAudio() {
fadeInTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
self.audioPlayer.volume += 0.01
if self.audioPlayer.volume >= 1.0 {
timer.invalidate()
}
}
}
private func fadeOutAudio() {
fadeOutTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
self.audioPlayer.volume -= 0.02
if self.audioPlayer.volume <= 0 {
timer.invalidate()
}
}
}
}