OpenAL vs AVAudioPlayer vs other techniques for playing sounds

巧了我就是萌 提交于 2019-12-22 08:51:53

问题


I know that OpenAL is fast library but it doesn't support any compressed audio format and it's not so easy to use...

AVAudioPlayer is not so fast, but supports wide range file formats, as well as compressed formats like mp3.

Also there is an SKAction class which can play a sound, as well as SystemSoundID...

I have few questions:

  1. What would be a preferred way/player/technique to play :

    • sound effects(multiple at the time)?
    • sound effects which can be sometimes repeated after small time delay
    • background music that loops
  2. Also, is it smart move to use uncompressed audio for sound effects? I suppose this is ok, because those files have small size anyway?


回答1:


I'm personally using ObjectAL. It's good because it utilizes OpenAL and AVAudioPlayer but abstracts a lot of the complicated parts away from you. My game has background music, tons of sounds playing simultaneously, and loopable sounds that increase in volume, pitch etc based on a sprites speed. ObjectAL can do all of that.

ObjectAL can be used for playing simple sounds and music loops using it's OALSimpleAudio class. Or you can get deeper into it and do more complex things.

I've created a simple wrapper around ObjectAL specifically for my game so it's further abstracted away from me.

From what I've read, uncompressed audio is better. You just need to make sure you preload the sounds so that your game isnt trying to pull the file each time it's playing a sound.




回答2:


This very simple class has serviced multiple projects for me flawlessly with lots of sounds running at the same time. I find it a lot simpler than fussing with OpenAL. It has everything you asked for, pre-setup sounds, multiple concurrent plays, after delay, background loops.

Doesnt matter if you use compressed files or not because you set it up first.

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

To use in your game:

Set up a class variable and pre-load it with your sound:

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];



回答3:


Here's a port of @patrick's solution to 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()
}


来源:https://stackoverflow.com/questions/28286767/openal-vs-avaudioplayer-vs-other-techniques-for-playing-sounds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!