ios开发学习--歌词处理--解析lrc文件
2015-08-21 19:28
567 查看
我觉得要想解析lrc 首先大家应该了解一下lrc文件的结构,大家可以去看一下**百科 我这里粗略的写一下;
■ 时间标签(Time-tag)
形式为"[mm:ss]"(分钟数:秒数)
或"[mm:ss.ff]"。数字须为非负整数
■ 标识标签(ID-tags)
其格式为"[标识名:值]"。大小写等价。以下是预定义的标签。
[ar:艺人名]
[ti:曲名]
[al:专辑名]
[by:编者(指编辑LRC歌词的人)]
[offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。
[t_time:(总时长)]
每一句歌词可能有多个播放时间,如:
[00:12:34][00:34:15][00:25:54]测试
所以解析的时候都要考虑到;
下面附源码,源码中有关键点的注释;源码下面还会有解释
注:代码中很多部分采用了三元式,希望大家可以看懂,三元式可以和if else 语句替换,大家自己可以网上搜一下,后面知识点会稍微说一下,不会很详细
View Code
知识点:
1、[[NSBundle mainBundle] pathForResource:name ofType:type]]
//路径构建,传进的name 和 type 参数需要做 路径构建
2、NSArray *StrToInt = [NSArray arrayWithObjects:@"ar",@"ti",@"al",@"by",@"of",@"t_",nil];//NSString switch 配置
switch ((int)[StrToInt indexOfObject:[temp substringWithRange:NSMakeRange(1, 2)]])
//OC的switch case 不支持NSString 这可能让很多学过Java的小伙伴很*疼,利用NSArray indexOfObject:方法实现NSString 映射到数字(数组下标),以便于调用 switch case;
3、
substringFromIndex//截取
stringByReplacingOccurrencesOfString:@"]" withString:@"\0"//替换
NSMutableArray * arraylrc = [[NSMutableArray alloc] initWithArray:[strlrc componentsSeparatedByString:@"\n"]];//分割
大量的字符串 处理函数 大家自多看吧,毕竟很常用也很重要
4、三元式的读取
条件?a:b; 满足条件返回a 不满足条件返回b 如果a b 是表达式 则会自动执行表达式
新增部分:
代码的第58行,替换成:BOOL flag = arraylrc.count > 0 ? YES : NO; //防止错误路径或者歌词文件为空导致的概率性崩溃;
代码的第89行,插入:self.lrcArrayTime.count == 0 ? [self.lrcArrayTime insertObject:@"0" atIndex:0],[self.lrcArrayStr insertObject:@"未找到歌词!" atIndex:0]:nil; //又是一个三元式,没办法喜欢他, 和上面作用一样,不一样的是插入了一句提示语,找不到歌词。
此处编辑于:15-09-23 12时
[b]注意:以上部分未在下面的源文件中更新[/b]
代码中的细节,基本都做了注释,不懂得可以留言,我会尽可能的答复;
代码源文件下载
■ 时间标签(Time-tag)
形式为"[mm:ss]"(分钟数:秒数)
或"[mm:ss.ff]"。数字须为非负整数
■ 标识标签(ID-tags)
其格式为"[标识名:值]"。大小写等价。以下是预定义的标签。
[ar:艺人名]
[ti:曲名]
[al:专辑名]
[by:编者(指编辑LRC歌词的人)]
[offset:时间补偿值] 其单位是毫秒,正值表示整体提前,负值相反。这是用于总体调整显示快慢的。
[t_time:(总时长)]
每一句歌词可能有多个播放时间,如:
[00:12:34][00:34:15][00:25:54]测试
所以解析的时候都要考虑到;
下面附源码,源码中有关键点的注释;源码下面还会有解释
注:代码中很多部分采用了三元式,希望大家可以看懂,三元式可以和if else 语句替换,大家自己可以网上搜一下,后面知识点会稍微说一下,不会很详细
// // LyricsAnalysis.m // 08-10-MusicPlayer // // Created by Ibokan on 15/8/21. // Copyright (c) 2015年 Crazy凡. All rights reserved. // #import "LyricsAnalysis.h" @interface LyricsAnalysis () @property double offset;//歌词时间调整变量 @end @implementation LyricsAnalysis //初始化 - (instancetype)init { self = [super init]; if (self) { self.ar = [[NSString alloc]init]; self.ti = [[NSString alloc]init]; self.by = [[NSString alloc]init]; self.al = [[NSString alloc]init]; self.offset = 0; self.t_time = [[NSString alloc]init];//歌曲总时长单位(s) self.lrcArrayStr = [[NSMutableArray alloc]init];//歌词数组初始化 self.lrcArrayTime = [[NSMutableArray alloc]init];//时间数组初始化 } return self; } //带文件名的初始化 - (instancetype)initWithFileName:(NSString *)name ofType:(NSString *)type { self = [self init]; [self lyricsAnalysisWithFileName:name ofType:type]; return self; } //带文件路径的初始化 - (instancetype)initWithFilePath:(NSString *)filePath { self = [self init]; [self lyricsAnalysisWithFilePath:filePath]; return self; } //处理文件名歌词 - (void)lyricsAnalysisWithFileName:(NSString *)name ofType:(NSString *)type { [self lyricsAnalysisWithFilePath:[[NSBundle mainBundle] pathForResource:name ofType:type]];//构建filepath } //处理文件路径 - (void)lyricsAnalysisWithFilePath:(NSString *)filePath { NSString *strlrc = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; NSMutableArray * arraylrc = [[NSMutableArray alloc] initWithArray:[strlrc componentsSeparatedByString:@"\n"]]; NSArray *StrToInt = [NSArray arrayWithObjects:@"ar",@"ti",@"al",@"by",@"of",@"t_",nil];//NSString switch 配置 BOOL flag = YES; while(flag) { NSString *temp = arraylrc[0]; switch ((int)[StrToInt indexOfObject:[temp substringWithRange:NSMakeRange(1, 2)]]) { case 0:self.ar = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@"\0"];break; case 1:self.ti = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@"\0"];break; case 2:self.al = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@"\0"];break; case 3:self.by = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@"\0"];break; case 4:self.offset = [[[temp substringFromIndex:8] stringByReplacingOccurrencesOfString:@"]" withString:@"\0"] doubleValue];break; case 5:self.t_time = [[temp substringFromIndex:9] stringByReplacingOccurrencesOfString:@")]" withString:@"\0"];break; default:flag = NO; break; } flag?[arraylrc removeObjectAtIndex:0]:nil;//判断是否需要移除已经被读取的信息(是歌词则不移除) }// lrc时间的格式分3种:[mm:ss.SS]、[mm:ss:SS]、[mm:ss];第一种是标准形式,后面两种存在但是不标准;先把时间字符串按照“:”拆分,生成{mm ss.SS}、{mm ss SS}、{mm ss};对于1、3,直接取doubleValue即可;注意分钟*60;对于第二种情况需要单独处理SS(毫秒)位; for (NSString *str in arraylrc) { NSArray * ArrayTemp = [str componentsSeparatedByString:@"]"];//分割每一句歌词 for(int j = 0 ; j < ArrayTemp.count -1 ;j++) { NSArray * Arraytime = [[ArrayTemp[j] substringFromIndex:1] componentsSeparatedByString:@":"];//分割时间字符串 double timedouble = [Arraytime[0] doubleValue]*60.0 + [Arraytime[1] doubleValue];//处理分钟和秒 timedouble += Arraytime.count > 2 ? [[[NSString alloc]initWithFormat:@"0.%@",Arraytime[2]] doubleValue]:0;//处理毫秒位 timedouble += (self.offset / 1000.0);//时间调整 timedouble = timedouble > 0 ? timedouble : 0;//避免因为时间调整导致的时间<0 int i = 0; while (i < self.lrcArrayTime.count && [self.lrcArrayTime[i++] doubleValue] < timedouble);//查找当前歌词的插入位置 [self.lrcArrayTime insertObject:[[NSString alloc]initWithFormat:@"%lf",timedouble] atIndex:i];//插入时间数组 [self.lrcArrayStr insertObject:ArrayTemp[ArrayTemp.count-1] atIndex:i];//插入歌词数组 } } } @end
View Code
知识点:
1、[[NSBundle mainBundle] pathForResource:name ofType:type]]
//路径构建,传进的name 和 type 参数需要做 路径构建
2、NSArray *StrToInt = [NSArray arrayWithObjects:@"ar",@"ti",@"al",@"by",@"of",@"t_",nil];//NSString switch 配置
switch ((int)[StrToInt indexOfObject:[temp substringWithRange:NSMakeRange(1, 2)]])
//OC的switch case 不支持NSString 这可能让很多学过Java的小伙伴很*疼,利用NSArray indexOfObject:方法实现NSString 映射到数字(数组下标),以便于调用 switch case;
3、
substringFromIndex//截取
stringByReplacingOccurrencesOfString:@"]" withString:@"\0"//替换
NSMutableArray * arraylrc = [[NSMutableArray alloc] initWithArray:[strlrc componentsSeparatedByString:@"\n"]];//分割
大量的字符串 处理函数 大家自多看吧,毕竟很常用也很重要
4、三元式的读取
条件?a:b; 满足条件返回a 不满足条件返回b 如果a b 是表达式 则会自动执行表达式
新增部分:
代码的第58行,替换成:BOOL flag = arraylrc.count > 0 ? YES : NO; //防止错误路径或者歌词文件为空导致的概率性崩溃;
代码的第89行,插入:self.lrcArrayTime.count == 0 ? [self.lrcArrayTime insertObject:@"0" atIndex:0],[self.lrcArrayStr insertObject:@"未找到歌词!" atIndex:0]:nil; //又是一个三元式,没办法喜欢他, 和上面作用一样,不一样的是插入了一句提示语,找不到歌词。
此处编辑于:15-09-23 12时
[b]注意:以上部分未在下面的源文件中更新[/b]
代码中的细节,基本都做了注释,不懂得可以留言,我会尽可能的答复;
代码源文件下载
相关文章推荐
- iOS将数组中的内容分拼接成字符串
- 如何学习iOS开发?iOS Developer Library足矣!
- IOS开发之动态获取模型的属性值
- iOS 屏幕适配
- iOS 关于传值
- iOS高级-QuartzCore框架-图形上下文栈、矩阵操作、裁剪、重绘(刷帧)
- 【读书笔记】iOS-写代码注意事项
- 【读书笔记】iOS-写代码注意事项
- 如何使用iOS 8的虚化效果
- iOS沙盒简单介绍
- iOS 去掉导航栏的边界灰线;去掉搜索框的边界灰线和其中文本输入框的阴影
- iOS 获取设备类型
- iOS 9学习系列:如何使用ATS提高应用的安全性
- IOS XIB Cell自适应高度实现
- 【iOS程序启动与运转】- RunLoop个人小结
- xcode6+ios8最新真机调试教程
- BIOS加电自检
- OutMan——单例模式、代理模式以及iOS沙盒(sandbox)机制
- iOS本地推送与远程推送
- ios通过svg截取头像