OpenAL против AVAudioPlayer против других методов воспроизведения звуков
Я знаю, что OpenAL - быстрая библиотека, но она не поддерживает сжатый аудиоформат, и его не так просто использовать...
AVAudioPlayer не так быстр, но поддерживает широкий диапазон форматов файлов, а также сжатые форматы, такие как mp3.
Также есть класс SKAction, который может воспроизводить звук, а также SystemSoundID...
У меня есть несколько вопросов:
Какой предпочтительный способ / игрок / техника играть:
- звуковые эффекты (несколько одновременно)
- звуковые эффекты, которые иногда могут повторяться после небольшой задержки
- фоновая музыка, которая петли
Кроме того, разумно ли использовать несжатый звук для звуковых эффектов? Полагаю, это нормально, потому что эти файлы имеют небольшой размер?
3 ответа
Я лично использую ObjectAL. Это хорошо, потому что он использует OpenAL и AVAudioPlayer, но абстрагирует от вас множество сложных деталей. Моя игра имеет фоновую музыку, тонны звуков, играемых одновременно, и зацикливающиеся звуки, которые увеличиваются по громкости, высоте и т. Д. В зависимости от скорости спрайтов. ObjectAL может сделать все это.
ObjectAL можно использовать для воспроизведения простых звуков и музыкальных циклов, используя класс OALSimpleAudio. Или вы можете углубиться в это и делать более сложные вещи.
Я создал простую обертку вокруг ObjectAL специально для своей игры, так что она еще более отвлечена от меня.
Из того, что я прочитал, несжатый звук лучше. Вам просто нужно убедиться, что вы предварительно загрузили звуки, чтобы ваша игра не пыталась извлечь файл при каждом воспроизведении звука.
Этот очень простой класс обслужил несколько проектов для меня безупречно с множеством звуков, работающих одновременно. Я нахожу это намного проще, чем суетиться с 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];
Вот порт решения @ 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()
}