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.播放多个音乐文件

说明:如果要播放多个音乐文件,那么最傻瓜的做法是,创建多个全局的播放器去播放对应的音乐文件,但是这种方法无法适用于需要播放的文件数量巨大的情况。

  另外一种做法是:自己封装一个播放音乐文件的工具类。
 
封装工具类的实现步骤:
  新建一个类,继承自NSObject类。提供三个对外的接口:
  
分别是:
播放音乐(参数:文件名)
暂停音乐(参数:文件名)
停止音乐(参数:文件名)
该工具类中的代码设计如下:
XZAudioTool.h文件
 1 #import <Foundation/Foundation.h>
 2 
 3 @interface XZAudioTool : NSObject
 4 
 5 /**
 6  *  根据音乐文件名称播放音乐
 7  *
 8  *  @param filename 音乐文件名称
 9  */
10 + (void)playMusicWithFilename:(NSString  *)filename;
11 
12 /**
13  *  根据音乐文件名称暂停音乐
14  *
15  *  @param filename 音乐文件名称
16  */
17 + (void)pauseMusicWithFilename:(NSString  *)filename;
18 
19 /**
20  *  根据音乐文件名称停止音乐
21  *
22  *  @param filename 音乐文件名称
23  */
24 + (void)stopMusicWithFilename:(NSString  *)filename;
25 @end
XZAudioTool.m文件测试程序:
  1 #import "XZAudioTool.h"
  2 #import <AVFoundation/AVFoundation.h>
  3 
  4 @implementation XZAudioTool
  5 /**
  6  *  存放所有的音乐播放器
  7  */
  8 static NSMutableDictionary *_players;
  9 + (NSMutableDictionary *)players
 10 {
 11     if (!_players) {
 12         _players = [NSMutableDictionary dictionary];
 13     }
 14     return _players;
 15 }
 16 
 17 /**
 18  *  根据音乐文件名称播放音乐
 19  *
 20  *  @param filename 音乐文件名称
 21  */
 22 + (void)playMusicWithFilename:(NSString  *)filename
 23 {
 24     // 0.判断文件名是否为nil
 25     if (filename == nil) {
 26         return;
 27     }
 28     
 29     // 1.从字典中取出播放器
 30     AVAudioPlayer *player = [self players][filename];
 31     
 32     // 2.判断播放器是否为nil
 33     if (!player) {
 34         NSLog(@"创建新的播放器");
 35         
 36         // 2.1根据文件名称加载音效URL
 37         NSURL *url = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
 38         
 39         // 2.2判断url是否为nil
 40         if (!url) {
 41             return;
 42         }
 43         
 44         // 2.3创建播放器
 45         player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
 46         
 47         // 2.4准备播放
 48         if(![player prepareToPlay])
 49         {
 50             return; //如果缓冲失败,那么就直接返回
 51         }
 52         // 允许快进
 53         player.enableRate = YES;
 54         player.rate = 3;
 55         
 56         // 2.5将播放器添加到字典中
 57         [self players][filename] = player;
 58         
 59     }
 60     // 3.播放音乐
 61     if (!player.playing)
 62     {
 63         [player play];
 64     }
 65    
 66 }
 67 
 68 /**
 69  *  根据音乐文件名称暂停音乐
 70  *
 71  *  @param filename 音乐文件名称
 72  */
 73 + (void)pauseMusicWithFilename:(NSString  *)filename
 74 {
 75     // 0.判断文件名是否为nil
 76     if (filename == nil) {
 77         return;
 78     }
 79     
 80     // 1.从字典中取出播放器
 81     AVAudioPlayer *player = [self players][filename];
 82 
 83     // 2.判断播放器是否存在
 84     if(player)
 85     {
 86         // 2.1判断是否正在播放
 87         if (player.playing)
 88         {
 89             // 暂停
 90             [player pause];
 91         }
 92     }
 93     
 94 }
 95 
 96 /**
 97  *  根据音乐文件名称停止音乐
 98  *
 99  *  @param filename 音乐文件名称
100  */
101 + (void)stopMusicWithFilename:(NSString  *)filename
102 {
103     // 0.判断文件名是否为nil
104     if (filename == nil) {
105         return;
106     }
107     
108     // 1.从字典中取出播放器
109     AVAudioPlayer *player = [self players][filename];
110 
111     // 2.判断播放器是否为nil
112     if (player) {
113         // 2.1停止播放
114         [player stop];
115         // 2.2清空播放器
116 //        player = nil;
117         // 2.3从字典中移除播放器
118         [[self players] removeObjectForKey:filename];
119     }
120 }
121 @end

 在storyboard中拖拽控件,并进行连线,以做控制。

导入可供播放的音乐素材。

测试程序的代码设计如下:

 1 //
 2 //  ViewController.m
 3 //  03-多个音乐文件的播放
 4 //
 5 //  Created by XZ on 14/11/7.
 6 //  Copyright (c) 2014年 github. All rights reserved.
 7 //
 8 
 9 #import "ViewController.h"
10 #import <AVFoundation/AVFoundation.h>
11 #import "XZAudioTool.h"
12 
13 @interface ViewController ()
14 //  播放器
15 @property (nonatomic, strong) AVAudioPlayer *player;
16 
17 // 播放
18 - (IBAction)playMusic;
19 
20 // 暂停
21 - (IBAction)pauseMusic;
22 
23 // 停止
24 - (IBAction)stopMusic;
25 
26 // 下一首
27 - (IBAction)nextMusic;
28 
29 // 用一个数组来保存所有的音乐文件
30 @property (nonatomic, strong) NSArray *musics;
31 
32 // 用一个int型的属性来记录当前播放音乐的索引
33 @property (nonatomic, assign) int  currentIndex;
34 @end
35 
36 @implementation ViewController
37 
38 #pragma mark - 懒加载
39 - (NSArray *)musics
40 {
41     if (!_musics) {
42         _musics = @[@"最佳损友.mp3", @"心碎了无痕.mp3", @"瓦解.mp3", @"简单爱.mp3"];
43     }
44     return _musics;
45 }
46 
47 - (void)viewDidLoad {
48     [super viewDidLoad];
49 }
50 
51 - (IBAction)playMusic {
52     // 开始播放/继续播放
53     [XZAudioTool playMusicWithFilename:self.musics[self.currentIndex]];
54 }
55 
56 - (IBAction)pauseMusic {
57     // 暂停
58     [XZAudioTool pauseMusicWithFilename:self.musics[self.currentIndex]];
59 }
60 
61 - (IBAction)stopMusic {
62     // 停止
63     [XZAudioTool stopMusicWithFilename:self.musics[self.currentIndex]];
64 
65 }
66 
67 - (IBAction)nextMusic {
68     // 下一首
69     
70     // 1.递增索引
71     int nextIndex = self.currentIndex + 1;
72     
73     // 1.1.判断是否越界
74     if (nextIndex >= self.musics.count) {
75         nextIndex = 0;
76     }
77     NSLog(@"当前 %d  下一首 %d",  self.currentIndex, nextIndex);
78     // 2.播放
79     // 2.1停止上一首播放
80     [self stopMusic];
81     self.currentIndex = nextIndex;
82     // 2.2播放下一首
83     [self playMusic];
84 }
85 
86 @end

二、对工具类进行改造,让其兼能播放音效文件

说明:

  音效只有创建、播放和销毁(停止)三个操作,因为音效一般都很短,因此没有暂停的方法。

  

把对音效文件的播放加入到工具类中,实现的代码如下:

XZAudioTool.h文件
 1 #import <Foundation/Foundation.h>
 2 
 3 @interface XZAudioTool : NSObject
 4 /**
 5  *  根据音效文件名称播放音效
 6  *
 7  *  @param filename 音效文件名称
 8  */
 9 + (void)playAudioWithFilename:(NSString  *)filename;
10 
11 /**
12  *  根据音效文件名称销毁音效
13  *
14  *  @param filename 音效文件名称
15  */
16 + (void)disposeAudioWithFilename:(NSString  *)filename;
17 
18 /**
19  *  根据音乐文件名称播放音乐
20  *
21  *  @param filename 音乐文件名称
22  */
23 + (void)playMusicWithFilename:(NSString  *)filename;
24 
25 /**
26  *  根据音乐文件名称暂停音乐
27  *
28  *  @param filename 音乐文件名称
29  */
30 + (void)pauseMusicWithFilename:(NSString  *)filename;
31 
32 /**
33  *  根据音乐文件名称停止音乐
34  *
35  *  @param filename 音乐文件名称
36  */
37 + (void)stopMusicWithFilename:(NSString  *)filename;
38 @end
SLAudioTool.m文件测试程序:
  1 #import "XZAudioTool.h"
  2 #import <AVFoundation/AVFoundation.h>
  3 
  4 @implementation XZAudioTool
  5 /**
  6  *  存放所有的音效ID
  7  */
  8 static NSMutableDictionary *_soundIDs;
  9 + (NSMutableDictionary *)soundIDs
 10 {
 11     if (!_soundIDs) {
 12         _soundIDs = [NSMutableDictionary dictionary];
 13     }
 14     return _soundIDs;
 15 }
 16 
 17 /**
 18  *  存放所有的音乐播放器
 19  */
 20 static NSMutableDictionary *_players;
 21 + (NSMutableDictionary *)players
 22 {
 23     if (!_players) {
 24         _players = [NSMutableDictionary dictionary];
 25     }
 26     return _players;
 27 }
 28 
 29 /**
 30  *  根据音效文件名称播放音乐
 31  *
 32  *  @param filename 音效文件名称
 33  */
 34 + (void)playAudioWithFilename:(NSString *)filename
 35 {
 36     
 37     // 0.判断文件名是否为nil
 38     if (filename == nil) {
 39         return;
 40     }
 41     
 42     // 1.从字典中取出音效ID
 43     SystemSoundID soundID = [[self soundIDs][filename] unsignedIntValue];
 44     
 45     // 判断音效ID是否为nil
 46     if (!soundID) {
 47         NSLog(@"创建新的soundID");
 48         
 49         // 音效ID为nil
 50         // 根据文件名称加载音效URL
 51         NSURL *url = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
 52         
 53         // 判断url是否为nil
 54         if (!url) {
 55             return;
 56         }
 57         
 58         // 创建音效ID
 59         AudioServicesCreateSystemSoundID((__bridge CFURLRef)(url), &soundID);
 60         
 61         // 将音效ID添加到字典中
 62         [self soundIDs][filename] = @(soundID);
 63     }
 64     // 播放音效
 65     AudioServicesPlaySystemSound(soundID);
 66 }
 67 
 68 /**
 69  *  根据音效文件名称销毁音乐
 70  *
 71  *  @param filename 音效文件名称
 72  */
 73 + (void)disposeAudioWithFilename:(NSString *)filename
 74 {
 75     // 0.判断文件名是否为nil
 76     if (filename == nil) {
 77         return;
 78     }
 79     
 80     // 1.从字典中取出音效ID
 81     SystemSoundID soundID = [[self soundIDs][filename] unsignedIntValue];
 82     
 83     if (soundID) {
 84         // 2.销毁音效ID
 85         AudioServicesDisposeSystemSoundID(soundID);
 86         
 87         // 3.从字典中移除已经销毁的音效ID
 88         [[self soundIDs] removeObjectForKey:filename];
 89     }
 90     
 91 }
 92 
 93 
 94 /**
 95  *  根据音乐文件名称播放音乐
 96  *
 97  *  @param filename 音乐文件名称
 98  */
 99 + (void)playMusicWithFilename:(NSString  *)filename
100 {
101     // 0.判断文件名是否为nil
102     if (filename == nil) {
103         return;
104     }
105     
106     // 1.从字典中取出播放器
107     AVAudioPlayer *player = [self players][filename];
108     
109     // 2.判断播放器是否为nil
110     if (!player) {
111         NSLog(@"创建新的播放器");
112         
113         // 2.1根据文件名称加载音效URL
114         NSURL *url = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
115         
116         // 2.2判断url是否为nil
117         if (!url) {
118             return;
119         }
120         
121         // 2.3创建播放器
122         player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
123         
124         // 2.4准备播放
125         if(![player prepareToPlay])
126         {
127             return; //如果缓冲失败,那么就直接返回
128         }
129         // 允许快进
130         player.enableRate = YES;
131         player.rate = 3;
132         
133         // 2.5将播放器添加到字典中
134         [self players][filename] = player;
135         
136     }
137     // 3.播放音乐
138     if (!player.playing)
139     {
140         [player play];
141     }
142    
143 }
144 
145 /**
146  *  根据音乐文件名称暂停音乐
147  *
148  *  @param filename 音乐文件名称
149  */
150 + (void)pauseMusicWithFilename:(NSString  *)filename
151 {
152     // 0.判断文件名是否为nil
153     if (filename == nil) {
154         return;
155     }
156     
157     // 1.从字典中取出播放器
158     AVAudioPlayer *player = [self players][filename];
159 
160     // 2.判断播放器是否存在
161     if(player)
162     {
163         // 2.1判断是否正在播放
164         if (player.playing)
165         {
166             // 暂停
167             [player pause];
168         }
169     }
170     
171 }
172 
173 /**
174  *  根据音乐文件名称停止音乐
175  *
176  *  @param filename 音乐文件名称
177  */
178 + (void)stopMusicWithFilename:(NSString  *)filename
179 {
180     // 0.判断文件名是否为nil
181     if (filename == nil) {
182         return;
183     }
184     
185     // 1.从字典中取出播放器
186     AVAudioPlayer *player = [self players][filename];
187 
188     // 2.判断播放器是否为nil
189     if (player) {
190         // 2.1停止播放
191         [player stop];
192         // 2.2清空播放器
193 //        player = nil;
194         // 2.3从字典中移除播放器
195         [[self players] removeObjectForKey:filename];
196     }
197 }
198 @end

代码测试:

- (IBAction)playMusic {
    // 开始播放/继续播放
//    [HMAudioTool playMusicWithFilename:self.musics[self.currentIndex]];
    [HMAudioTool playAudioWithFilename:@"buyao.wav"];
}

代码说明:

打印的值为0,播放成功(因为函数是C++中的)

原文地址:https://www.cnblogs.com/zengshuilin/p/5768507.html