zoukankan      html  css  js  c++  java
  • 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++中的)

  • 相关阅读:
    合并指定表格指定列的相同文本的相邻单元格
    [转载]>/dev/null 2>&1 含义
    有关cron
    jQuery版本对checkbox影响
    c# 如何获取项目的根目录
    Javascript 字符串组装用函数 format
    sql server 删除数据库
    说说接口封装
    有开放的接口!!!!
    支付宝支付功能的集成
  • 原文地址:https://www.cnblogs.com/zengshuilin/p/5768507.html
Copyright © 2011-2022 走看看