Sprite kit OpenAL vs AVAudioPlayer vs其他播放声音的技术
我知道OpenAL是一个快速库,但它不支持任何压缩音频格式,而且使用起来也不那么容易 AVAudioPlayer速度不太快,但支持多种文件格式,以及mp3等压缩格式 还有一个SKAction类可以播放声音,以及SystemSoundID 我有几个问题:Sprite kit OpenAL vs AVAudioPlayer vs其他播放声音的技术,sprite-kit,avaudioplayer,openal,skaction,Sprite Kit,Avaudioplayer,Openal,Skaction,我知道OpenAL是一个快速库,但它不支持任何压缩音频格式,而且使用起来也不那么容易 AVAudioPlayer速度不太快,但支持多种文件格式,以及mp3等压缩格式 还有一个SKAction类可以播放声音,以及SystemSoundID 我有几个问题: 首选的打法/球员/技术是什么: 音效(一次多个) 有时在小时间延迟后可以重复的声音效果 循环播放的背景音乐 另外,使用未压缩音频进行声音效果是明智之举吗?我想这没问题,因为这些文件的大小很小 我个人在用。这很好,因为它利用了OpenAL和AV
- 音效(一次多个)
- 有时在小时间延迟后可以重复的声音效果
- 循环播放的背景音乐
据我所知,未压缩音频更好。你只需要确保预先加载声音,这样你的游戏就不会在每次播放声音时都试图拉文件。这个非常简单的类为我完美地服务了多个项目,同时运行了很多声音。我发现这比在OpenAL上大惊小怪要简单得多。它有你要求的一切,预先设置的声音,多个并发播放,延迟后,背景循环 不管您是否使用压缩文件,因为您首先设置了它 SKAudio.h
#import <Foundation/Foundation.h>
@import AVFoundation;
@interface SKAudio : NSObject
+(AVAudioPlayer*)setupRepeatingSound:(NSString*)file volume:(float)volume;
+(AVAudioPlayer*)setupSound:(NSString*)file volume:(float)volume;
+(void)playSound:(AVAudioPlayer*)player;
+(void)playSound:(AVAudioPlayer*)player afterDelay:(float)delaySeconds;
+(void)pauseSound:(AVAudioPlayer*)player;
@end
要在游戏中使用:
设置一个类变量并将其与声音一起预加载:
static AVAudioPlayer *whooshHit;
static AVAudioPlayer *bgMusic;
+(void)preloadShared {
// cache all the sounds in this class
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
whooshHit = [SKAudio setupSound:@"whoosh-hit-chime-1.mp3" volume:1.0];
// setup background sound with a lower volume
bgMusic = [SKAudio setupRepeatingSound:@"background.mp3" volume:0.3];
});
}
...
// whoosh with delay
[SKAudio playSound:whooshHit afterDelay:1.0];
...
// whoosh and shrink SKAction
SKAction *whooshAndShrink = [SKAction group:@[
[SKAction runBlock:^{ [SKAudio playStarSound:whooshHit afterDelay:1.0]; }],
[SKAction scaleTo:0 duration:1.0]]];
...
[SKAudio playSound:bgMusic];
...
[SKAudio pauseSound:bgMusic];
这是@patrick对Swift 3的解决方案的一个端口
import AVFoundation
// MARK -
// MARK setup sound
// get a repeating sound
func setupRepeatingSound(file: String, volume: Float) -> AVAudioPlayer? {
let sound: AVAudioPlayer? = setupSound(file: file, volume: volume)
sound?.numberOfLoops = -1
return sound
}
// setup a sound
func setupSound(file: String, volume: Float) -> AVAudioPlayer? {
var sound: AVAudioPlayer?
if let path = Bundle.main.path(forResource: file, ofType:nil) {
let url = NSURL(fileURLWithPath: path)
do {
sound = try AVAudioPlayer(contentsOf: url as URL)
} catch {
// couldn't load file :(
}
}
sound?.numberOfLoops = 0
sound?.volume = volume
sound?.prepareToPlay()
return sound
}
// MARK sound controls
// play a sound now through GCD
func playSound(_ sound: AVAudioPlayer?) {
if sound != nil {
DispatchQueue.global(qos: .default).async {
sound!.play()
}
}
}
// play a sound later through GCD
func playSound(_ sound: AVAudioPlayer?, afterDelay: Float) {
if sound != nil {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(afterDelay)) {
sound!.play()
}
}
}
// pause a currently running sound (mostly for background music)
func pauseSound(_ sound: AVAudioPlayer?) {
sound?.pause()
}
这看起来很简单,我会试试看。但我不确定我是否理解示例中的dealloc方法……为什么我们手动调用release?我认为您在示例中看到了release,因为它可能是在arc之前创建的。这是一个相当古老的图书馆。您可能不需要使用release或retain。啊,我理解。谢谢我终于尝试了ObjectAL,它看起来非常适合播放多个短声音。但有一个问题。它与电话中断有关。。。你经历过这样的事情吗很抱歉直接与您联系,但我认为您可能知道如何处理此问题,因为您提到您的游戏已使用ObjectAL。非常感谢您的回复,我会尝试一下。我听说过这种方法(通过GCD播放声音),但从未见过它的实际实现。
import AVFoundation
// MARK -
// MARK setup sound
// get a repeating sound
func setupRepeatingSound(file: String, volume: Float) -> AVAudioPlayer? {
let sound: AVAudioPlayer? = setupSound(file: file, volume: volume)
sound?.numberOfLoops = -1
return sound
}
// setup a sound
func setupSound(file: String, volume: Float) -> AVAudioPlayer? {
var sound: AVAudioPlayer?
if let path = Bundle.main.path(forResource: file, ofType:nil) {
let url = NSURL(fileURLWithPath: path)
do {
sound = try AVAudioPlayer(contentsOf: url as URL)
} catch {
// couldn't load file :(
}
}
sound?.numberOfLoops = 0
sound?.volume = volume
sound?.prepareToPlay()
return sound
}
// MARK sound controls
// play a sound now through GCD
func playSound(_ sound: AVAudioPlayer?) {
if sound != nil {
DispatchQueue.global(qos: .default).async {
sound!.play()
}
}
}
// play a sound later through GCD
func playSound(_ sound: AVAudioPlayer?, afterDelay: Float) {
if sound != nil {
DispatchQueue.main.asyncAfter(deadline: .now() + Double(afterDelay)) {
sound!.play()
}
}
}
// pause a currently running sound (mostly for background music)
func pauseSound(_ sound: AVAudioPlayer?) {
sound?.pause()
}