How to play a sound using Swift?
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 AVFoundationvar 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 AVFoundationvar 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 AVFoundationvar 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 inassets.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
For Swift 3 :
import AVFoundation/// **must** define instance variable outside, because .play() will deallocate AVAudioPlayer /// immediately and you won't hear a thingvar player: AVAudioPlayer?func playSound() { guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else { print("url not found") return } do { /// this codes for making this app ready to takeover the device audio try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) try AVAudioSession.sharedInstance().setActive(true) /// change fileTypeHint according to the type of your audio file (you can omit this) player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) // no need for prepareToPlay because prepareToPlay is happen automatically when calling play() player!.play() } catch let error as NSError { print("error: \(error.localizedDescription)") }}
The best practice for local assets is to put it inside assets.xcassets
and you load the file like this :
func playSound() { guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else { print("url not found") return } do { /// this codes for making this app ready to takeover the device audio try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback) try AVAudioSession.sharedInstance().setActive(true) /// change fileTypeHint according to the type of your audio file (you can omit this) /// for iOS 11 onward, use : player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue) /// else : /// player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) // no need for prepareToPlay because prepareToPlay is happen automatically when calling play() player!.play() } catch let error as NSError { print("error: \(error.localizedDescription)") }}
iOS 12 - Xcode 10 beta 6 - Swift 4.2
Use just 1 IBAction and point all the buttons to that 1 action.
import AVFoundationvar player = AVAudioPlayer()@IBAction func notePressed(_ sender: UIButton) { print(sender.tag) // testing button pressed tag let path = Bundle.main.path(forResource: "note\(sender.tag)", ofType : "wav")! let url = URL(fileURLWithPath : path) do { player = try AVAudioPlayer(contentsOf: url) player.play() } catch { print ("There is an issue with this code!") }}