Reputation: 349
I've got a vexing problem with getting sound to play in a game but can't seem to get any output through the AVAudioPlayer. Originally this was set up as a class but when it didn't work I tried hardcoding a sound output just to check if there was a problem there. It still didn't work and I tried a few different files to rule out a problematic audio file or format.The URL is being retrieved but the audioPlayer simply seems to be outputting no sound.
I've read a few threads about similar issues and fiddled with system sound settings but it's made no difference. It's been suggested that the Simulator can't output sound in some circumstances but I don't believe this is the case here.
let myFile = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("gong", ofType: "wav")!)
print ("URL data: \(myFile)")
do{
let audioPlayer = try AVAudioPlayer(contentsOfURL:myFile)
audioPlayer.prepareToPlay()
audioPlayer.play()
}catch {
print("Error playing sound")
}
However this plays fine:
self.runAction(SKAction.playSoundFileNamed("gong", waitForCompletion: false))
I need the functionality of AVAudioPlayer as I want to be able to start stop and control the volume of the sound as it loops. I'm using XCode 7.3.1 and Swift 2.2.
Any ideas?
Many thanks, Kw
Upvotes: 2
Views: 267
Reputation: 3158
I would like to add an answer that helps me. AVAudioPlayer
's play()
method is asynchronous, so I've actually found the best way to play a sound file without experiencing lag the first time it's loaded into memory is by calling it asynchronously:
SWIFT 2
import AVFoundation
var audioPlayer: AVAudioPlayer?
init() {
let soundURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("FileName", ofType: "wav")!)
if let soundURL = soundURL {
do {
self.audioPlayer = try AVAudioPlayer(contentsOfURL: soundURL)
} catch let error as NSError {
print(error.description)
}
} else {
// Handle situation where URL isn't found
print("Sound file URL not found")
}
}
func playSound() {
guard let audioPlayer = audioPlayer else { return }
// Now we can play the sound asynchronously - which will eliminate any lag upon initial play
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
audioPlayer.play()
})
}
SWIFT 3
import AVFoundation
var audioPlayer: AVAudioPlayer?
init() {
let soundURL = URL(fileURLWithPath: Bundle.main.path(forResource: "FileName", ofType: "wav")!)
if let soundURL = soundURL {
do {
self.audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
} catch let error {
print(error.description)
}
} else {
// Handle situation where URL isn't found
print("Sound file URL not found")
}
}
func playSound() {
guard let audioPlayer = audioPlayer else { return }
// Now we can play the sound asynchronously - which will eliminate any lag upon initial play
DispatchQueue.global().async {
audioPlayer.play()
}
}
The idea of this is to incorporate some sort of SoundManager class into your model. I usually create a class like this that has an AVAudioPlayer
for every sound I need throughout my app, and I can instantiate it when I load my ViewController - which will initialize the individual audioPlayers upon it's own init()
method. Then I can play each file by using my own play methods. If you have a bunch of different sounds, it can also help to use an enum
to organize different files, and have one custom play()
method that will play whichever file is passed in as a request.
Upvotes: 0
Reputation: 35392
Speaking about Swift 2, I think you should try a different approach to get the url:
import AVFoundation
func playMusic(filename: String) {
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
if (url == nil) {
print("Could not find file: \(filename)")
return
}
do { backgroundMusicPlayer = try AVAudioPlayer(contentsOfURL: url!, fileTypeHint: nil) }
catch let error as NSError { print(error.description) }
if let player = backgroundMusicPlayer {
player.volume = 1
player.numberOfLoops = -1
player.prepareToPlay()
player.play()
}
}
Upvotes: 1