歌詞處理-時間、歌詞截取 - (Obj-C)

歌詞.lrc文件實際存放的就是二進(jìn)制的字符串
歌詞.lrc文件的解析實際就是二進(jìn)制字符串解析

內(nèi)部格式大致為:

[03:02.00][01:05.00]這晚夜沒有吻別

主要由兩部分組成: 時間部分歌詞部分
兩個時間戳代表同一句歌詞會在兩個時間下顯示

歌詞解析:

1.先抽取一個歌詞模型類(存放每一句歌詞)
2.聲明屬性:時間(每句的起始時間) 和 歌詞(每一句)
3.創(chuàng)建一個工具類,專門用作解析歌詞,供外界直接調(diào)用

3.1 讀取歌詞字符串
3.2 分隔字符串為一個存放每一句歌詞的數(shù)組(包含時間和歌詞)
3.3 遍歷存放歌詞的數(shù)組,根據(jù)時間格式使用正則表達(dá)式過濾字符串,得到一個存放NSTextCheckingResult對象的數(shù)組
3.4 截取時間和歌詞,遍歷存放歌詞(含時間和歌詞)的數(shù)組:
      3.4.1 遍歷存放NSTextCheckingResult對象的數(shù)組,通過range屬性獲得時間(因為每句歌詞可能含多個時間戳)
      3.4.2 通過range屬性,截取歌詞
3.5 給歌詞模型屬性賦值
3.6 將得到的歌詞模型對象添加到可變數(shù)組
3.7 將存放歌詞模型對象的數(shù)組重新排序
  • 時間截取:
1. 每句歌詞可能含多個時間戳,所以在遍歷歌詞數(shù)組時,使用正則表達(dá)式過濾歌詞,會得到一個存放NSTextCheckingResult對象的數(shù)組,這里需要使用到NSTextCheckingResult的range屬性,再次遍歷存放NSTextCheckingResult對象的數(shù)組,通過range屬性截取時間字符串
2. 截取的是時間字符串,為了便于使用,這里將字符串轉(zhuǎn)為NSTimeInterval格式再進(jìn)行存儲(歌詞模型中也是直接使用NSTimeInterval聲明的)
  • 歌詞截取:
參考_歌詞內(nèi)部格式示例_,一句歌詞可能會有多個時間戳,根據(jù)正則表達(dá)式獲取到存放時間的數(shù)組,取出數(shù)組中最后一個元素,也就是每句歌詞中最后的一個時間戳:
用最后的時間戳的local + length才是全部時間部分的長度,也就得到了后面歌詞的索引
  • 示例代碼:

歌詞模型類(只是聲明了屬性,并未提供方法):

#import <Foundation/Foundation.h>

@interface JSLyricModel : NSObject

// 該句歌詞的初始時間
@property (nonatomic,assign) NSTimeInterval initialTime;
// 該句歌詞
@property (nonatomic,copy) NSString *content;


@end

歌詞解析工具類:

#import "JSLyricManager.h"
#import "NSDateFormatter+Shared.h"
#import "JSLyricModel.h"

@implementation JSLyricManager

+ (NSArray<JSLyricModel *> *)parserLyricWithFileName:(NSString *)fileName{
    
    // 取出歌詞字符串
    NSString *filePath = [[NSBundle mainBundle]pathForResource:fileName ofType:nil];
    NSString *lyricStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
    
    // 分隔字符串
    NSArray *lyricArr = [lyricStr componentsSeparatedByString:@"\n"];
    
    
    /*      正則表達(dá)式過濾字符串:
     [00:19.00]曲:河合奈保子 詞:向雪懷
     [02:19.00][00:23.00]仍然倚在失眠夜望天邊星宿
     */
    NSString *regularExpressionString = @"\\[[0-9]{2}:[0-9]{2}.[0-9]{2}\\]";
    NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:regularExpressionString options:0 error:nil];
    
    // 存放歌詞對象的臨時可變數(shù)組
    NSMutableArray *tempMarr = [NSMutableArray array];
    
    //遍歷歌詞數(shù)組,取出每一句歌詞
    for (NSString *element in lyricArr) {
        
        // 正則表達(dá)式遍歷
        NSArray<NSTextCheckingResult *> *textCheckingResult = [regularExpression matchesInString:element options:0 range:NSMakeRange(0, element.length)];
        
        // 2.截取歌詞內(nèi)容
        NSTextCheckingResult *lastTimeString = textCheckingResult.lastObject;// 取出得到數(shù)組中的最后一個時間元素,用來獲取range
        
        // 截取歌詞 (一句歌詞可能會有多個時間戳,取到最后一個時間戳,用自己的local + length才是全部時間部分的長度,也就得到了后面歌詞的索引)
        NSString *lyricContent = [element substringFromIndex:lastTimeString.range.length + lastTimeString.range.location];
        
        // 同一句歌詞可能多處顯示,所以返回值是一個數(shù)組,遍歷取出每一個起始時間字符串
        for (NSTextCheckingResult *result in textCheckingResult) {

            // 1. 截取時間字符串
            NSString *lyricSubString = [element substringWithRange:NSMakeRange(result.range.location, result.range.length)];
            
            // 截取玩后設(shè)置每一句歌詞的起始時間
            NSTimeInterval currentLyricInitialTime = [self timeIntervalWithTimeString:lyricSubString];
            
            // 創(chuàng)建歌詞模型
            JSLyricModel *model = [[JSLyricModel alloc]init];
            // 模型賦值
            model.initialTime = currentLyricInitialTime;// 給歌詞模型的歌詞初試時間賦值
            model.content = lyricContent;               // 給歌詞模型的歌詞內(nèi)容賦值
            
            // 添加到臨時可變數(shù)組
            [tempMarr addObject:model];
            
        }
        
    }
    
    // 歌詞起始時間排序
    NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"initialTime" ascending:YES];
    NSArray *lyricModelArr = [tempMarr sortedArrayUsingDescriptors:@[descriptor]];
    
    
    // 進(jìn)行解析
    return lyricModelArr;
}

