Playing Audio With Swift 2 in Xcode 7 - ios

I am trying to play background music on an app I am creating, but none of the solutions I have seen online work. I have experimented with about 5 different blocks of code that others said worked for them but have been short of success on all the attempts. My current code is down below(it is also not working even though there are no errors), I would greatly appreciate it if anyone could give me an explanation as to what I am doing wrong. Thanks!
func playBackgroundMusic() {
do {
self.audioPlayer = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("cool_song", ofType: "mp3")!))
self.audioPlayer.play()
} catch {
print("Error")
}
}

Related

Cannot play audio file without app crashing on device running ios 13

I have an app being used by people to receive orders with it needing to make a continuous sound until staff attend to it. It was working for two months then just started crashing a lot. For whatever reason, it runs fine on an iPad but not on iPhones running a recent operating system.
When this bit of code gets called it crashes:
guard let path = Bundle.main.path(forResource: "alert.mp3", ofType: nil) else { return }
let url = URL(fileURLWithPath: path)
do {
self.alertSoundEffect = try AVAudioPlayer(contentsOf: url)
} catch let err {
print("err: \(err)")
}
DispatchQueue.main.async {
self.alertSoundEffect.numberOfLoops = -1
self.alertSoundEffect.prepareToPlay()
self.alertSoundEffect.play()
}
The fix online to declare the alertSoundEffect variable like this:
private var alertSoundEffect : AVAudioPlayer!
has not worked at all.
I tried moving everything but the line:
self.alertSoundEffect.play()
to viewDidLoad as I thought maybe that code couldn't get called more than once, but it didn't help.
Specifically, the compiler highlights this line when it crashes:
self.alertSoundEffect = try AVAudioPlayer(contentsOf: url)
I tried using try AVAudioPlayer where it takes a Data object as a parameter or with including the type of audio file to be played, but that did not change anything.
When I try the AVAudioPlayer's delegate and declare it like this:
self.alertSoundEffect.delegate = self
right before the first lines of code I shared above Xcode highlights this line instead when it reliably crashes.
What else should I try?
I suppose your path is wrong.
Try this:
guard let path = Bundle.main.path(forResource: "alert", ofType: "mp3") else { return }
Also, if your audio file is short, like less than 30s, then try not to call self.alertSoundEffect.prepareToPlay(). Just call self.alertSoundEffect.play() right away.
Since iOS 13, this was causing a bug in my app, since I have notification sounds which are 3-10 seconds long.
If you initialise your AVAudioPlayer like var wrongMusicPlayer: AVAudioPlayer = AVAudioPlayer() OR wrongMusicPlayer = AVAudioPlayer() in any method then please remove it and just Declare like var wrongMusicPlayer: AVAudioPlayer!.
iOS 13.1 Crash in AVAudio Player

How to switch to earSpeaker programmatically in iOS?

I am currently playing an audio file with "MobileVlcKit" and I need to switch to earSpeaker (top speaker for phone calls) in the middle of playing audio file.
Currently I am using this code:
AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
But it keep playing from main speaker.
Do anyone knows what is my problem?
I just checked my 2 years old objective-c code, not sure will it work for you, but worth to try. here is its swift version:
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setActive(false)
try audioSession.setCategory(.playAndRecord, options: .defaultToSpeaker)
try audioSession.overrideOutputAudioPort(.none)
try audioSession.setActive(true)
} catch {
// handle error
print(error)
}

Play dialler tone on ear-speaker

I'm currently working on a VOIP based application. In which when a user calls another person I need to play a dialler tone on the ear-speaker. I've searched a lot, but couldn't find any solution yet. I've used the following code to play the dialler tone:
// This method plays the ringtone for incoming call
func playRingtone()
{
let path = Bundle.main.path(forResource: "ringing.mp3", ofType:nil)!
let url = URL(fileURLWithPath: path)
do
{
ringtonePlayer = try AVAudioPlayer(contentsOf: url)
ringtonePlayer?.numberOfLoops = 5
ringtonePlayer?.play()
}
catch let error
{
print(error.localizedDescription)
}
}
But it's playing on the loud speaker, not on the ear-speaker.
Additional Info: I'm using TokBox SDK
Can anyone please help me to solve this issue? Thanks in advance.

AVAudioPlayer sound not playing

In iOS 8/Xcode 6 I had a function that included a sound effect. It no longer works in iOS 9 after changing the code multiple times. This is what I've tried:
Original:
let bangSoundEffect = SKAction.playSoundFileNamed("Bang.mp3", waitForCompletion: false)
runAction(bangSoundEffect)
Other attempt:
self.runAction(SKAction.playSoundFileNamed("Bang.mp3", waitForCompletion: false))
Also:
func playRocketExplosionSound(filename: String) {
let url = NSBundle.mainBundle().URLForResource(
filename, withExtension: nil)
if (url == nil) {
print("Could not find file: \(filename)")
return }
var error: NSError? = nil
do {
backgroundMusicPlayer =
try AVAudioPlayer(contentsOfURL: url!)
} catch let error1 as NSError {
error = error1
backgroundMusicPlayer = nil
}
if backgroundMusicPlayer == nil {
print("Could not create audio player: \(error!)")
return}
backgroundMusicPlayer.numberOfLoops = 1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play() }
playRocketExplosionSound("Bang.mp3")
I'm pulling my hair out. I'm using the same code in a different scene for another sound effect and it works fine!! What's going wrong?
I've noticed that the sound effect begins to play sometimes in the simulator, however it doesn't complete and throws this error:
2015-09-24 19:12:14.554 APPNAME[4982:270835] 19:12:14.553 ERROR: 177: timed out after 0.012s (735 736); mMajorChangePending=0
It doesn't work at all on actual devices.
What is the problem? :'(
Possible problem with MP3 file
The problem is most likely connected with the MP3 file you're using. The code works for other sounds, this suggests that the MP3 file might be corrupted and AVAudioPlayer fails with decoding it. You can try re-encode this file and see if the problem persists. Or, even better, converting it to WAV.
Using WAVs
General rule of the thumb when creating short sound effects for games, is to use WAV unless you really feel you need the trim the fat.
Top-notch games are going for top-of-the-line production quality, so they record and produce assets uncompressed 24bit/48kHz. Titles with slightly lesser ambitions might record and produce in 16/44.1, which is the official standard for CD quality audio.
This has at least two benefits. One is that the sound has a better quality. Second one, the CPU does not have to decode the file to play it.
Corrupt data file | AVAudioPlayer out of scope
1. Corrupt data file
This will ensure you have found the file:
var backgroundMusicPlayer: AVAudioPlayer? = nil
if let url = Bundle.main.url(
forResource: "Bang", withExtension: "mp3") {
do {
try backgroundMusicPlayer = AVAudioPlayer(contentsOf: url)
backgroundMusicPlayer!.play()
} catch {}
}
return nil
2. AVAudioPlayer out of scope
The variable retaining backgroundMusicPlayer must not go out of scope before play() has completed and returns. This is generally achieved by using a class variable:
var backgroundMusicPlayer: AVAudioPlayer? = nil
Don't do this: the following sound will play for, at best, outOfScopeDelay due to the local scope of var audioPlayer.
let outOfScopeDelay = 0.5
do {
var audioPlayer:AVAudioPlayer! // Incorrectly scoped variable
try audioPlayer = AVAudioPlayer(contentsOf: audioRecorder.url)
audioPlayer.play()
Thread.sleep(forTimeInterval: outOfScopeDelay)
} catch {}
► Find this solution on GitHub and additional details on Swift Recipes.
try this:
dispatch_async(dispatch_get_main_queue(), {
(self.playRocketExplosionSound("Bang.mp3")
})
it's no longer safe to play audio in child thread under iOS 9.

XCode 7 Swift - Call can throw, it it is not markedwith 'try' and the error is not handled

I'm trying to play music on my iOS application when I click a button and I already know how to do it but this time when I insert the line; audioPlayer = AVAudioPlayer(contentsOfURL: audioPlayerURL, error: nil)it will give me an option to change errorto fileTypeHintwhich I do but then I get the following error; `Call can throw, it it is not markedwith 'try' and the error is not handled'.
I don't really understand because in Xcode 6 I used the word error in that line of code and I had no issues with that and playing music was working. There must be a different or similar way of writing that line since I've upgraded to Xcode 7 Beta 3 but I've searched everywhere to see what's changed.
Would anybody know anything about it?
Error handling has changed in Swift 2.0. Use the following try-catch code to resolve the error:
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: audioFileUrl,
fileTypeHint: AVFileTypeMPEGLayer3)
} catch let error as NSError {
print("AV Sound Error: \(error.localizedDescription)")
}
I had the same issue, after piecing together some information this is what I came up with and it works in Swift 2.0.
override func viewWillLayoutSubviews() {
let bgMusicURL:NSURL = NSBundle.mainBundle().URLForResource("bgmusic", withExtension: "mp3")!
backgroundMusicPlayer = try! AVAudioPlayer(contentsOfURL: bgMusicURL)
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play()
}
Make sure to Import AVFoundation
and also add this in your controller
var backgroundMusicPlayer:AVAudioPlayer = AVAudioPlayer()

Resources