转载

iOS开发手记-仿QQ音乐播放器动态歌词的实现

最近朋友想做个音乐App,让我帮忙参考下。其中歌词动态滚动的效果,正好我之前也没做过,顺便学习一下,先来个预览效果。

iOS开发手记-仿QQ音乐播放器动态歌词的实现

实现思路

歌词常见的就是lrc歌词了,我们这里也是通过解析lrc歌词文件来获取其播放参数,以实现和播放器协同。下面是我从百度音乐获取的歌词文件示例:

 [ti:冰雨] [ar:刘德华] [al:笨小孩] [00:0.05]冰雨 [00:0.94]作词:刘德华、李密 作曲:潘协庆 [00:01.23]演唱:刘德华  [00:01.37] [00:04.79](歌手独白) [00:17.18]我是在等待 一个女孩 [00:25.18]还是在等待沉沦苦海 [00:32.91]一个人静静发呆 没有人去管花谢花开 [00:41.03]无法肯定的爱  左右摇摆 [00:45.43]只好把心酸往深心里塞 [00:49.61]我是在等待 你的回来 [00:57.73]难道只换回一句活该 [01:05.27]一个人静静发呆 [01:09.18]两个人却有不同无奈 [01:13.15]好好的一份爱 啊怎么会慢慢变坏 [01:18.43] [01:20.44]冷冷的冰雨在脸上胡乱的拍 [01:24.31]暖暖的眼泪跟寒雨混成一块 [01:28.32]眼前的色彩忽然被掩盖 [01:32.28]你的影子无情在身边徘徊 [01:36.30]你就像一个刽子手把我出卖 [01:40.35]我的心彷佛被剌刀狠狠地宰 [01:44.36]在悬崖上的爱 谁会愿意接受最痛的意外 [01:51.09] [02:26.59]我是在等待你的回来 [02:35.52]难道只换回一句活该 [02:42.99]一个人静静发呆 [02:46.99]两个人却有不同无奈 [02:51.08]好好的一份爱 啊怎么会慢慢变坏 [02:56.42] [02:58.54]冷冷的冰雨在脸上胡乱的拍 [03:02.41]暖暖的眼泪跟寒雨混成一块 [03:06.39]眼前的色彩忽然被掩盖 [03:10.31]你的影子无情在身边徘徊 [03:14.23]你就像一个刽子手把我出卖 [03:18.34]我的心彷佛被剌刀狠狠地宰 [03:22.33]在悬崖上的爱  谁会愿意接受最痛的意外 [03:28.66] [03:34.57]冷冷的冰雨在脸上胡乱的拍 [03:38.33]暖暖的眼泪跟寒雨混成一块 [03:42.31]眼前的色彩忽然被掩盖 [03:46.32]你的影子无情在身边徘徊 [03:50.27]你就像一个刽子手把我出卖 [03:54.34]我的心彷佛被剌刀狠狠地宰 [03:58.34]悬崖上的爱  谁会敢去采 [04:02.37]还是愿意接受最痛的意外 最爱的女孩 [04:08.85] [04:19.72]悬崖上的爱  谁会敢去采 [04:31.84]还是愿意接受最痛的意外 最爱的女孩 [04:51.75] [05:10.60]歌手独白 [06:16.76] 

解析lrc歌词

这可能是最常见的格式了,每行为一句歌词,[]括号内为歌词对应的时间区间,所以我们首先要做的事情就是将他们提取分离出来,分别作为时间参数数组和歌词内容数组。这里我参考了一些博客的方法,解析lrc文件的代码如下:

 #import <Foundation/Foundation.h>  @interface LrcParser : NSObject  //时间 @property (nonatomic,strong) NSMutableArray *timerArray; //歌词 @property (nonatomic,strong) NSMutableArray *wordArray;   //解析歌词 -(void) parseLrc; //解析歌词 -(void) parseLrc:(NSString*)lrc; @end 

