How do you add background music to SpriteKit? - ios

I tried doing this:
let soundFilePath = NSBundle.mainBundle().pathForResource("GL006_SNES_Victory_loop.aif", ofType: "GL006_SNES_Victory_loop.aif")
let soundFileURL = NSURL(fileURLWithPath: soundFilePath!)
let player = AVAudioPlayer(contentsOfURL: soundFileURL, fileTypeHint: nil)
player.numberOfLoops = -1 //infinite
player.play()
I put this code in the didMoveToView function, and I have import AVFoundation at the top of my code. I get the error:
Call can throw, but it is not marked with 'try' and the error is not handled.
Thank you in advance!

(Xcode 8 and Swift 3)
Using SpriteKit this is pretty simple. You create an SKAudioNote with a sound file and then you attach it to your Scene as a child. It will loop by default:
override func didMove(to view: SKView) {
let backgroundSound = SKAudioNode(fileNamed: "bg.mp3")
self.addChild(backgroundSound)
}
If you want to stop the background music at some point you can use the build in methods:
backgroundSound.run(SKAction.stop())
Or maybe you want to play the sound again after stopping it:
backgroundSound.run(SKAction.play())
SpriteKit makes this really simple. I hope this helps you.

In Swift 2, the parameter of type NSErrorPointer is left out and can be caught within catch block as follows:
do
{
let player = try AVAudioPlayer(contentsOfURL: soundFileURL, fileTypeHint: nil)
}
catch let error as NSError
{
print(error.description)
}
Addendum:
It is better to declare your AVAudioPlayer as an ivar; otherwise, it could be released and thus the music won't play:
class yourViewController: UIViewController
{
var player : AVAudioPlayer!
....
So, given that, we make a minor change to the aforementioned try-catch:
do
{
player = try AVAudioPlayer(contentsOfURL: soundFileURL, fileTypeHint: nil)
}
catch let error as NSError
{
print(error.description)
}
Edit:
What you originally have:
let soundFilePath = NSBundle.mainBundle().pathForResource("GL006_SNES_Victory_loop.aif", ofType: "GL006_SNES_Victory_loop.aif")
let soundFileURL = NSURL(fileURLWithPath: soundFilePath!)
let player = AVAudioPlayer(contentsOfURL: soundFileURL, fileTypeHint: nil)
player.numberOfLoops = -1 //infinite
player.play()
Hereby adding the catch clause in Swift 2:
let soundFilePath = NSBundle.mainBundle().pathForResource("GL006_SNES_Victory_loop.aif", ofType: "GL006_SNES_Victory_loop.aif")
let soundFileURL = NSURL(fileURLWithPath: soundFilePath!)
do
{
player = try AVAudioPlayer(contentsOfURL: soundFileURL, fileTypeHint: nil)
}
catch let error as NSError
{
print(error.description)
}
player.numberOfLoops = -1 //infinite
player.play()
Assuming your class is a subclass of SKScene:
class yourGameScene: SKScene
{
//declare your AVAudioPlayer ivar
var player : AVAudioPlayer!
//Here is your didMoveToView function
override func didMoveToView(view: SKView)
{
let soundFilePath = NSBundle.mainBundle().pathForResource("GL006_SNES_Victory_loop.aif", ofType: "GL006_SNES_Victory_loop.aif")
let soundFileURL = NSURL(fileURLWithPath: soundFilePath!)
do
{
player = try AVAudioPlayer(contentsOfURL: soundFileURL, fileTypeHint: nil)
}
catch let error as NSError
{
print(error.description)
}
player.numberOfLoops = -1 //infinite
player.play()
//The rest of your other codes
}
}

Related

Play a sound file on repeat in Swift?

I have had success playing sounds by pressing a button, by using the following code. However, I'd like to press a button and have that sound play in a loop/infinitely. How is this acheived? I'd also like to acheive pause/play functionality as well. Thanks in advance.
#IBAction func keyPressed(_ sender: UIB`utton) {
playSound(soundName: sender.currentTitle!)
}
func playSound(soundName: String) { //
let url = Bundle.main.url(forResource: soundName, withExtension: "wav")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
} // End of Play Sound
By default AVAudioPlayer plays its audio from start to finish then stops, but we can control how many times to make it loop by setting its numberOfLoops property. For example, to make your audio play three times in total, you’d write this:
player.numberOfLoops = 3
if you want the infinite loop then use
player.numberOfLoops = -1
for e.g
func playSound(soundName: String) { //
let url = Bundle.main.url(forResource: soundName, withExtension: "wav")
player = try! AVAudioPlayer(contentsOf: url!)
player.numberOfLoops = -1 // set your count here
player.play()
} // End of Play Sound
var audioPlayer: AVAudioPlayer?
func startBackgroundMusic() {
if let bundle = Bundle.main.path(forResource: "Guru_Nanak_Sahib_Ji", ofType: "mp3") {
let backgroundMusic = NSURL(fileURLWithPath: bundle)
do {
audioPlayer = try AVAudioPlayer(contentsOf:backgroundMusic as URL)
guard let audioPlayer = audioPlayer else { return }
audioPlayer.numberOfLoops = -1 // for infinite times
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print(error)
}
}
}
You can retain the player. Then in the player's completion delegate callback, start playing again. Or stop the player at any time, since you've retained a reference to it.

