Reputation: 295
I am trying to implement an audio player in my application to play an audio file. I am using the AVFoundation framework in order to play the audio files. I have controls like a slider to change the audio flow and rate buttons to increase and decrease the audio speed. The slider should move along with audio and if the slider position is changed the audio should play from the position the slider is placed. And even if the rate buttons are clicked the audio should increase the speed from where it is playing. How can I make it work in Swift 5?
import AVFoundation
class AudioPlayer: UIViewController, AVAudioPlayerDelegate {
@IBOutlet weak var slider: UISlider!
@IBOutlet weak var currentTime: UILabel!
@IBOutlet weak var totalDuration: UILabel!
@IBAction func playButton(_ sender: Any) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: audioPath)
guard let player = audioPlayer else { return }
player.prepareToPlay()
player.enableRate = true
player.play()
} catch let error {
print(error.localizedDescription)
}
}
@IBAction func slideMoved(_ sender: Any) {
slider.maximumValue = Float(audioPlayer.duration)
}
var audioPlayer:AVAudioPlayer!
override func viewDidLoad() {
self.audioPlayer = try AVAudioPlayer(contentsOf: path)
self.audioPlayer.enableRate = true
self.audioPlayer.prepareToPlay()
self.audioPlayer.delegate = self
}
@objc func speed1ViewTapped(_ sender: UITapGestureRecognizer? = nil) {
}
@objc func speed2ViewTapped(_ sender: UITapGestureRecognizer? = nil) {
}
@objc func speed3ViewTapped(_ sender: UITapGestureRecognizer? = nil) {
}
}
Upvotes: 1
Views: 921
Reputation: 14417
You can use AVPlayer's PeriodicTime Observer to update your slider progress
let _ = audioPlayer.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in
self?.slider.value = Float(CMTimeGetSeconds(time)) / Float(totalDuration)
}
instead of setting maximum value of slider ... change this function as well
@IBAction func slideMoved(_ sender: Any) {
let value = self.slider.value
let durationToSeek = Float(totalDuration) * value
audioPlayer.seek(to: CMTimeMakeWithSeconds(Float64(durationToSeek),player.currentItem!.duration.timescale)) { [weak self](state) in
}
}
Upvotes: 1