在很多游戲中则涯,當(dāng)執(zhí)行某個(gè)動(dòng)作的時(shí)候,會發(fā)出聲音赘被∈钦或者在設(shè)置界面,點(diǎn)擊按鈕的時(shí)候也會發(fā)出聲音民假。這些聲音一般比較短,瞬間就可以播放完龙优。這就是音效羊异,時(shí)間長度在30秒之內(nèi)的音頻事秀,我們把它們歸為音效播放。
iOS中播放音效和音樂需要用不同的方式野舶。###
基本實(shí)現(xiàn)步驟:
1.導(dǎo)入框架易迹,AVFoundation
2.創(chuàng)建音效文件
3.AudioServicesCreateSystemSoundID,C語言的方法平道,涉及到CF的內(nèi)容睹欲,需要橋接
4.在mainBundle中,獲取音頻文件的URL
5.兩種播放方式
不帶震動(dòng)的播放
帶震動(dòng)的播放一屋,真機(jī)才有效果
6.清空音效
如果不需要播放了窘疮,需要釋放音效所占用的內(nèi)存
工具類方法:
VRAudioTools.h
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
@interface VRAudioTools : NSObject
/** 播放系統(tǒng)音效*/
+ (void)playSystemSoundWithURL:(NSURL *)url;
/** 播放震動(dòng)音效*/
+ (void)playAlertSoundWithURL:(NSURL *)url;
/** 清空音效文件的內(nèi)存*/
+ (void)clearMemory;
@end
VRAudioTools.m
/** 緩存字典*/
static NSMutableDictionary *_soundIDDict;
@implementation VRAudioTools
// 只要頭文件參與了編譯調(diào)用
//+ (void)load
/** 緩存字典初始化*/
+ (void)initialize
{
_soundIDDict = [NSMutableDictionary dictionary];
}
+ (void)playSystemSoundWithURL:(NSURL *)url
{
// 不帶震動(dòng)的播放
AudioServicesPlaySystemSound([self loadSoundIDWithURL:url]);
}
/** 播放震動(dòng)音效*/
+ (void)playAlertSoundWithURL:(NSURL *)url
{
// 帶震動(dòng)的播放
AudioServicesPlayAlertSound([self loadSoundIDWithURL:url]);
}
#pragma mark 播放音效的公用方法
+ (SystemSoundID)loadSoundIDWithURL:(NSURL *)url
{
// 思路思路
// soundID重復(fù)創(chuàng)建 --> soundID每次創(chuàng)建, 就會有對應(yīng)的URL地址產(chǎn)生
// 可以將創(chuàng)建后的soundID 及 對應(yīng)的URL 進(jìn)行緩存處理
//1. 獲取URL的字符串
NSString *urlStr = url.absoluteString;
//2. 從緩存字典中根據(jù)URL來取soundID 系統(tǒng)音效文件,SystemSoundID==UInt32
SystemSoundID soundID = [_soundIDDict[urlStr] intValue];
//需要在剛進(jìn)入的時(shí)候, 判斷緩存字典是否有url對應(yīng)的soundID
//3. 判斷soundID是否為0, 如果為0, 說明沒有找到, 需要?jiǎng)?chuàng)建
if (soundID == 0) {
//3.1 創(chuàng)建音效文件
AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);
//3.2 緩存字典的添加鍵值
_soundIDDict[urlStr] = @(soundID);
}
return soundID;
}
/** 清空音效文件的內(nèi)存*/
+ (void)clearMemory
{
//1. 遍歷字典
[_soundIDDict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
//2. 清空音效文件的內(nèi)存
SystemSoundID soundID = [obj intValue];
AudioServicesDisposeSystemSoundID(soundID);
}];
}
@end
在需要播放音效的控制器文件中調(diào)用:
#pragma mark 點(diǎn)擊播放音效
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//1. 獲取URL地址
NSURL *url = [[NSBundle mainBundle] URLForResource:@"xxx.wav" withExtension:nil];
//2. 調(diào)用工具類播放音效
//[VRAudioTools playSystemSoundWithURL:url];
[VRAudioTools playAlertSoundWithURL:url];
}
#pragma mark 當(dāng)前控制器收到內(nèi)存警告時(shí)會調(diào)用的方法
- (void)didReceiveMemoryWarning
{
// 局部音效需要在這里進(jìn)行釋放
[VRAudioTools clearMemory];
NSLog(@"%s",__func__);
}
當(dāng)需要釋放全局的音效的時(shí)候(比如多個(gè)控制器里都有音效需要釋放)要在 AppDelegate里釋放
AppDelegate.m
#pragma mark 清空全局的音效文件
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
[VRAudioTools clearMemory];
//NSLog(@"%s",__func__);
}```