AVAudioPlayer can't play sound until using debug script

I'm using Xcode 7.3.1 with iOS 9 and having issue with playing sound by AVAudioPlayer. I've tried all possible solution out there and nothing works Here is my code
let mp3Url = NSBundle.mainBundle().URLForResource("BCA", withExtension:"mp3")!
var player = AVAudioPlayer()
do {
player = try AVAudioPlayer(contentsOfURL: mp3Url)
player.prepareToPlay()
player.play()
} catch let error as NSError {
print(error.description)
}
The sound won't play until I put a breakpoint at player.play() and using po player. Then the sound will be played.
Any idea will be helpful for me.
Try this :
var player: AVAudioPlayer?
func playSound(){
guard let url = Bundle.main.url(forResource: "alert_song", withExtension: "mp3") else {
print("MP3 resource not found.")
return
}
print("Music to play : \(String(describing: url))")
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
player = try AVAudioPlayer(contentsOf: url)
guard let player = player else { return }
player.play()
} catch let error {
print(error.localizedDescription)
}
}
Try this :
var player = AVAudioPlayer() //global variables will otherwise be deadlock
let mp3Url = NSBundle.mainBundle().URLForResource("BCA", withExtension:"mp3")!
do {
player = try AVAudioPlayer(contentsOfURL: mp3Url)
player.play()
} catch let error as NSError {
print(error.description)
}

Play different audioplayers in sequence Swift

So basically I have two audio players while using the AVFoundation. I want the second one to be played right after the first one finishes.
myFilePathString = NSBundle.mainBundle().pathForResource("\(workout[currentExercise])", ofType: "mp3")
#IBAction func startWorkout(sender: AnyObject) {
if let myFilePathString = myFilePathString {
let myFilePathURL = NSURL(fileURLWithPath: myFilePathString)
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: myFilePathURL)
audioPlayer.play()
}catch {
print("Error")
}
}
This above one is to be the first
let path = NSBundle.mainBundle().pathForResource("Rest", ofType: "mp3")
let url = NSURL(fileURLWithPath: path!)
do {
let sound = try AVAudioPlayer(contentsOfURL: url)
secondAudioPlayer = sound
sound.play()
} catch {
print("error")
}
...while this one is to be played after. At the moment they play at the same time. Got any ideas for me?
Thank you in advance.

Swift AVAudioPlayer doesn't play sound

I want to play two sound files in my Swift app. "C1_bip.aif" and "false.aif".
They're both in the same folder in the project.
But when I start the app, the C1_bip sound is played and the false sound not and it prints Error to the Console.
The sound files are the same file type and I can play them both in the project explorer in Xcode.
if let path = NSBundle.mainBundle().pathForResource("C1_bip", ofType: "aif") {
audioPlayer = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: path),
fileTypeHint: "aif", error: nil)
if let sound = audioPlayer {
sound.prepareToPlay()
sound.play()
}
}
else {
println("Error")
}
if let path = NSBundle.mainBundle().pathForResource("false", ofType: "aif") {
audioPlayer = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: path),
fileTypeHint: "aif", error: nil)
if let sound = audioPlayer {
sound.prepareToPlay()
sound.play()
}
}
else {
println("Error")
}
Here is what I did in my test project:
let musicPath = NSBundle.mainBundle().pathForResource("bgmusic", ofType: "mp3")
let url = NSURL(fileURLWithPath: musicPath!)
do{
audioPlayer = try AVAudioPlayer(contentsOfURL: url)
}catch _ {
audioPlayer = nil
}
audioPlayer.numberOfLoops = -1
audioPlayer.prepareToPlay()
audioPlayer.play()
And it did work well:)

AVAudioPlayer not playing audio in Swift