实现代码

 @implementation LrcParser    -(instancetype) init{     self=[super init];     if(self!=nil){         self.timerArray=[[NSMutableArray alloc] init];         self.wordArray=[[NSMutableArray alloc] init];     }     return  self; }    -(NSString *)getLrcFile:(NSString *)lrc{     NSString* filePath=[[NSBundle mainBundle] pathForResource:lrc ofType:@"lrc"];     return  [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; } //测试示例 -(void)parseLrc{     [self parseLrc:[self getLrcFile:@"冰雨"]]; }   -(void)parseLrc:(NSString *)lrc{     NSLog(@"%@",lrc);          if(![lrc isEqual:nil]){         NSArray *sepArray=[lrc componentsSeparatedByString:@"["];         NSArray *lineArray=[[NSArray alloc] init];         for(int i=0;i<sepArray.count;i++){             if([sepArray[i] length]>0){                 lineArray=[sepArray[i] componentsSeparatedByString:@"]"];                 if(![lineArray[0] isEqualToString:@"/n"]){                     [self.timerArray addObject:lineArray[0]];                                          [self.wordArray addObject:lineArray.count>1?lineArray[1]:@""];                 }             }         }     } } @end 

经过测试,可以将歌词顺利解析出来,下面我们要将获得歌词数据应用于控制器。

实现动态歌词页面

看了QQ音乐的滚动歌词页面后,可以知道是借助UITableView或者UIScrollView来实现的,这里我们采用UITableView来实现动态歌词界面。

 - (void)viewDidLoad {     [super viewDidLoad];     // Do any additional setup after loading the view, typically from a nib.     //歌词TableView代理     self.lrcTable.delegate=self;     self.lrcTable.dataSource=self;          //解析歌词     self.lrcContent=[[LrcParser alloc] init];     [self.lrcContent parseLrc];     [self.lrcTable reloadData];     //初始化播放器     [self initPlayer];     //监听播放器状态     [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTime) userInfo:nil repeats:YES];     //载入歌词背景     UIImage *img=[UIImage imageNamed:@"wall1.jpg"];          UIImageView *bgView=[[UIImageView alloc] initWithImage:[self getBlurredImage:img]];          self.lrcTable.backgroundView=bgView;      } //cell委托 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{      UITableViewCell *cell=[self.lrcTable dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];      cell.textLabel.text=self.lrcContent.wordArray[indexPath.row];      if(indexPath.row==_currentRow)          cell.textLabel.textColor = [UIColor redColor];      else          cell.textLabel.textColor = [UIColor whiteColor];            cell.textLabel.textAlignment = NSTextAlignmentCenter;      cell.textLabel.font = [UIFont systemFontOfSize:15];      cell.backgroundColor=[UIColor clearColor];           return cell;  } 

这里歌词列表的背景我采用了高斯模糊的图片,高斯模糊的方法如下:

 //实现高斯模糊 -(UIImage *)getBlurredImage:(UIImage *)image{     CIContext *context = [CIContext contextWithOptions:nil];     CIImage *ciImage=[CIImage imageWithCGImage:image.CGImage];     CIFilter *filter=[CIFilter filterWithName:@"CIGaussianBlur"];     [filter setValue:ciImage forKey:kCIInputImageKey];     [filter setValue:@5.0f forKey:@"inputRadius"];     CIImage *result=[filter valueForKey:kCIOutputImageKey];     CGImageRef ref=[context createCGImage:result fromRect:[result extent]];     return [UIImage imageWithCGImage:ref]; } 

播放器则采用AVPlayer,其定义和初始化设置如下:

 @interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>  @property (nonatomic,strong) AVAudioPlayer *player;  @end 
 -(void) initPlayer{     AVAudioSession *session=[AVAudioSession sharedInstance];     [session setActive:YES error:nil];     [session setCategory:AVAudioSessionCategoryPlayback error:nil];               [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];          self.player=[[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle]  URLForResource:@"冰雨" withExtension:@"mp3"] error:nil];     //单曲循环     self.player.numberOfLoops=10;     [self.player prepareToPlay];     [self.player play];      } 

这样就为应用定义了一个音乐播放器,下面要监听播放器的时间参数,来载入对应的歌词,如下:

 [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTime) userInfo:nil repeats:YES]; 

根据时间更新UI

 -(void) updateTime{     CGFloat currentTime=self.player.currentTime;     NSLog(@"%d:%d",(int)currentTime / 60, (int)currentTime % 60);     for (int i=0; i<self.lrcContent.timerArray.count; i++) {         NSArray *timeArray=[self.lrcContent.timerArray[i] componentsSeparatedByString:@":"];         float lrcTime=[timeArray[0] intValue]*60+[timeArray[1] floatValue];         if(currentTime>lrcTime){             _currentRow=i;         }else             break;     }          [self.lrcTable reloadData];     [self.lrcTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_currentRow inSection:0] atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; } 

最后编译运行,就会发现一个滚动歌词播放器就实现啦。

完整Demo项目地址: https://github.com/ChangweiZhang/AudioPlayerDemo

原文  http://www.cnblogs.com/mantgh/p/5208034.html
正文到此结束
Loading...