我正在尝试在不使用SpriteKit的情况下在iOS中创建游戏。 我被困在及时发挥声音效果。我一直在使用我在网上找到的以下代码,背景音乐效果很好。但是,当我使用的时候 " playSoundEffect"方法它第一次播放然后开始落后并变得不同步。我想这是因为它每次都初始化一个AVAudioPlayer。 任何人都知道如何及时播放音效,同时还播放背景音乐?谢谢!
import AVFoundation
public class SKTAudio: NSObject, AVAudioPlayerDelegate {
public var backgroundMusicPlayer: AVAudioPlayer?
public var soundEffectPlayer: AVAudioPlayer?
private var mainLoopFileName:String! {
let randomSong = Int(arc4random_uniform(3))
switch randomSong {
//case 0: return "Test.mp3"
//case 1: return "Test2.mp3"
case 0: return "SneakySnitch.mp3"
case 1: return "FasterDoesIt.mp3"
case 2: return "MonkeysSpinningMonkeys.mp3"
default:
break
}
return "SneakySnitch.mp3"
}
public class func sharedInstance() -> SKTAudio {
return SKTAudioInstance
}
public func playBackgroundMusic() {
let filename = mainLoopFileName
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
if (url == nil) {
println("Could not find file: \(filename)")
return
}
var error: NSError? = nil
backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: url, error: &error)
if let player = backgroundMusicPlayer {
player.numberOfLoops = 0
player.delegate = self
player.prepareToPlay()
player.play()
} else {
println("Could not create audio player: \(error!)")
}
}
public func pauseBackgroundMusic() {
if let player = backgroundMusicPlayer {
if player.playing {
player.pause()
}
}
}
public func resumeBackgroundMusic() {
if let player = backgroundMusicPlayer {
if !player.playing {
player.play()
}
}
}
public func playSoundEffect(filename: String) {
let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil)
if (url == nil) {
println("Could not find file: \(filename)")
return
}
var error: NSError? = nil
soundEffectPlayer = AVAudioPlayer(contentsOfURL: url, error: &error)
if let player = soundEffectPlayer {
player.numberOfLoops = 0
player.prepareToPlay()
player.play()
} else {
println("Could not create audio player: \(error!)")
}
}
// MARK: AVAudioPlayerDelegate
public func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) {
println("finished playing \(flag)")
delay(5.0, {
self.playBackgroundMusic()
})
}
public func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer!, error: NSError!) {
println("\(error.localizedDescription)")
}
}
答案 0 :(得分:1)
您可以使用AVPlayer播放声音文件。保留一个播放器,但在需要播放新声音时将其AVPlayerItem
更改为新项目。它可能比每次重新创建播放器更快。
虽然AVAudioPlayer
/ AVPlayer
是最简单的选项,但在播放音频文件时它不会给您最短的延迟或完美的同步。您应该查看Core Audio中的音频队列或音频单元,以获得更准确的声音播放。
答案 1 :(得分:0)
问题是你在第一个声音效果完成之前正在播放第二个声音效果。当您将新的AVAudioPlayer
设置为soundEffectPlayer
变量并且第一个将停止播放时,您将删除对第一个的引用。
如果你不介意失去控制声音音量的可用性,你可以使用它:
var mySound: SystemSoundID = 0
AudioServicesCreateSystemSoundID(url, &mySound)
// Play
AudioServicesPlaySystemSound(mySound)
否则,如果将创建的每个声音添加到数组中,则可以使用AVAudioPlayer
,保留引用。然后,您可以通过实施AVAudioPlayer
委托来完成声音删除。
func playSound(){
let path : NSString? = NSBundle.mainBundle().pathForResource("sound", ofType: "wav")!
let url = NSURL(fileURLWithPath: path!)
var error : NSError?
let sound = AVAudioPlayer(contentsOfURL: url, error: &error)
sound.delegate = self
sound.volume = 0.5
self.soundsEffectsArray.addObject(sound)
sound.prepareToPlay()
sound.play()
}
func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) {
self.soundsEffectsArray.removeObject(player)
}