iosswiftavfoundation

How to play a sound using Swift?


I would like to play a sound using Swift.

My code worked in Swift 1.0 but now it doesn't work anymore in Swift 2 or newer.

override func viewDidLoad() {
  super.viewDidLoad()

  let url:NSURL = NSBundle.mainBundle().URLForResource("soundName", withExtension: "mp3")!

  do { 
    player = try AVAudioPlayer(contentsOfURL: url, fileTypeHint: nil) 
  } catch _{
    return
  }

  bgMusic.numberOfLoops = 1
  bgMusic.prepareToPlay()

  if (Data.backgroundMenuPlayed == 0){
    player.play()
    Data.backgroundMenuPlayed = 1
  }
}

Solution

  • Most preferably you might want to use AVFoundation. It provides all the essentials for working with audiovisual media.

    Update: Compatible with Swift 2, Swift 3 and Swift 4 as suggested by some of you in the comments.


    Swift 2.3

    import AVFoundation
    
    var player: AVAudioPlayer?
    
    func playSound() {
        let url = NSBundle.mainBundle().URLForResource("soundName", withExtension: "mp3")!
    
        do {
            player = try AVAudioPlayer(contentsOfURL: url)
            guard let player = player else { return }
    
            player.prepareToPlay()
            player.play()
    
        } catch let error as NSError {
            print(error.description)
        }
    }
    

    Swift 3

    import AVFoundation
    
    var player: AVAudioPlayer?
    
    func playSound() {
        guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else { return }
    
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)
    
            let player = try AVAudioPlayer(contentsOf: url)
    
            player.play()
    
        } catch let error {
            print(error.localizedDescription)
        }
    }
    

    Swift 4 (iOS 13 compatible)

    import AVFoundation
    
    var player: AVAudioPlayer?
    
    func playSound() {
        guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else { return }
    
        do {
            try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)            
            try AVAudioSession.sharedInstance().setActive(true)
    
            /* The following line is required for the player to work on iOS 11. Change the file type accordingly*/
            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)
    
            /* iOS 10 and earlier require the following line:
            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) */
    
            guard let player = player else { return }
    
            player.play()
    
        } catch let error {
            print(error.localizedDescription)
        }
    }
    

    Make sure to change the name of your tune as well as the extension. The file needs to be properly imported (Project Build Phases > Copy Bundle Resources). You might want to place it in assets.xcassets for greater convenience.

    For short sound files you might want to go for non-compressed audio formats such as .wav since they have the best quality and a low cpu impact. The higher disk-space consumption should not be a big deal for short sound files. The longer the files are, you might want to go for a compressed format such as .mp3 etc. pp. Check the compatible audio formats of CoreAudio.


    Fun-fact: There are neat little libraries which make playing sounds even easier. :)
    For example: SwiftySound