【问题标题】:OpenAL vs AVAudioPlayer vs other techniques for playing soundsOpenAL vs AVAudioPlayer vs 其他播放声音的技术
【发布时间】:2015-02-02 21:07:18
【问题描述】:

我知道 OpenAL 是一个快速的库,但它不支持任何压缩音频格式,而且使用起来也不是那么容易......

AVAudioPlayer 没有那么快,但支持范围广泛的文件格式,以及像 mp3 这样的压缩格式。

还有一个可以播放声音的SKAction类,还有SystemSoundID...

我有几个问题:

  1. 什么是首选的游戏方式/玩家/技术:

    • 音效(同时多个)?
    • 声音效果有时会在小时间延迟后重复
    • 循环播放的背景音乐
  2. 另外,使用未压缩的音频来制作音效是明智之举吗?我想这没关系,因为这些文件仍然很小?

【问题讨论】:

    标签: sprite-kit avaudioplayer openal skaction


    【解决方案1】:

    我个人使用ObjectAL。这很好,因为它利用了 OpenAL 和 AVAudioPlayer,但是从你那里抽象出了很多复杂的部分。我的游戏有背景音乐、大量同时播放的声音,以及基于精灵速度增加音量、音高等的可循环声音。 ObjectAL 可以做到所有这些。

    ObjectAL 可以使用它的 OALSimpleAudio 类来播放简单的声音和音乐循环。或者你可以更深入地研究它并做更复杂的事情。

    我专门为我的游戏创建了一个简单的 ObjectAL 包装器,因此它被进一步抽象出来。

    据我所知,未压缩的音频更好。您只需要确保预加载声音,这样您的游戏就不会在每次播放声音时都尝试拉取文件。

    【讨论】:

    • 这个看起来不错,很简单,我试试看。但我不确定我是否理解示例中的 dealloc 方法......为什么我们手动调用 release ?
    • 我认为您在示例中看到了发布,因为这可能是在弧前时代创建的。这是一个相当古老的图书馆。您可能不需要使用释放或保留。
    • 啊,我明白了。谢谢!
    • 我终于尝试了 ObjectAL,它看起来非常适合播放多个短音。但它有一个问题。它与电话中断有关......你有没有经历过这样的事情? :stackoverflow.com/q/32510684/3402095 很抱歉直接与您联系,但我想您可能知道如何处理这个问题,因为您提到您的游戏已经在使用 ObjectAL。
    【解决方案2】:

    这个非常简单的课程完美地为我服务了多个项目,同时运行了许多声音。我发现它比使用 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
    

    SKAudio.m

    #import "SKAudio.h"
    
    @implementation SKAudio
    
    #pragma mark -
    #pragma mark setup sound
    
    // get a repeating sound
    +(AVAudioPlayer*)setupRepeatingSound:(NSString*)file volume:(float)volume {
        AVAudioPlayer *s = [self setupSound:file volume:volume];
        s.numberOfLoops = -1;
        return s;
    }
    
    // setup a sound
    +(AVAudioPlayer*)setupSound:(NSString*)file volume:(float)volume{
        NSError *error;
        NSURL *url = [[NSBundle mainBundle] URLForResource:file withExtension:nil];
        AVAudioPlayer *s = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
        s.numberOfLoops = 0;
        s.volume = volume;
        [s prepareToPlay];
        return s;
    }
    
    #pragma mark sound controls
    
    // play a sound now through GCD
    +(void)playSound:(AVAudioPlayer*)player {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [player play];
        });
    }
    
    // play a sound later through GCD
    +(void)playSound:(AVAudioPlayer*)player afterDelay:(float)delaySeconds {
    
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delaySeconds * NSEC_PER_SEC);
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [player play];
        });
    }
    
    // pause a currently running sound (mostly for background music)
    +(void)pauseSound:(AVAudioPlayer*)player {
        [player pause];
    }
    
    @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];
    

    【讨论】:

    • 非常感谢您的回复,我试试看。我听说过这种方法(通过 GCD 播放声音),但从未见过它的实际实现。
    【解决方案3】:

    这是@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()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多