在开发过程中,使用到了音频的播放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
的效果,我的使用场景是暂停一首音乐,继续播放下一首音乐。这时问题出现了:
- 如果是用的是同一个
AVAudioPlayer
实例来播放音乐的话,第一首音乐并没有声音淡出的效果,并且第二首音乐声音逐渐变小直到暂停。 - 如果不是同一个
AVAudioPlayer
实例来播放音乐的话,第二首音乐会在第一首音乐没有暂停时就开始播放。
造成这种问题的原因就是播放第二首音乐的代码,在第一首暂停方法未执行完毕的时候就开始执行了。那么我们使用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的方法名,就可以使用了。
第一次发文章,热爱技术的大家,欢迎交流啊!