首页 > 代码库 > iOS开发拓展篇—封装音频文件播放工具类
iOS开发拓展篇—封装音频文件播放工具类
iOS开发拓展篇—封装音频文件播放工具类
一、简单说明
1.关于音乐播放的简单说明
(1)音乐播放用到一个叫做AVAudioPlayer的类
(2)AVAudioPlayer常用方法
加载音乐文件
- (id)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError;
- (id)initWithData:(NSData *)data error:(NSError **)outError;
准备播放(缓冲,提高播放的流畅性) - (BOOL)prepareToPlay;
播放(异步播放)- (BOOL)play;
暂停 - (void)pause;
停止- (void)stop;
是否正在播放 @property(readonly, getter=isPlaying) BOOL playing;
时长 @property(readonly) NSTimeInterval duration;
当前的播放位 @property NSTimeInterval currentTime;
播放次数(-1代表无限循环播放,其他代表播放numberOfLoops+1次 @property NSInteger numberOfLoops;
音量 @property float volume;
是否允许更改速率@property BOOL enableRate;
播放速率(1是正常速率,0.5是一般速率,2是双倍速率) @property float rate;
有多少个声道 @property(readonly) NSUInteger numberOfChannels;
2.播放多个音乐文件
说明:如果要播放多个音乐文件,那么最傻瓜的做法是,创建多个全局的播放器去播放对应的音乐文件,但是这种方法无法适用于需要播放的文件数量巨大的情况。
1 // 2 // YYAudioTool.h 3 // 17-多个音乐文件的播放 4 // 5 // Created by apple on 14-8-9. 6 // Copyright (c) 2014年 yangyong. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h>10 #import <AVFoundation/AVFoundation.h>11 @interface YYAudioTool : NSObject12 /**13 *播放音乐文件14 */15 +(BOOL)playMusic:(NSString *)filename;16 /**17 *暂停播放18 */19 +(void)pauseMusic:(NSString *)filename;20 /**21 *播放音乐文件22 */23 +(void)stopMusic:(NSString *)filename;24 @end
YYAudioTool.m文件
1 // 2 // YYAudioTool.m 3 // 17-多个音乐文件的播放 4 // 5 // Created by apple on 14-8-9. 6 // Copyright (c) 2014年 yangyong. All rights reserved. 7 // 8 9 #import "YYAudioTool.h"10 11 @implementation YYAudioTool12 /**13 *存放所有的音乐播放器14 */15 static NSMutableDictionary *_musices;16 +(NSMutableDictionary *)musices17 {18 if (_musices==nil) {19 _musices=[NSMutableDictionary dictionary];20 }21 return _musices;22 }23 24 /**25 *播放音乐26 */27 +(BOOL)playMusic:(NSString *)filename28 {29 if (!filename) return NO;//如果没有传入文件名,那么直接返回30 //1.取出对应的播放器31 AVAudioPlayer *player=[self musices][filename];32 33 //2.如果播放器没有创建,那么就进行初始化34 if (!player) {35 //2.1音频文件的URL36 NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];37 if (!url) return NO;//如果url为空,那么直接返回38 39 //2.2创建播放器40 player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];41 42 //2.3缓冲43 if (![player prepareToPlay]) return NO;//如果缓冲失败,那么就直接返回44 45 //2.4存入字典46 [self musices][filename]=player;47 }48 49 //3.播放50 if (![player isPlaying]) {51 //如果当前没处于播放状态,那么就播放52 return [player play];53 }54 55 return YES;//正在播放,那么就返回YES56 }57 58 +(void)pauseMusic:(NSString *)filename59 {60 if (!filename) return;//如果没有传入文件名,那么就直接返回61 62 //1.取出对应的播放器63 AVAudioPlayer *player=[self musices][filename];64 65 //2.暂停66 [player pause];//如果palyer为空,那相当于[nil pause],因此这里可以不用做处理67 68 }69 70 +(void)stopMusic:(NSString *)filename71 {72 if (!filename) return;//如果没有传入文件名,那么就直接返回73 74 //1.取出对应的播放器75 AVAudioPlayer *player=[self musices][filename];76 77 //2.停止78 [player stop];79 80 //3.将播放器从字典中移除81 [[self musices] removeObjectForKey:filename];82 }83 @end
测试程序:
在storyboard中拖拽控件,并进行连线,以做控制。
导入可供播放的音乐素材。
测试程序的代码设计如下:
1 // 2 // YYViewController.m 3 // 17-多个音乐文件的播放 4 // 5 // Created by apple on 14-8-9. 6 // Copyright (c) 2014年 yangyong. All rights reserved. 7 // 8 9 #import "YYViewController.h"10 #import "YYAudioTool.h"11 12 @interface YYViewController ()13 - (IBAction)play;14 - (IBAction)pause;15 - (IBAction)stop;16 - (IBAction)next;17 18 //用一个数组来保存所有的音乐文件19 @property(nonatomic,strong)NSArray *songs;20 //用一个int型的属性来记录当前的索引21 @property(nonatomic,assign)int currentIndex;22 @end23 24 @implementation YYViewController25 #pragma mark-懒加载26 -(NSArray *)songs27 {28 if (_songs==nil) {29 self.songs=@[@"235319.mp3",@"309769.mp3",@"120125029.mp3"];30 }31 return _songs;32 }33 34 - (void)viewDidLoad35 {36 [super viewDidLoad];37 }38 39 - (IBAction)play {40 //开始播放/继续播放41 [YYAudioTool playMusic:self.songs[self.currentIndex]];42 }43 44 - (IBAction)pause {45 //暂停播放46 [YYAudioTool pauseMusic:self.songs[self.currentIndex]];47 }48 49 - (IBAction)stop {50 //停止播放51 [YYAudioTool stopMusic:self.songs[self.currentIndex]];52 }53 54 //播放下一首55 - (IBAction)next {56 //1.先停止当前播放57 [self stop];58 59 //2.设置当前索引+160 self.currentIndex++;61 if (self.currentIndex>=self.songs.count) {62 self.currentIndex=0;63 }64 65 //3.播放音乐66 [self play];67 }68 @end
二、对工具类进行改造,让其兼能播放音效文件
说明:
音效只有创建、播放和销毁(停止)三个操作,因为音效一般都很短,因此没有暂停的方法。
把对音效文件的播放加入到工具类中,实现的代码如下:
YYAudioTool.h文件
1 // 2 // YYAudioTool.h 3 // 17-多个音乐文件的播放 4 // 5 // Created by apple on 14-8-9. 6 // Copyright (c) 2014年 yangyong. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h>10 #import <AVFoundation/AVFoundation.h>11 @interface YYAudioTool : NSObject12 /**13 *播放音乐文件14 */15 +(BOOL)playMusic:(NSString *)filename;16 /**17 *暂停播放18 */19 +(void)pauseMusic:(NSString *)filename;20 /**21 *播放音乐文件22 */23 +(void)stopMusic:(NSString *)filename;24 25 /**26 *播放音效文件27 */28 +(void)playSound:(NSString *)filename;29 /**30 *销毁音效31 */32 +(void)disposeSound:(NSString *)filename;33 @end
YYAudioTool.m文件
1 // 2 // YYAudioTool.m 3 // 17-多个音乐文件的播放 4 // 5 // Created by apple on 14-8-9. 6 // Copyright (c) 2014年 yangyong. All rights reserved. 7 // 8 9 #import "YYAudioTool.h" 10 11 @implementation YYAudioTool 12 /** 13 *存放所有的音乐播放器 14 */ 15 static NSMutableDictionary *_musicPlayers; 16 +(NSMutableDictionary *)musicPlayers 17 { 18 if (_musicPlayers==nil) { 19 _musicPlayers=[NSMutableDictionary dictionary]; 20 } 21 return _musicPlayers; 22 } 23 24 /** 25 *存放所有的音效ID 26 */ 27 static NSMutableDictionary *_soundIDs; 28 +(NSMutableDictionary *)soundIDs 29 { 30 if (_soundIDs==nil) { 31 _soundIDs=[NSMutableDictionary dictionary]; 32 } 33 return _soundIDs; 34 } 35 36 37 /** 38 *播放音乐 39 */ 40 +(BOOL)playMusic:(NSString *)filename 41 { 42 if (!filename) return NO;//如果没有传入文件名,那么直接返回 43 //1.取出对应的播放器 44 AVAudioPlayer *player=[self musicPlayers][filename]; 45 46 //2.如果播放器没有创建,那么就进行初始化 47 if (!player) { 48 //2.1音频文件的URL 49 NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil]; 50 if (!url) return NO;//如果url为空,那么直接返回 51 52 //2.2创建播放器 53 player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil]; 54 55 //2.3缓冲 56 if (![player prepareToPlay]) return NO;//如果缓冲失败,那么就直接返回 57 58 //2.4存入字典 59 [self musicPlayers][filename]=player; 60 } 61 62 //3.播放 63 if (![player isPlaying]) { 64 //如果当前没处于播放状态,那么就播放 65 return [player play]; 66 } 67 68 return YES;//正在播放,那么就返回YES 69 } 70 71 +(void)pauseMusic:(NSString *)filename 72 { 73 if (!filename) return;//如果没有传入文件名,那么就直接返回 74 75 //1.取出对应的播放器 76 AVAudioPlayer *player=[self musicPlayers][filename]; 77 78 //2.暂停 79 [player pause];//如果palyer为空,那相当于[nil pause],因此这里可以不用做处理 80 81 } 82 83 +(void)stopMusic:(NSString *)filename 84 { 85 if (!filename) return;//如果没有传入文件名,那么就直接返回 86 87 //1.取出对应的播放器 88 AVAudioPlayer *player=[self musicPlayers][filename]; 89 90 //2.停止 91 [player stop]; 92 93 //3.将播放器从字典中移除 94 [[self musicPlayers] removeObjectForKey:filename]; 95 } 96 97 //播放音效 98 +(void)playSound:(NSString *)filename 99 {100 if (!filename) return;101 //1.取出对应的音效102 SystemSoundID soundID=[[self soundIDs][filename] unsignedIntegerValue];103 104 //2.播放音效105 //2.1如果音效ID不存在,那么就创建106 if (!soundID) {107 108 //音效文件的URL109 NSURL *url=[[NSBundle mainBundle]URLForResource:filename withExtension:nil];110 if (!url) return;//如果URL不存在,那么就直接返回111 112 OSStatus status = AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);113 NSLog(@"%ld",status);114 //存入到字典中115 [self soundIDs][filename]=@(soundID);116 }117 118 //2.2有音效ID后,播放音效119 AudioServicesPlaySystemSound(soundID);120 }121 122 //销毁音效123 +(void)disposeSound:(NSString *)filename124 {125 //如果传入的文件名为空,那么就直接返回126 if (!filename) return;127 128 //1.取出对应的音效129 SystemSoundID soundID=[[self soundIDs][filename] unsignedIntegerValue];130 131 //2.销毁132 if (soundID) {133 AudioServicesDisposeSystemSoundID(soundID);134 135 //2.1销毁后,从字典中移除136 [[self soundIDs]removeObjectForKey:filename];137 }138 }139 @end
代码测试:
代码说明:
打印的值为0,播放成功(因为函数是C++中的)