OC开发iOS技术点

iOS播放音乐,音量淡出暂停效果

2016-04-01  本文已影响895人  ziooooo

在开发过程中,使用到了音频的播放AVAudioPlayer,其中的-(void)pause;暂停播放的方法暂停时过于生硬。于是我试着暂停时使音量逐渐降低,达到淡出的效果。

音量、逐渐、降低,看这几个词我决定使用一个定时器修改AVAudioPlayer实例的volume属性直到值为0,来实现这个效果。


首先为AVAudioPlayer创建一个分类

@interface AVAudioPlayer (Category)

-(void)graduallyPasue;

@end

下面按照之前的想法来简单实现以下音量逐渐降低,在.m文件中

-(void)graduallyPasue
{
    //用GCD创建一个计时器
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    //0.1秒执行一次
    dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), 0.1 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{
        //每次音量 -0.1
        self.volume -= 0.1;
        if (self.volume < 0) {//音量小于0时结束定时器
            dispatch_source_cancel(_timer);
        }
    });
    dispatch_source_set_cancel_handler(_timer, ^{
        //结束时,暂停
        [self pause];
    });
    dispatch_resume(_timer);
}

上面的代码中,如果原来的音量是1.0,那么就需要1s的时间来暂停音乐,暂时先这么写,以后再做优化。

接下来试一试-(void)graduallyPasue的效果,我的使用场景是暂停一首音乐,继续播放下一首音乐。这时问题出现了:

造成这种问题的原因就是播放第二首音乐的代码,在第一首暂停方法未执行完毕的时候就开始执行了。那么我们使用GCD提供的dipatch group来保持队列同步,使计时器结束后再执行后面的代码。

-(void)graduallyPasue
{
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    
    //用GCD创建一个计时器
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    //0.1秒执行一次
    dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), 0.1 * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{
        //每次音量 -0.1
        self.volume -= 0.1;
        if (self.volume < 0) {//音量小于0时结束定时器
            dispatch_source_cancel(_timer);
        }
    });
    dispatch_source_set_cancel_handler(_timer, ^{
        //结束时,暂停
        [self pause];
        
        dispatch_group_leave(group);
    });
    dispatch_resume(_timer);
    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}

这样用起来就好多了,那么再优化一下,可以控制暂停时淡出的时间。

-(void)graduallyPasueWithDuration:(NSTimeInterval)duration
{
    //频率
    static NSTimeInterval frequency = 0.05;
    //定时器执行次数
    __block int overCount = duration / frequency;
    //声音每次降低的偏移量
    float volumeOffset = self.volume / overCount;
    
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), frequency * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{
        overCount -= 1;
        self.volume -= volumeOffset;
        if (overCount < 0) {
            dispatch_source_cancel(_timer);
        }
    });
    dispatch_source_set_cancel_handler(_timer, ^{
        [self pause];
        dispatch_group_leave(group);
    });
    dispatch_resume(_timer);
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}

修改一下.h的方法名,就可以使用了。


第一次发文章,热爱技术的大家,欢迎交流啊!

上一篇 下一篇

猜你喜欢

热点阅读