zoukankan      html  css  js  c++  java
  • 音乐

    iOS 音乐


    这篇博客介绍的是较长的音频播放-音乐...
    有关音效的介绍可以点击下面的连接进入...
    iOS 音效

    首先导入框架:AVFoundation.framework

    导入框架后我们在需要使用音乐的文件内引入头文件:

    #import <AVFoundation/AVFoundation.h>

    做好准备后开始介绍这篇博客的主要内容:

    我在这里实现了一个特别小的功能(如图)

    • 可以播放,暂停与停止(分别由三个按钮实现)
    • 播放进度的slider可以显示当前播放进度,并且通过拖动实现播放进度的改变
    • 播放速度的slider可以改变音乐的播放速度
    • 播放音量的slider可以改变音乐的播放音量

    下面我会根据每个内容逐个介绍,从而实现整个代码:

    AVAudioPlayer

    AVAudioPlayer可以说是整个音乐的操作者,通过他我们实现各个操作.

    @property (nonatomic, strong) AVAudioPlayer * player;
    

    我们在AVAudioPlayer的懒加载中做一些操作

    - (AVAudioPlayer *)player{
        if (!_player) {
            
            NSURL * url = [[NSBundle mainBundle]URLForResource:@"终于等到你" withExtension:@"mp3"];
            
            NSError * error;
            
            //实例化播放
            _player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
            
            //设置代理
            _player.delegate = self;
            
            if (error) {
                NSLog(@"初始化失败");
            }else{
                
                //准备开始播放 缓冲数据
                [_player prepareToPlay];
                
                //是否允许快播
                _player.enableRate = YES;
                
                //设置播放次数 -1为无限
                //0:播放一次 1:播放两次 ......
                _player.numberOfLoops = 0;
                
                //slider最大值
                self.timeSlider.maximumValue = _player.duration;
                
            }
        }
        return  _player;
    }
    

    这里值得注意的是准备开始播放 (其他的就不过多说了代码里有着详细的介绍)
    即:

    [_player prepareToPlay];

    没有这句是无法正常播放的.

    播放

    代码操作:

    //播放
    - (IBAction)play:(id)sender {
        
        if (![self.player isPlaying]) {
            
            //添加定时器到runloop中
            [self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
            
            [self.player play];
        }
        
    }

    在播放操作中我们进行了是否在播放的判断,以避免混音.
    定时器是为了对播放进度的实现,后面会介绍到.

    暂停

    代码操作:

    //暂停
    - (IBAction)pause:(id)sender {
        
        if ([self.player isPlaying]) {
            [self.player pause];
            
            //暂停link
            [self.link invalidate];
            self.link = nil;
        }   
    }

    在暂停操作中我们先判断是否正在播放,只有正在播放才能执行暂停.
    暂停的时候为了避免资源的过多浪费我们定制定时器并把定时器清空.

    停止播放

    代码操作:

    //停止
    - (IBAction)stop:(id)sender {
        
        [self.player stop];
        
        //清空内存
        self.player = nil;
        
        //停止link
        [self.link invalidate];
        self.link = nil;
    
    }

    在停止操作中有一点很值得注意,当我们停止后,再次点击播放会发现是继续播放,显然不符合情理.
    因此我们在这里对player进行了清空操作.
    定时器的操作如暂停.

    播放进度slider

    播放进度slider的实现是需要配合定时器的使用的("实时"监控),因此前面出现的定时器也就可以理解
    了.

    //定时器的属性声明

    //定时器
    @property (nonatomic, strong) CADisplayLink * link;

    //定时器的懒加载

    - (CADisplayLink *)link{
        
        if (!_link) {
            _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(change)];
        }
        return _link;
    }
    
    //改变slider进度的方法
    - (void)change{
        
        //获取当前时间 重置播放进度
        self.timeSlider.value = self.player.currentTime;
    }

    该功能分析:

    实现的功能是拖动控件实现进度跳转
    那么

    • 当我们点击的时候停止播放
    • 根据value值设置进度
    • 当我们结束拖动时继续播放

    代码操作:

    //按下slieder 开始拖拽
    - (IBAction)timeTouchDown:(id)sender {
        
        //停止播放
        [self.player pause];
        
    }
    
    //结束拖拽
    - (IBAction)timeTouchUp:(id)sender {
        
        //继续播放
        [self.player play];
    }
    
    //改变播放进度
    - (IBAction)timeChangeSlider:(UISlider *)sender {
        
        //修改现在的播放时间
        self.player.currentTime = sender.value;
    }

    播放速度

    代码操作:

    //播放速度
    - (IBAction)rateChange:(UISlider *)sender {
        
        self.player.rate = sender.value;
    }
    

    播放音量

    代码操作:

    //播放音量
    - (IBAction)voiceChange:(UISlider *)sender {
        
        self.player.volume = sender.value;
    }

    代理

    //播放完成
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
        
    }
    
    //error
    - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{
        
    }
    
    //iOS8 开始中断
    - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{
        
    }
    
    //iOS8 结束中断
    - (void)audioPlayerEndInterruption:(AVAudioPlayer *)player{
        
    }

    在上面可以到iOS8的字样
    那么iOS9呢???

    - (void)viewDidLoad {
        
        [super viewDidLoad];
        
        //iOS9处理中断
        AVAudioSession * session = [AVAudioSession sharedInstance];
        
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(Interruption:) name:AVAudioSessionInterruptionNotification object:session];
        
    }
    
    //iOS9中断处理方法
    - (void)Interruption:(NSNotification *)noti{
        if (noti.userInfo.allKeys.count == 2) {
            NSLog(@"结束中断");
        }else{
            NSLog(@"开始中断");
        }
    }
    

    一页的代码就把代码贴上了

    
    #import "ViewController.h"
    #import <AVFoundation/AVFoundation.h>
    
    
    @interface ViewController ()<AVAudioPlayerDelegate>
    //播放本地音乐
    @property (nonatomic, strong) AVAudioPlayer * player;
    
    //播放时间的滑块
    @property (weak, nonatomic) IBOutlet UISlider *timeSlider;
    
    //定时器
    @property (nonatomic, strong) CADisplayLink * link;
    
    @end
    
    @implementation ViewController
    
    #pragma mark - <getters and setters>
    
    - (CADisplayLink *)link{
        
        if (!_link) {
            _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(change)];
        }
        return _link;
    }
    
    - (AVAudioPlayer *)player{
        if (!_player) {
            
            NSURL * url = [[NSBundle mainBundle]URLForResource:@"CX" withExtension:@"mp3"];
            
            NSError * error;
            
            //实例化播放
            _player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
            
            //设置代理
            _player.delegate = self;
            
            if (error) {
                NSLog(@"初始化失败");
            }else{
                
                //准备开始播放 缓冲数据
                [_player prepareToPlay];
                
                //是否允许快播
                _player.enableRate = YES;
                
                //设置播放次数 -1为无限
                //0:播放一次 1:播放两次 ......
                _player.numberOfLoops = 0;
                
                //slider最大值
                self.timeSlider.maximumValue = _player.duration;
                
            }
        }
        return  _player;
    }
    
    #pragma mark - <life cycle>
    - (void)viewDidLoad {
        
        [super viewDidLoad];
        
        //iOS9处理中断
        AVAudioSession * session = [AVAudioSession sharedInstance];
        
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(Interruption:) name:AVAudioSessionInterruptionNotification object:session];
        
    }
    
    #pragma mark - <AVAudioPlayerDelegate>
    
    //播放完成
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
        
    }
    
    //error
    - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error{
        
    }
    
    //iOS8 开始中断
    - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{
        
    }
    
    //iOS8 结束中断
    - (void)audioPlayerEndInterruption:(AVAudioPlayer *)player{
        
    }
    
    #pragma mark - <event handle>
    
    //改变slider进度的方法
    - (void)change{
        
        //获取当前时间 重置播放进度
        self.timeSlider.value = self.player.currentTime;
    }
    
    //iOS9中断处理方法
    - (void)Interruption:(NSNotification *)noti{
        if (noti.userInfo.allKeys.count == 2) {
            NSLog(@"结束中断");
        }else{
            NSLog(@"开始中断");
        }
    }
    
    //播放
    - (IBAction)play:(id)sender {
        
        if (![self.player isPlaying]) {
            
            //添加定时器到runloop中
            [self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
            
            [self.player play];
        }
        
    }
    
    //暂停
    - (IBAction)pause:(id)sender {
        
        if ([self.player isPlaying]) {
            [self.player pause];
            
            //暂停link
            [self.link invalidate];
            self.link = nil;
        }
        
    }
    
    //停止
    - (IBAction)stop:(id)sender {
        
        [self.player stop];
        
        //清空内存
        self.player = nil;
        
        //停止link
        [self.link invalidate];
        self.link = nil;
    
    }
    
    //按下slieder 开始拖拽
    - (IBAction)timeTouchDown:(id)sender {
        
        //停止播放
        [self.player pause];
        
    }
    
    //结束拖拽
    - (IBAction)timeTouchUp:(id)sender {
        
        //继续播放
        [self.player play];
    }
    
    //改变播放进度
    - (IBAction)timeChangeSlider:(UISlider *)sender {
        
        //修改现在的播放时间
        self.player.currentTime = sender.value;
    }
    
    //播放速度
    - (IBAction)rateChange:(UISlider *)sender {
        
        self.player.rate = sender.value;
    }
    
    //播放音量
    - (IBAction)voiceChange:(UISlider *)sender {
        
        self.player.volume = sender.value;
    }
    
    @end
  • 相关阅读:
    【转】K/3 KIS BOS 插件入门
    [转]SQL Server 存储过程中使用 in 动态变量
    [转]Delphi 12种大小写转换的方法
    cxGrid FilterRow 添加左模糊查询,实现 %ABC%
    cxGrid 锁定一行,让该行数据不能编辑
    K/3工业单据K3BillTransfer的属性及使用方法
    VB6上创建金蝶K/3或KIS旗舰版插件
    MySQL UTF8 中文乱码处理
    两种方法自动部署代码:webhooks钩子自动部署代码方法一 及定时任务自动部署二 简介
    Linux查看进程的4种方法
  • 原文地址:https://www.cnblogs.com/iOSlearner/p/5484389.html
Copyright © 2011-2022 走看看