// 將時間字符串轉(zhuǎn)換為NSTimerInterval類型,方便外面直接判斷
+ (NSTimeInterval)timeIntervalWithTimeString:(NSString *)timeString{
    
    // 時間字符串 --> 日期對象 NSDate  --> 計算對應(yīng)的時間間隔
    NSDateFormatter *dateFormatter = [NSDateFormatter sharedManager];
    // 設(shè)置格式
    dateFormatter.dateFormat = @"[mm:ss.SS]";
    // 創(chuàng)建初始時間對象 用來計算時間間隔
    NSDate *initialDate = [dateFormatter dateFromString:@"[00:00.00]"];
    // 將字符串轉(zhuǎn)換為NSDate
    NSDate *targetDate = [dateFormatter dateFromString:timeString];
    
    // 計算時間間隔
    return [targetDate timeIntervalSinceDate:initialDate];
    
}


@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市猿棉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖值骇,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異移国,居然都是意外死亡吱瘩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門迹缀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來搅裙,“玉大人,你說我怎么就攤上這事裹芝〔看” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵嫂易,是天一觀的道長兄朋。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么颅和? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任傅事,我火速辦了婚禮,結(jié)果婚禮上峡扩,老公的妹妹穿的比我還像新娘蹭越。我一直安慰自己,他們只是感情好教届,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布响鹃。 她就那樣靜靜地躺著,像睡著了一般案训。 火紅的嫁衣襯著肌膚如雪买置。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天强霎,我揣著相機(jī)與錄音忿项,去河邊找鬼。 笑死城舞,一個胖子當(dāng)著我的面吹牛轩触,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播家夺,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼脱柱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秦踪?” 一聲冷哼從身側(cè)響起褐捻,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎椅邓,沒想到半個月后柠逞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡景馁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年板壮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片合住。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡绰精,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出透葛,到底是詐尸還是另有隱情笨使,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布僚害,位于F島的核電站硫椰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜靶草,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一蹄胰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奕翔,春花似錦裕寨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至互艾,卻和暖如春试和,著一層夾襖步出監(jiān)牢的瞬間讯泣,已是汗流浹背纫普。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留好渠,地道東北人昨稼。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像拳锚,于是被迫代替她去往敵國和親假栓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法霍掺,類相關(guān)的語法匾荆,內(nèi)部類的語法,繼承相關(guān)的語法杆烁,異常的語法牙丽,線程的語...
    子非魚_t_閱讀 31,644評論 18 399
  • 前言 要解析 lrc 格式的歌詞, 首先需要知道什么是 lrc 歌詞, 還需要知道 lrc 歌詞的規(guī)范. 在這里先...
    李國安閱讀 5,392評論 8 14
  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司兔魂,掛了不少烤芦,但最終還是拿到小米、百度析校、阿里构罗、京東、新浪智玻、CVTE遂唧、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,255評論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)吊奢,斷路器盖彭,智...
    卡卡羅2017閱讀 134,672評論 18 139
  • Sorry Sorry 鎖骨旁邊 藍(lán)色英文紋身 戴著口罩的你 高冷的讓我窒息 然而你的眼神 那么迷人 我只敢用余光...
    停停不能停閱讀 192評論 0 2