iOS:如何播放audio没有FPS滴?

我正在使用Sprite Kit开发iOS 9+游戏,最好使用Swift库。

目前我正在使用一个Singleton,我预先加载我的audio文件,每个连接到一个单独的AVAudioPlayer实例。

下面是一个简短的代码,以获得这个想法:

import SpriteKit import AudioToolbox import AVFoundation class AudioEngine { static let sharedInstance = AudioEngine() internal var sfxPing: AVAudioPlayer private init() { self.sfxPing = AVAudioPlayer() if let path = NSBundle.mainBundle().pathForResource("ping", ofType: "m4a") { do { let url = NSURL(fileURLWithPath:path) sfxPing = try AVAudioPlayer(contentsOfURL: url) sfxPing.prepareToPlay() } catch { print("ERROR: Can't load ping.m4a audio file.") } } } } 

这个Singleton在应用程序启动时初始化。 在游戏循环中,我只需调用以下行来播放特定的audio文件:

 AudioEngine.sharedInstance.sfxPing.play() 

这基本上可以工作,但是当我播放一个文件,并且在iPad Air上,帧频从60.0下降到56.0时,我总会遇到一些小问题。

有人有任何想法如何解决这个AVAudioPlayer的性能问题?

我还注意到了第三方库,即:

  • AudioKit [看起来非常重]
  • ObjectAL [最新更新2013 …]
  • AVAudioEngine [基于AVAudioPlayer,同样的问题?]

要求:

  • 播放很多很短的样本(如镜头,点击等)。
  • 发挥一些电机效应(因此投球会很好)
  • 在循环中播放一些背景/环境声音
  • 没有讨厌的毛刺/帧率下降!

你可以推荐上面提到的任何一个库,或者使用上面的代码指出问题吗?

更新:

播放简短的声音:

 self.runAction(SKAction.playSoundFileNamed("sfx.caf", waitForCompletion: false)) 

确实提高了帧率。 我将Audiacity的audio文件导出为.caf格式(Apple的Core Audio Format)。 但在本教程中,他们用“ Signed 32-bit PCM ”编码导出,导致我的audio播放受到干扰。 使用任何其他编码选项( 32-bit floatU-LawA-Law等)对我来说工作的很好。

为什么使用caf格式? 因为它是未压缩的,所以与m4a这样的压缩格式相比,可以更快地将其加载到内存中,而CPU占用更less。 短暂的声音效果在很短的时间间隔内发挥了很大的作用,这对于消耗less量千字节的短小audio文件来说并不重要。 对于更大的audio文件,如环境和背景音乐,使用压缩格式( mp3m4a )显然是更好的select。

根据你的问题,如果你为iOS 9+开发游戏,你可以使用新的iOS 9库SKAudioNode ( 苹果官方文档 ):

 var backgroundMusic: SKAudioNode! 

例如,你可以添加到didMoveToView()

 if let musicURL = NSBundle.mainBundle().URLForResource("music", withExtension: "m4a") { backgroundMusic = SKAudioNode(URL: musicURL) addChild(backgroundMusic) } 

你也可以用来发挥一个简单的效果:

 let beep = SKAudioNode(fileNamed: "beep.wav") beep.autoplayLooped = false self.addChild(beep) 

最后,如果你想改变音量:

 beep.runAction(SKAction.changeVolumeTo(0.4, duration: 0)) 

更新

我看你有更新你的问题谈到AVAudioPlayerSKAction 。 我已经testing了他们两个我的iOS8 +兼容游戏。

关于AVAudioPlayer ,我个人使用了一个由我自己创build的基于旧SKTAudio的自定义库。

我看到你的代码,关于AVAudioPlayer初始化,和我的代码是不同的,因为我使用:

 @available(iOS 7.0, *) public init(contentsOfURL url: NSURL, fileTypeHint utiString: String?) 

我不知道如果fileTypeHint有所作为,所以试着把我的关于你的testing。

您的代码优势 :使用基于AVAudioPlayer的共享实例audiopipe理器,您可以控制音量,随心所欲地使用您的pipe理器,确保与iOS8兼容

你的代码的缺点 :每次你发出声音,你想播放另一个声音,以前是打破了,特别是如果你有启动背景音乐。

怎么解决? 根据这个SO post ,没有问题似乎AVFoundation是有限的4个AVAudioPlayer属性instantiables,所以你可以这样做:

  • 1)backgroundMusicPlayer:AVAudioPlayer!
  • 2)soundEffectPlayer1:AVAudioPlayer!
  • 3)soundEffectPlayer2:AVAudioPlayer!
  • 4)soundEffectPlayer3:AVAudioPlayer!

你可以build立一个方法,通过3 soundEffect切换,看是否被占用:

 if player.playing 

并使用下一个免费播放器。 有了这个解决方法,你总是可以正确播放你的声音,甚至是你的背景音乐。