How to add a delay to a sound being played with swift - ios
I am a total swift beginner and am working on a tutorial project (magic 8 ball) and have been successful at doing the following:
- play a specific sound when the "Ask" button is pressed.
- play a specific sound when for each of the randomly picked images
However now the sound that should play whenever the button is pressed only plays once and from there on i only hear the sounds that are being displayed with each image. Is this because I am "stuck" in the "if - else" loop ? Or do I have to delay the sounds that are being played for each image in the array ?
Thanks so much for your help !
Here is my code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var magicBall: UIImageView!
var magicBallDisplay = 1
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
magicBall.image = #imageLiteral(resourceName: "theanswerisyes")
}
#IBAction func askButtonPressed(_ sender: UIButton) {
let magicBallArray = [ #imageLiteral(resourceName: "askagainlater"),#imageLiteral(resourceName: "no"),#imageLiteral(resourceName: "theanswerisyes"),#imageLiteral(resourceName: "yes"),#imageLiteral(resourceName: "noidea")]
magicBall.image = magicBallArray.randomElement()
let soundURL = NSURL(fileURLWithPath: Bundle.main.path(forResource: "Ask", ofType: "wav")!)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
}catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
if (magicBall.image?.isEqual(UIImage(named: "yes")))! {
let soundURL = NSURL(fileURLWithPath: Bundle.main.path(forResource: "yes", ofType: "mp3")!)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
} catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
}
else if (magicBall.image?.isEqual(UIImage(named: "no")))! {
let soundURL = NSURL(fileURLWithPath: Bundle.main.path(forResource: "no", ofType: "mp3")!)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
} catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
}
else if (magicBall.image?.isEqual(UIImage(named: "theanswerisyes")))! {
let soundURL = NSURL(fileURLWithPath: Bundle.main.path(forResource: "theanswerisyes", ofType: "mp3")!)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
} catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
}
else if (magicBall.image?.isEqual(UIImage(named: "noidea")))! {
let soundURL = NSURL(fileURLWithPath: Bundle.main.path(forResource: "noidea", ofType: "mp3")!)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
} catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
}
else if (magicBall.image?.isEqual(UIImage(named: "askagainlater")))! {
let soundURL = NSURL(fileURLWithPath: Bundle.main.path(forResource: "askagainlater", ofType: "mp3")!)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
} catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
}
}
}
I make a new project and change your code to this:
import UIKit
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var magicBall: UIImageView!
// you never used this
//var magicBallDisplay = 1
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
magicBall.image = #imageLiteral(resourceName: "theanswerisyes")
}
#IBAction func askButtonPressed(_ sender: UIButton) {
// because you have audio file and image with equal name i made array of string
let magicBallArray = [ "yes","no","theanswerisyes","noidea","askagainlater"]
// check if i get not null item
guard let choosedImageName = magicBallArray.randomElement() else {return}
print(choosedImageName)
// set image with random picked name
magicBall.image = UIImage(named: choosedImageName)
// play ask sound
playSound(fileName: "Ask", fileType: "wav")
// play picked image sound after 10 second from now()
// change number to your needed time
DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: {
self.playSound(fileName: choosedImageName, fileType: "mp3")
})
}
private func playSound(fileName: String, fileType: String)
{
// check if you find the audio file
guard let url = Bundle.main.path(forResource: fileName, ofType: fileType) else {
print("path not found")
return
}
// make NSURL from path
let soundURL = NSURL(fileURLWithPath: url)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
} catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
}
}
I explain code for you.
I didn't enable the button. you can improve this code when you came stronger in swift
your code is really messy.
at first, I advise you to make a function for playing sound like that:
func playSound(fileName: String, fileType: String) {
let soundURL = NSURL(fileURLWithPath: Bundle.main.path(forResource: fileName, ofType: fileType)!)
do{
audioPlayer = try AVAudioPlayer(contentsOf: soundURL as URL)
}catch {
print("there was some error. The error was \(error)")
}
audioPlayer.play()
}
you must have a callback for first play sound. after finishing the first sound you can check your if-else or you can try switch-case.
also, you can use delay for playing second sound
Related
How to play mp3 file in swift3?
I have started to learn ios development and am stuck in one place. My code to play mp3 file is var bombSoundEffect: AVAudioPlayer! let path = Bundle.main.path(forResource: "faded", ofType:"mp3")! let url = NSURL(fileURLWithPath: path) do { let sound = try AVAudioPlayer(contentsOf: (url as NSURL) as URL) bombSoundEffect.play() } catch { print("couldn't load file :(") } if bombSoundEffect != nil { bombSoundEffect.stop() bombSoundEffect = nil } However, when I click on the button, my file doesn't play. The song is playing perfectly normally.
Try with the follow code: var bombSoundEffect: AVAudioPlayer? func playAudio() { let url = Bundle.main.url(forResource: "faded", withExtension: "mp3")! do { bombSoundEffect = try AVAudioPlayer(contentsOf: url) guard let bombSound = bombSoundEffect else { return } bombSound.prepareToPlay() bombSound.play() } catch let error { print(error.localizedDescription) } }
There's lots wrong with your code, but it's a sunny day, so try something like this… func playSound() { guard let url = Bundle.main.url(forResource: "faded", withExtension: "mp3") else { return } let bombSoundEffect = try? AVAudioPlayer(contentsOf: url) bombSoundEffect?.play() }
Music player error
I get an error in the first line of my music player code. How can I fix it? Error: Call can throw but its not marked with try and the error is not handled audioPlayer = AVAudioPlayer(contentsOf: pianoSound as URL) audioPlayer.prepareToPlay() var pianoSound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "C", ofType: "m4a")!) var audioPlayer = AVAudioPlayer()
As it is possible to conclude from the error you get : Error: Call can throw but its not marked with try and the error is not handled Because AVAudioPlayer can throw exception you should use do {} catch {} let path = Bundle.main.path(forResource: "C", ofType:"m4a")! let url = URL(fileURLWithPath: path) do { let sound = try AVAudioPlayer(contentsOf: url) sound.play() } catch { // Catch exception } This is example of working prototype: class ViewController: UIViewController { var boomSound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "boom", ofType: "wav")!) var audioPlayer = AVAudioPlayer() override func viewDidLoad() { super.viewDidLoad() } #IBAction func play(_ sender: AnyObject) { do { audioPlayer = try AVAudioPlayer(contentsOf: boomSound as URL) audioPlayer.prepareToPlay() audioPlayer.play() } catch { // Catch exception } } }
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.
AVAudioPlayer can't hear any sound using swift 2.1
i try to make iOS app to play some funny sound put when i click play no sound are out from speaker here is the code : #IBAction func slow(sender: UIButton) { if let filePath = NSBundle.mainBundle().URLForResource("io", withExtension: "mp3") { let _a = try! AVAudioPlayer(contentsOfURL: filePath) // Play _a.play() }else { print("error") } } there is no error but i can't hear any sound at all
for how that face this problem #IBAction func slow(sender: UIButton) { if let path = NSBundle.mainBundle().pathForResource("io", ofType:"mp3") { let fileURL = NSURL(fileURLWithPath: path) player = try! AVAudioPlayer(contentsOfURL: fileURL) player.prepareToPlay() player.play() } else { print("error") } } }
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) } } }