I have this code in a very simple, single view Swift application in my ViewController:
var audioPlayer = AVAudioPlayer()
#IBAction func playMyFile(sender: AnyObject) {
let fileString = NSBundle.mainBundle().pathForResource("audioFile", ofType: "m4a")
let url = NSURL(fileURLWithPath: fileString)
var error : NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: url, error: &error)
audioPlayer.delegate = self
audioPlayer.prepareToPlay()
if (audioPlayer.isEqual(nil)) {
println("There was an error: (er)")
} else {
audioPlayer.play()
NSLog("working")
}
I have added import AVFoundation and audioPlayer is a global variable. When I execute the code, it does print "working", so it makes it through without errors but no sound is played. The device is not in silent.
There's so much wrong with your code that Socratic method breaks down; it will probably be easiest just to throw it out and show you:
var player : AVAudioPlayer! = nil // will be Optional, must supply initializer
#IBAction func playMyFile(sender: AnyObject?) {
let path = NSBundle.mainBundle().pathForResource("audioFile", ofType:"m4a")
let fileURL = NSURL(fileURLWithPath: path)
player = AVAudioPlayer(contentsOfURL: fileURL, error: nil)
player.prepareToPlay()
player.delegate = self
player.play()
}
I have not bothered to do any error checking, but the upside is you'll crash if there's a problem.
One final point, which may or may not be relevant: not every m4a file is playable. A highly compressed file, for example, can fail silently (pun intended).
Important that AvPlayer is class member and not in the given function, else it goes out of scope... :)
I had to declare a global player variable
var player: AVAudioPlayer!
and set it in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
player = AVAudioPlayer()
}
Then I could play the audio file wherever like this:
func playAudioFile(){
do {
if audioFileUrl == nil{
return
}
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: audioFileUrl, fileTypeHint: AVFileType.m4a.rawValue)
/* iOS 10 and earlier require the following line:
player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3) */
guard let player = player else { return }
player.play()
print("PLAYING::::: \(audioFileUrl)")
}
catch let error {
print(error.localizedDescription)
}
}
}
Here is a working snippet from my swift project. Replace "audiofile" by your file name.
var audioPlayer = AVAudioPlayer()
let audioPath = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("audiofile", ofType: "mp3"))
audioPlayer = AVAudioPlayer(contentsOfURL: audioPath, error: nil)
audioPlayer.delegate = self
audioPlayer.prepareToPlay()
audioPlayer.play()
You can download fully functional Swift Audio Player application source code from here https://github.com/bpolat/Music-Player
for some reason (probably a bug) Xcode can't play certain music files in the .m4a and the .mp3 format I would recommend changing them all to .wav files to get it to play
//top of your class
var audioPlayer = AVAudioPlayer
//where you want to play your sound
let Sound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "sound", ofType: "wav")!)
do {
audioPlayer = try AVAudioPlayer(contentsOf: Sound as URL)
audioPlayer.prepareToPlay()
} catch {
print("Problem in getting File")
}
audioPlayer.play()
var audioPlayer = AVAudioPlayer()
var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("KiepRongBuon", ofType: "mp3")!)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.prepareToPlay()
audioPlayer.play()
I used the below code in my app and it works. Hope that is helpful.
var audioPlayer: AVAudioPlayer!
if var filePath = NSBundle.mainBundle().pathForResource("audioFile", ofType:"mp3"){
var filePathUrl = NSURL.fileURLWithPath(filePath)
audioPlayer = AVAudioPlayer(contentsOfURL: filePathUrl, error: nil)
audioPlayer.play()
}else {
println("Path for audio file not found")
}
In Swift Coding using Try catch, this issues will solve and play audio for me and my code below,
var playerVal = AVAudioPlayer()
#IBAction func btnPlayAction(sender: AnyObject) {
let fileURL: NSURL = NSURL(string: url)!
let soundData = NSData(contentsOfURL: fileURL)
do {
playerVal = try AVAudioPlayer(data: soundData!)
}
catch {
print("Something bad happened. Try catching specific errors to narrow things down",error)
}
playerVal.delegate = self
playerVal.prepareToPlay()
playerVal.play()
}
Based on #matt answer but little bit detailed 'cause original answer did not completely satisfied me.
import AVFoundation
class YourController: UIViewController {
private var player : AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
prepareAudioPlayer()
}
#IBAction func playAudio() {
player?.play()
}
}
extension YourController: AVAudioPlayerDelegate {}
private extension YourController {
func prepareAudioPlayer() {
guard let path = Bundle.main.path(forResource: "you-audio", ofType:"mp3") else {
return
}
let fileURL = URL(fileURLWithPath: path)
do {
player = try AVAudioPlayer(contentsOf: fileURL)
} catch let ex {
print(ex.localizedDescription)
}
player?.prepareToPlay()
player?.delegate = self
}
}
swift 3.0:
import UIKit
import AVFoundation
class ViewController: UIViewController
{
var audioplayer = AVAudioPlayer()
#IBAction func Play(_ sender: Any)
{
audioplayer.play()
}
#IBAction func Pause(_ sender: Any)
{
if audioplayer.isPlaying
{
audioplayer.pause()
}
else
{
}
}
#IBAction func Restart(_ sender: Any)
{
if audioplayer.isPlaying
{
audioplayer.currentTime = 0
audioplayer.play()
}
else
{
audioplayer.play()
}
}
override func viewDidLoad()
{
super.viewDidLoad()
do
{
audioplayer = try AVAudioPlayer(contentsOf:URL.init(fileURLWithPath:Bundle.main.path(forResource:"bahubali", ofType: "mp3")!))
audioplayer.prepareToPlay()
var audioSession = AVAudioSession.sharedInstance()
do
{
try audioSession.setCategory(AVAudioSessionCategoryPlayback)
}
catch
{
}
}
catch
{
print (error)
}
}
}

Resources