Created
November 29, 2022 00:47
-
-
Save karenxpn/3e2520d31ac237811455466e018cefc2 to your computer and use it in GitHub Desktop.
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
import Foundation | |
import AVKit | |
import SwiftUI | |
import AVFoundation | |
import Combine | |
class AudioPlayViewModel: ObservableObject { | |
private var timer: Timer? | |
@Published var isPlaying: Bool = false | |
@Published public var soundSamples = [AudioPreviewModel]() | |
let sample_count: Int | |
var index = 0 | |
let url: URL | |
var dataManager: ServiceProtocol | |
@Published var player: AVPlayer! | |
@Published var session: AVAudioSession! | |
init(url: URL, sampels_count: Int, dataManager: ServiceProtocol = Service.shared) { | |
self.url = url | |
self.sample_count = sampels_count | |
self.dataManager = dataManager | |
visualizeAudio() | |
do { | |
session = AVAudioSession.sharedInstance() | |
try session.setCategory(.playAndRecord) | |
try session.overrideOutputAudioPort(AVAudioSession.PortOverride.speaker) | |
} catch { | |
print(error.localizedDescription) | |
} | |
player = AVPlayer(url: self.url) | |
} | |
func startTimer() { | |
count_duration { duration in | |
let time_interval = duration / Double(self.sample_count) | |
self.timer = Timer.scheduledTimer(withTimeInterval: time_interval, repeats: true, block: { (timer) in | |
if self.index < self.soundSamples.count { | |
withAnimation(Animation.linear) { | |
self.soundSamples[self.index].color = Color.black | |
} | |
self.index += 1 | |
} | |
}) | |
} | |
} | |
@objc func playerDidFinishPlaying(note: NSNotification) { | |
self.player.pause() | |
self.player.seek(to: .zero) | |
self.timer?.invalidate() | |
self.isPlaying = false | |
self.index = 0 | |
self.soundSamples = self.soundSamples.map { tmp -> AudioPreviewModel in | |
var cur = tmp | |
cur.color = Color.gray | |
return cur | |
} | |
} | |
func playAudio() { | |
if isPlaying { | |
pauseAudio() | |
} else { | |
NotificationCenter.default.addObserver(self, selector:#selector(self.playerDidFinishPlaying(note:)),name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem) | |
isPlaying.toggle() | |
player.play() | |
startTimer() | |
count_duration { _ in } | |
} | |
} | |
func pauseAudio() { | |
player.pause() | |
timer?.invalidate() | |
self.isPlaying = false | |
} | |
func count_duration(completion: @escaping(Float64) -> ()) { | |
DispatchQueue.global(qos: .background).async { | |
if let duration = self.player.currentItem?.asset.duration { | |
let seconds = CMTimeGetSeconds(duration) | |
DispatchQueue.main.async { | |
completion(seconds) | |
} | |
return | |
} | |
DispatchQueue.main.async { | |
completion(1) | |
} | |
} | |
} | |
func visualizeAudio() { | |
dataManager.buffer(url: url, samplesCount: sample_count) { results in | |
self.soundSamples = results | |
} | |
} | |
func removeAudio() { | |
do { | |
try FileManager.default.removeItem(at: url) | |
NotificationCenter.default.post(name: Notification.Name("hide_audio_preview"), object: nil) | |
} catch { | |
print(error) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment