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

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

      另外一种做法是:自己封装一个播放音乐文件的工具类。
     
    封装工具类的实现步骤:
      新建一个类,继承自NSObject类。提供三个对外的接口:
      
    分别是:
    播放音乐(参数:文件名,返回值:BOOL)
    暂停音乐(参数:文件名)
    停止音乐(参数:文件名)
    该工具类中的代码设计如下:
    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 : NSObject
    12 /**
    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 YYAudioTool
    12 /**
    13  *存放所有的音乐播放器
    14  */
    15 static NSMutableDictionary *_musices;
    16 +(NSMutableDictionary *)musices
    17 {
    18     if (_musices==nil) {
    19         _musices=[NSMutableDictionary dictionary];
    20     }
    21     return _musices;
    22 }
    23 
    24 /**
    25  *播放音乐
    26  */
    27 +(BOOL)playMusic:(NSString *)filename
    28 {
    29     if (!filename) return NO;//如果没有传入文件名,那么直接返回
    30     //1.取出对应的播放器
    31     AVAudioPlayer *player=[self musices][filename];
    32     
    33     //2.如果播放器没有创建,那么就进行初始化
    34     if (!player) {
    35         //2.1音频文件的URL
    36         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;//正在播放,那么就返回YES
    56 }
    57 
    58 +(void)pauseMusic:(NSString *)filename
    59 {
    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 *)filename
    71 {
    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 @end
    23 
    24 @implementation YYViewController
    25 #pragma mark-懒加载
    26 -(NSArray *)songs
    27 {
    28     if (_songs==nil) {
    29         self.songs=@[@"235319.mp3",@"309769.mp3",@"120125029.mp3"];
    30     }
    31     return _songs;
    32 }
    33 
    34 - (void)viewDidLoad
    35 {
    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.设置当前索引+1
    60     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 : NSObject
    12 /**
    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         //音效文件的URL
    109         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 *)filename
    124 {
    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++中的)

  • 相关阅读:
    Can't locate ... in @INC
    c++写一个类后编译发现class重定义
    python with
    遍历Java Map
    mod_jk notes
    NPM使用总结
    Yeoman
    Java中的Marker Interfaces有什么用
    有关Ehcache的内容的引用和Java的deep copy
    JDBC的PreparedStatement语句使用记录
  • 原文地址:https://www.cnblogs.com/LiLihongqiang/p/5687232.html
Copyright © 2020-2023  润新知