How to play the same sound overlapping with AVAudi

2020-03-29 05:36发布

问题:

This code plays the sound when the button is tapped but cancels the previous if it is pressed again. I do not want this to happen I want the same sound to overlap when repeatedly pressed. I believe it might be due to using the same AVAudioPlayer as I have looked on the internet but I am new to swift and want to know how to create a new AVAudioPlayer everytime the method runs so the sounds overlap.

   func playSound(sound:String){


    // Set the sound file name & extension

    let soundPath = NSURL(fileURLWithPath:NSBundle.mainBundle().pathForResource(sound, ofType: "mp3")!)
    do {
        //Preperation
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
    } catch _{
    }
    do {
        try AVAudioSession.sharedInstance().setActive(true)
    }
    catch _ {
    }
    //Play the sound
    var error:NSError?
    do{
        audioPlayer = try AVAudioPlayer(contentsOfURL: soundPath)
    }catch let error1 as NSError {
        error = error1
    }

   audioPlayer.prepareToPlay()
  audioPlayer.play()

}

回答1:

To play two sounds simultaneously with AVAudioPlayer you just have to use a different player for each sound.

In my example I've declared two players, playerBoom and playerCrash, in the Viewcontroller, and I'm populating them with a sound to play via a function, then trigger the play at once:

import AVFoundation

class ViewController: UIViewController {

    var playerBoom:AVAudioPlayer?
    var playerCrash:AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()

        playerBoom = preparePlayerForSound(named: "sound1")
        playerCrash = preparePlayerForSound(named: "sound2")

        playerBoom?.prepareToPlay()
        playerCrash?.prepareToPlay()
        playerBoom?.play()
        playerCrash?.play()

    }

    func preparePlayerForSound(named sound: String) -> AVAudioPlayer? {
        do {
            if let soundPath = NSBundle.mainBundle().pathForResource(sound, ofType: "mp3") {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
                try AVAudioSession.sharedInstance().setActive(true)
                return try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: soundPath))
            } else {
                print("The file '\(sound).mp3' is not available")
            }
        } catch let error as NSError {
            print(error)
        }
        return nil
    }

}

It works very well but IMO is not suitable if you have many sounds to play. It's a perfectly valid solution for just a few ones, though.

This example is with two different sounds but of course the idea is exactly the same for two identic sounds.



回答2:

I could not find a solution using just AVAudioPlayer.

Instead, I have found a solution to this problem with a library that is built on top of AVAudioPlayer.

The library allows same sounds to be played overlapped with each other.

https://github.com/adamcichy/SwiftySound