简体   繁体   中英

Resume sound in AVAudioPlayer with swift

I am trying to play a clip of sound that can be paused, resumed or stopped. My pause button works, and the action function for this button is shown below. However I cannot get my resume function to work. When I press the resume button no audio is played. I have read around online and the only tips I can find are to use the prepareToPlay() function and to set shortStartTimeDelay to a value greater than 0.0. I have tried both of these to no avail.

timeAtPause is a global variable of type NSTimeInterval

The action function for the pause button is as follows:

@IBAction func pauseAllAudio(sender: UIButton) { timeAtPause = audioPlayer.currentTime audioPlayer.pause() }

The action function for the resume button is as follows:

@IBAction func resumeAllAudio(sender: UIButton) {
    let shortStartDelay = 0.01
    audioPlayer.prepareToPlay()
    audioPlayer.playAtTime(timeAtPause + shortStartDelay)
}

Any tips on how to resume the audio would be really appreciated. Thank you for your time.

You should not use playAtTime() to resume the AVAudioPlayer , as documentation states:

Plays a sound asynchronously, starting at a specified point in the audio output device's timeline.

and

Use this method to precisely synchronize the playback of two or more AVAudioPlayer objects.

And, even if you use it, it should be used in conjunction with deviceCurrentTime plus the time in seconds to have the delay. In one word, it's not meant to be used to resume the paused player. Instead, just use play() to resume the playback.

You probably did what I did. Upon calling my play() function, I created a new player every time:

// The Wrong Way
@IBAction func playAction(sender: AnyObject) {
    // do and catch omitted for brevity
    player = try AVAudioPlayer(contentsOf: goodURL)
    player.play()
}

However this should be done at some other initialization time, such as when you have the user choose the file to play. Or, if you're hard-coding the file to play, you could initialize at an earlier time, such as viewDidLoad().

Then, once your AVAudioPlayer is initialized, you can call .play() and pause() on it and they will work correctly. And .play() will resume after a pause.

To simply pause and restart at the same point in the audio file, the following works:

@IBAction func playAction(sender: AnyObject) {

     player.play()
}


@IBAction func pauseAction(sender: AnyObject) {

    player.pause()
}

I found these to be helpful. If you are doing this in Swift, I did this a little differently. I created an AudioPlayer class after importing AVFoundation and used these two functions to pause and resume the music. In the SwiftUI call, I used an @State boolean that toggled between the button states. Here is the code that I used:

import AVFoundation
class MusicPlayer {
    static let shared = MusicPlayer()
    var audioPlayer: AVAudioPlayer?

    // Pause music
    func pauseBackgroundMusic() {
        guard let audioPlayer = audioPlayer else { return }
        audioPlayer.pause()
    }

    // Resume music
    func resumeBackgroundMusic() {
        guard let audioPlayer = audioPlayer else { return }
        audioPlayer.play()
    }
}

And in the View: Define an @State variable: @State var pauseMode = false

And call the music player as follows in the Button action code:

Button(action: {
    if pauseMode {
            MusicPlayer.shared.resumeBackgroundMusic()
            self.pauseMode.toggle()
        } else {
            MusicPlayer.shared.pauseBackgroundMusic()
            self.pauseMode.toggle()
        }
    })
    {
        Image(systemName: "playpause")
    }

FYI - I posted this in SwiftUI since newer programmers (and Apple) seem to be moving in this direction. I figured this might help someone (like me!) who came to this question seeking a Swift / SwiftUI answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM