• ios开发学习--歌词处理--解析lrc文件


    我觉得要想解析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 语句替换,大家自己可以网上搜一下,后面知识点会稍微说一下,不会很详细  
     
     
     1 //
     2 //  LyricsAnalysis.h
     3 //  08-10-MusicPlayer
     4 //
     5 //  Created by Ibokan on 15/8/21.
     6 //  Copyright (c) 2015年 Crazy凡. All rights reserved.
     7 //
     8 
     9 #import <Foundation/Foundation.h>
    10 
    11 @interface LyricsAnalysis : NSObject
    12 @property (nonatomic,strong)NSString *ar;//演唱
    13 @property (nonatomic,strong)NSString *ti;//歌曲名
    14 @property (nonatomic,strong)NSString *al;//专辑名
    15 @property (nonatomic,strong)NSString *by;//歌词作者
    16 @property (nonatomic,strong)NSString *t_time;//歌曲总时长
    17 @property (nonatomic,strong)NSMutableArray *lrcArrayTime;//时间数组
    18 @property (nonatomic,strong)NSMutableArray *lrcArrayStr;//歌词数组
    19 
    20 - (instancetype)init;
    21 - (instancetype)initWithFileName:(NSString *)name ofType:(NSString *)type;
    22 - (instancetype)initWithFilePath:(NSString *)filePath;
    23 - (void)lyricsAnalysisWithFileName:(NSString *)name ofType:(NSString *)type;
    24 - (void)lyricsAnalysisWithFilePath:(NSString *)filePath;
    25 @end
    View Code

    以上是.h头文件源码 

    以下是.m源文件源码

     1 //
     2 //  LyricsAnalysis.m
     3 //  08-10-MusicPlayer
     4 //
     5 //  Created by Ibokan on 15/8/21.
     6 //  Copyright (c) 2015年 Crazy凡. All rights reserved.
     7 //
     8 
     9 #import "LyricsAnalysis.h"
    10 
    11 
    12 @interface LyricsAnalysis ()
    13 @property double offset;//歌词时间调整变量
    14 @end
    15 @implementation LyricsAnalysis
    16 
    17 //初始化
    18 - (instancetype)init
    19 {
    20     self = [super init];
    21     if (self) {
    22         self.ar = [[NSString alloc]init];
    23         self.ti = [[NSString alloc]init];
    24         self.by = [[NSString alloc]init];
    25         self.al = [[NSString alloc]init];
    26         self.offset = 0;
    27         self.t_time = [[NSString alloc]init];//歌曲总时长单位(s)
    28         self.lrcArrayStr = [[NSMutableArray alloc]init];//歌词数组初始化
    29         self.lrcArrayTime = [[NSMutableArray alloc]init];//时间数组初始化
    30     }
    31     return self;
    32 }
    33 //带文件名的初始化
    34 - (instancetype)initWithFileName:(NSString *)name ofType:(NSString *)type
    35 {
    36     self = [self init];
    37     [self lyricsAnalysisWithFileName:name ofType:type];
    38     return self;
    39 }
    40 //带文件路径的初始化
    41 - (instancetype)initWithFilePath:(NSString *)filePath
    42 {
    43     self = [self init];
    44     [self lyricsAnalysisWithFilePath:filePath];
    45     return self;
    46 }
    47 //处理文件名歌词
    48 - (void)lyricsAnalysisWithFileName:(NSString *)name ofType:(NSString *)type
    49 {
    50     [self lyricsAnalysisWithFilePath:[[NSBundle mainBundle] pathForResource:name ofType:type]];//构建filepath
    51 }
    52 //处理文件路径
    53 - (void)lyricsAnalysisWithFilePath:(NSString *)filePath
    54 {
    55     NSString *strlrc = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    56     NSMutableArray * arraylrc = [[NSMutableArray alloc] initWithArray:[strlrc componentsSeparatedByString:@"
    "]];
    57     NSArray *StrToInt = [NSArray arrayWithObjects:@"ar",@"ti",@"al",@"by",@"of",@"t_",nil];//NSString  switch 配置
    58     BOOL flag = YES;
    59     while(flag)
    60     {
    61         NSString *temp = arraylrc[0];
    62         switch ((int)[StrToInt indexOfObject:[temp substringWithRange:NSMakeRange(1, 2)]])
    63         {
    64             case 0:self.ar = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@""];break;
    65             case 1:self.ti = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@""];break;
    66             case 2:self.al = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@""];break;
    67             case 3:self.by = [[temp substringFromIndex:4]stringByReplacingOccurrencesOfString:@"]" withString:@""];break;
    68             case 4:self.offset = [[[temp substringFromIndex:8] stringByReplacingOccurrencesOfString:@"]" withString:@""] doubleValue];break;
    69             case 5:self.t_time = [[temp substringFromIndex:9] stringByReplacingOccurrencesOfString:@")]" withString:@""];break;
    70             default:flag = NO; break;
    71         }
    72         flag?[arraylrc removeObjectAtIndex:0]:nil;//判断是否需要移除已经被读取的信息(是歌词则不移除)
    73     }// lrc时间的格式分3种:[mm:ss.SS]、[mm:ss:SS]、[mm:ss];第一种是标准形式,后面两种存在但是不标准;先把时间字符串按照“:”拆分,生成{mm ss.SS}、{mm ss SS}、{mm ss};对于1、3,直接取doubleValue即可;注意分钟*60;对于第二种情况需要单独处理SS(毫秒)位;
    74     for (NSString *str in arraylrc) {
    75         NSArray * ArrayTemp = [str componentsSeparatedByString:@"]"];//分割每一句歌词
    76         for(int j = 0 ; j < ArrayTemp.count -1 ;j++)
    77         {
    78             NSArray * Arraytime = [[ArrayTemp[j] substringFromIndex:1] componentsSeparatedByString:@":"];//分割时间字符串
    79             double timedouble = [Arraytime[0] doubleValue]*60.0 + [Arraytime[1] doubleValue];//处理分钟和秒
    80             timedouble += Arraytime.count > 2 ? [[[NSString alloc]initWithFormat:@"0.%@",Arraytime[2]] doubleValue]:0;//处理毫秒位
    81             timedouble += (self.offset / 1000.0);//时间调整
    82             timedouble = timedouble > 0 ? timedouble : 0;//避免因为时间调整导致的时间<0
    83             int i = 0;
    84             while (i < self.lrcArrayTime.count && [self.lrcArrayTime[i++] doubleValue] < timedouble);//查找当前歌词的插入位置
    85             [self.lrcArrayTime insertObject:[[NSString alloc]initWithFormat:@"%lf",timedouble] atIndex:i];//插入时间数组
    86             [self.lrcArrayStr insertObject:ArrayTemp[ArrayTemp.count-1] atIndex:i];//插入歌词数组
    87         }
    88     }
    89 }
    90 @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:@""//替换

    NSMutableArray * arraylrc = [[NSMutableArray alloc] initWithArray:[strlrc componentsSeparatedByString:@" "]];//分割

    大量的字符串  处理函数  大家自多看吧,毕竟很常用也很重要

    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时

     

    注意:以上部分未在下面的源文件中更新


     代码中的细节,基本都做了注释,不懂得可以留言,我会尽可能的答复;
     
  • 相关阅读:
    java连接zookeeper实现zookeeper的基本操作
    spring boot 中用@value给static变量赋值
    jquery 点击移动一次body
    Javascript实现导航锚点滚动效果实例
    vue.js 脚手架vue-cli构建了项目,想去除Eslint验证,如何设置?
    jquery 点击切换值
    js同时(onclick)调用多个方法
    修改输入框placeholder文字默认颜色css用法
    js获取星期几
    js计算器
  • 原文地址:https://www.cnblogs.com/kongkaikai/p/4748822.html
Copyright © 2020-2023  润新知