From cd2b27aac4eec47039392ae38e931eda98d76bb2 Mon Sep 17 00:00:00 2001 From: gychao Date: Sat, 24 Sep 2016 17:03:57 +0800 Subject: [PATCH 1/4] clear --- .../LRCParserDemo.xcodeproj/project.pbxproj | 21 +++++++++++++------ .../LRCParserDemo/DDDetailViewController.h | 2 +- .../LRCParserDemo/DDRootViewController.m | 2 +- .../{ => LRCParser}/DDAudioLRCParser.h | 0 .../{ => LRCParser}/DDAudioLRCParser.m | 0 5 files changed, 17 insertions(+), 8 deletions(-) rename LRCParserDemo/LRCParserDemo/{ => LRCParser}/DDAudioLRCParser.h (100%) rename LRCParserDemo/LRCParserDemo/{ => LRCParser}/DDAudioLRCParser.m (100%) diff --git a/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj b/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj index 2b4b317..48ea4bb 100644 --- a/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj +++ b/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj @@ -7,12 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + 0D9D08F91D96759800C2B742 /* DDAudioLRCParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D9D08F81D96759800C2B742 /* DDAudioLRCParser.m */; }; 985836911C7E9B66007E6CB5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 985836901C7E9B66007E6CB5 /* main.m */; }; 985836941C7E9B66007E6CB5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 985836931C7E9B66007E6CB5 /* AppDelegate.m */; }; 9858369A1C7E9B66007E6CB5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 985836981C7E9B66007E6CB5 /* Main.storyboard */; }; 9858369C1C7E9B66007E6CB5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9858369B1C7E9B66007E6CB5 /* Assets.xcassets */; }; 9858369F1C7E9B66007E6CB5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9858369D1C7E9B66007E6CB5 /* LaunchScreen.storyboard */; }; - 985836A81C7E9B7E007E6CB5 /* DDAudioLRCParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 985836A71C7E9B7E007E6CB5 /* DDAudioLRCParser.m */; }; 985836AA1C7ECC73007E6CB5 /* TestLRC1 in Resources */ = {isa = PBXBuildFile; fileRef = 985836A91C7ECC73007E6CB5 /* TestLRC1 */; }; 985836AC1C7ECD04007E6CB5 /* TestLRC2 in Resources */ = {isa = PBXBuildFile; fileRef = 985836AB1C7ECD04007E6CB5 /* TestLRC2 */; }; 985836B01C7ECEA8007E6CB5 /* DDRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 985836AF1C7ECEA8007E6CB5 /* DDRootViewController.m */; }; @@ -20,6 +20,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0D9D08F71D96759800C2B742 /* DDAudioLRCParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDAudioLRCParser.h; sourceTree = ""; }; + 0D9D08F81D96759800C2B742 /* DDAudioLRCParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDAudioLRCParser.m; sourceTree = ""; }; 9858368C1C7E9B66007E6CB5 /* LRCParserDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LRCParserDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 985836901C7E9B66007E6CB5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 985836921C7E9B66007E6CB5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -28,8 +30,6 @@ 9858369B1C7E9B66007E6CB5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 9858369E1C7E9B66007E6CB5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 985836A01C7E9B66007E6CB5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 985836A61C7E9B7E007E6CB5 /* DDAudioLRCParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDAudioLRCParser.h; sourceTree = ""; }; - 985836A71C7E9B7E007E6CB5 /* DDAudioLRCParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDAudioLRCParser.m; sourceTree = ""; }; 985836A91C7ECC73007E6CB5 /* TestLRC1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TestLRC1; sourceTree = ""; }; 985836AB1C7ECD04007E6CB5 /* TestLRC2 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TestLRC2; sourceTree = ""; }; 985836AE1C7ECEA8007E6CB5 /* DDRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDRootViewController.h; sourceTree = ""; }; @@ -49,6 +49,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0D9D08F61D96759800C2B742 /* LRCParser */ = { + isa = PBXGroup; + children = ( + 0D9D08F71D96759800C2B742 /* DDAudioLRCParser.h */, + 0D9D08F81D96759800C2B742 /* DDAudioLRCParser.m */, + ); + path = LRCParser; + sourceTree = ""; + }; 985836831C7E9B66007E6CB5 = { isa = PBXGroup; children = ( @@ -68,8 +77,7 @@ 9858368E1C7E9B66007E6CB5 /* LRCParserDemo */ = { isa = PBXGroup; children = ( - 985836A61C7E9B7E007E6CB5 /* DDAudioLRCParser.h */, - 985836A71C7E9B7E007E6CB5 /* DDAudioLRCParser.m */, + 0D9D08F61D96759800C2B742 /* LRCParser */, 985836921C7E9B66007E6CB5 /* AppDelegate.h */, 985836931C7E9B66007E6CB5 /* AppDelegate.m */, 985836AD1C7ECE83007E6CB5 /* UI */, @@ -176,10 +184,10 @@ buildActionMask = 2147483647; files = ( 985836B01C7ECEA8007E6CB5 /* DDRootViewController.m in Sources */, - 985836A81C7E9B7E007E6CB5 /* DDAudioLRCParser.m in Sources */, 985836941C7E9B66007E6CB5 /* AppDelegate.m in Sources */, 985836911C7E9B66007E6CB5 /* main.m in Sources */, 985836B31C7ECEB8007E6CB5 /* DDDetailViewController.m in Sources */, + 0D9D08F91D96759800C2B742 /* DDAudioLRCParser.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -326,6 +334,7 @@ 985836A51C7E9B66007E6CB5 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/LRCParserDemo/LRCParserDemo/DDDetailViewController.h b/LRCParserDemo/LRCParserDemo/DDDetailViewController.h index 8e6444a..fca76fb 100644 --- a/LRCParserDemo/LRCParserDemo/DDDetailViewController.h +++ b/LRCParserDemo/LRCParserDemo/DDDetailViewController.h @@ -7,7 +7,7 @@ // #import -#import "DDAudioLRCParser.h" +#import "LRCParser/DDAudioLRCParser.h" @interface DDDetailViewController : UITableViewController @property (strong, nonatomic) DDAudioLRC *lrc; diff --git a/LRCParserDemo/LRCParserDemo/DDRootViewController.m b/LRCParserDemo/LRCParserDemo/DDRootViewController.m index 98c8d59..587e67f 100644 --- a/LRCParserDemo/LRCParserDemo/DDRootViewController.m +++ b/LRCParserDemo/LRCParserDemo/DDRootViewController.m @@ -7,7 +7,7 @@ // #import "DDRootViewController.h" -#import "DDAudioLRCParser.h" +#import "LRCParser/DDAudioLRCParser.h" #import "DDDetailViewController.h" @interface DDRootViewController () diff --git a/LRCParserDemo/LRCParserDemo/DDAudioLRCParser.h b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h similarity index 100% rename from LRCParserDemo/LRCParserDemo/DDAudioLRCParser.h rename to LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h diff --git a/LRCParserDemo/LRCParserDemo/DDAudioLRCParser.m b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m similarity index 100% rename from LRCParserDemo/LRCParserDemo/DDAudioLRCParser.m rename to LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m From 4e274ba476074815c39ca067d8450e164922700b Mon Sep 17 00:00:00 2001 From: gychao Date: Sun, 25 Sep 2016 14:04:09 +0800 Subject: [PATCH 2/4] =?UTF-8?q?update=20demo=20=E4=B8=AD=20lrc=20=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=BA=93=EF=BC=8C=E4=BD=BF=E5=85=B6=E8=83=BD=E5=A4=9F?= =?UTF-8?q?=20=E8=A7=A3=E6=9E=90=20lrc=20=E4=B8=89=E7=A7=8D=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、标准格式: [分钟:秒.毫秒] 歌词 注释:(如右图所示)中括号、冒号、点号全都要求英文输入状态; 2、其他格式①:[分钟:秒] 歌词; 3、其他格式②:[分钟:秒:毫秒] 歌词,与标准格式相比,秒后边的点号被改成了冒号。 --- LRCParserDemo/LRCParserDemo/AppDelegate.m | 21 +++++ .../LRCParser/DDAudioLRCParser.m | 77 ++++++++++--------- 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/LRCParserDemo/LRCParserDemo/AppDelegate.m b/LRCParserDemo/LRCParserDemo/AppDelegate.m index b4d4ea7..89c840e 100644 --- a/LRCParserDemo/LRCParserDemo/AppDelegate.m +++ b/LRCParserDemo/LRCParserDemo/AppDelegate.m @@ -17,6 +17,27 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. + + NSString * test = @"[00:53.00][01:43.88][02:1]虽然无所谓写在脸上"; + NSString * regex = @"(\\[\\d{0,2}:\\d{0,2}([.|:]\\d{0,2})?\\])"; + + NSRegularExpression * re = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:nil]; + + NSString * modefiy = [re stringByReplacingMatchesInString:test options:0 range:NSMakeRange(0, test.length) withTemplate:@""]; + + + if (re) { + NSArray * results = [re matchesInString:test options:0 range:NSMakeRange(0, test.length)]; + + for (NSTextCheckingResult * res in results) { + + NSString * substr = [test substringWithRange: res.range]; + NSLog(@"findstring is %@",substr); + } + } + + + return YES; } diff --git a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m index e9dfde6..69b61c1 100644 --- a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m +++ b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m @@ -29,19 +29,24 @@ + (DDAudioLRC *)parser:(NSString *)lrc kDDLRCMetadataKeyBY, kDDLRCMetadataKeyOFFSET]; - NSString *reg = @"\\[(\\d{0,2}:\\d{0,2}[.|:]\\d{0,2})\\].*?"; - NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:reg options:NSRegularExpressionCaseInsensitive error:nil]; - NSString *reg2 = @".*\\[\\d{0,2}:\\d{0,2}[.|:]\\d{0,2}\\](.*)"; - NSRegularExpression *re2 = [NSRegularExpression regularExpressionWithPattern:reg2 options:NSRegularExpressionCaseInsensitive error:nil]; + NSString * reg = @"(\\[\\d{0,2}:\\d{0,2}([.|:]\\d{0,2})?\\])"; + NSRegularExpression * eachTimeReg = [NSRegularExpression regularExpressionWithPattern:reg options:NSRegularExpressionCaseInsensitive error:nil]; - NSMutableArray *units = [NSMutableArray array]; + NSString *reg2 = @"(\\[\\d{0,2}:\\d{0,2}([.|:]\\d{0,2})?\\])+"; + NSRegularExpression * allTimeReg = [NSRegularExpression regularExpressionWithPattern:reg2 options:NSRegularExpressionCaseInsensitive error:nil]; + NSMutableArray *units = [NSMutableArray array]; NSArray *lines = [lrc componentsSeparatedByString:@"\n"]; + + NSString *sec; + NSArray *matches; + NSString *modifyString; + + for (NSString *aLine in lines) { if (aLine.length <= 1) { continue; } - BOOL isATag = NO; //歌曲信息 @@ -63,30 +68,27 @@ + (DDAudioLRC *)parser:(NSString *)lrc continue; } - //歌词信息 - NSArray *matches = [re matchesInString:aLine options:0 range:NSMakeRange(0, aLine.length)]; + // 歌词时间信息 + matches = [eachTimeReg matchesInString:aLine options:0 range:NSMakeRange(0, aLine.length)]; + + /**< 歌词*/ + modifyString = [allTimeReg stringByReplacingMatchesInString:aLine options:0 range:NSMakeRange(0, aLine.length) withTemplate:@""]; for (NSTextCheckingResult *result in matches) { - NSUInteger count = result.numberOfRanges; - if (count >= 2) { - NSRange secRange = [result rangeAtIndex:1]; - NSString *secString = [[aLine substringWithRange:secRange] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - - [re2 enumerateMatchesInString:aLine options:0 range:NSMakeRange(0, aLine.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { - NSUInteger count = result.numberOfRanges; - if (count >= 2) { - NSRange lrcRange = [result rangeAtIndex:1]; - NSString *lrc = [aLine substringWithRange:lrcRange]; - - DDAudioLRCUnit *unit = [DDAudioLRCUnit new]; - unit.secString = secString; - unit.lrc = lrc; - [units addObject:unit]; - } - }]; + if (result.range.location == NSNotFound) { + continue; } + sec = [aLine substringWithRange:result.range]; + sec = [sec stringByReplacingOccurrencesOfString:@"[" withString:@""]; + sec = [sec stringByReplacingOccurrencesOfString:@"]" withString:@""]; + + DDAudioLRCUnit *unit = [DDAudioLRCUnit new]; + unit.secString = sec; + unit.lrc = modifyString; + [units addObject:unit]; } } + tmp.units = [self sortedLRCUnits:units]; tmp.originLRCText = lrc; return tmp; @@ -245,17 +247,20 @@ - (void)setSecString:(NSString *)secString NSInteger s = 0; //秒 NSInteger ms = 0; //毫秒 - NSScanner *scanner = [NSScanner scannerWithString:secString]; - NSCharacterSet *set = [NSCharacterSet decimalDigitCharacterSet]; - - [scanner scanUpToCharactersFromSet:set intoString:nil]; - [scanner scanInteger:&m]; - [scanner scanUpToCharactersFromSet:set intoString:nil]; - [scanner scanInteger:&s]; - [scanner scanUpToCharactersFromSet:set intoString:nil]; - [scanner scanInteger:&ms]; + NSArray * components = [secString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":."]]; + if (components && components.count >= 2) { + m = [components[0] integerValue]; + s = [components[1] integerValue]; + if (components.count == 3) { + ms = [components[2] integerValue]; + }else{ + ms = 0; + } + }else{ + s = INT_MAX; + } - NSTimeInterval time = m*60 + s + ms*0.01; + NSTimeInterval time = m*60 + s + ms*0.001; self->_sec = time; } @@ -263,4 +268,4 @@ - (NSString *)description { return [NSString stringWithFormat:@"%@, timeSecond:%.0f , LRC:%@",[super description],self.sec,self.lrc]; } -@end \ No newline at end of file +@end From 6bdce93029e654d4a2b45f4e12963fcd509f2b85 Mon Sep 17 00:00:00 2001 From: gychao Date: Mon, 26 Sep 2016 11:38:22 +0800 Subject: [PATCH 3/4] fix clear --- LRCParser/DDAudioLRCParser.h | 54 ---- LRCParser/DDAudioLRCParser.m | 266 ------------------ .../LRCParser/DDAudioLRCParser.h | 7 +- .../LRCParser/DDAudioLRCParser.m | 40 ++- 4 files changed, 35 insertions(+), 332 deletions(-) delete mode 100644 LRCParser/DDAudioLRCParser.h delete mode 100644 LRCParser/DDAudioLRCParser.m diff --git a/LRCParser/DDAudioLRCParser.h b/LRCParser/DDAudioLRCParser.h deleted file mode 100644 index f03eedc..0000000 --- a/LRCParser/DDAudioLRCParser.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// DDAudioLRCParser.h -// JuYouQu -// -// Created by Normal on 16/2/19. -// Copyright © 2016年 Bo Wang. All rights reserved. -// - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class DDAudioLRC; -@class DDAudioLRCUnit; - -@interface DDAudioLRCParser : NSObject -+ (nullable DDAudioLRC *)parserLRCText:(NSString *)lrc; -@end - -FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyTI;//歌曲名 -FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyAR;//歌手名 -FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyAL;//专辑 -FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyBY;//编辑者 -FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyOFFSET;//补偿 -FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyTIME;//时长 - -@interface DDAudioLRC : NSObject -@property (nullable, strong, nonatomic) NSString *originLRCText; -@property (nullable, strong, nonatomic) NSArray *units; - -// 歌词上附带的一些歌曲数据。根据 keys 取数据,数据是否存在由歌词决定。 -- (void)setMetadata:(nullable id)value forKey:(NSString *)key; -- (nullable id)metadataForKey:(NSString *)key; - -// 根据时间返回相应歌词所在行数 -- (NSRange)linesAtTimeSecondFrom:(NSTimeInterval)from to:(NSTimeInterval)end; -- (NSUInteger)lineAtTimeSecond:(NSTimeInterval)sec; - -// 根据时间返回相应的歌词 -- (nullable NSArray *)LRCUnitsAtTimeSecondFrom:(NSTimeInterval)from to:(NSTimeInterval)end; -- (nullable DDAudioLRCUnit *)LRCUnitAtTimeSecond:(NSTimeInterval)sec; - -// 返回歌词行数对应的歌词内容 -- (nullable NSArray *)LRCUnitsAtLines:(NSRange)range; -- (nullable DDAudioLRCUnit *)LRCUnitAtLine:(NSUInteger)line; -@end - -@interface DDAudioLRCUnit : NSObject -@property (nullable, strong, nonatomic) NSString *secString; -@property (assign, readonly, nonatomic) NSTimeInterval sec; -@property (nullable, strong, nonatomic) NSString *lrc; -@end - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/LRCParser/DDAudioLRCParser.m b/LRCParser/DDAudioLRCParser.m deleted file mode 100644 index e9dfde6..0000000 --- a/LRCParser/DDAudioLRCParser.m +++ /dev/null @@ -1,266 +0,0 @@ -// -// DDAudioLRCParser.m -// JuYouQu -// -// Created by Normal on 16/2/19. -// Copyright © 2016年 Bo Wang. All rights reserved. -// - -#import "DDAudioLRCParser.h" - -@implementation DDAudioLRCParser - -+ (DDAudioLRC *)parserLRCText:(NSString *)lrc -{ - return [self parser:lrc]; -} - -+ (DDAudioLRC *)parser:(NSString *)lrc -{ - if (!lrc || lrc.length == 0) { - return nil; - } - - DDAudioLRC *tmp = [DDAudioLRC new]; - - NSArray *tags = @[kDDLRCMetadataKeyTI, - kDDLRCMetadataKeyAR, - kDDLRCMetadataKeyAL, - kDDLRCMetadataKeyBY, - kDDLRCMetadataKeyOFFSET]; - - NSString *reg = @"\\[(\\d{0,2}:\\d{0,2}[.|:]\\d{0,2})\\].*?"; - NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:reg options:NSRegularExpressionCaseInsensitive error:nil]; - NSString *reg2 = @".*\\[\\d{0,2}:\\d{0,2}[.|:]\\d{0,2}\\](.*)"; - NSRegularExpression *re2 = [NSRegularExpression regularExpressionWithPattern:reg2 options:NSRegularExpressionCaseInsensitive error:nil]; - - NSMutableArray *units = [NSMutableArray array]; - - NSArray *lines = [lrc componentsSeparatedByString:@"\n"]; - for (NSString *aLine in lines) { - if (aLine.length <= 1) { - continue; - } - - BOOL isATag = NO; - - //歌曲信息 - for (NSString *tag in tags) { - if (![tmp metadataForKey:tag]) { - NSString *prefix = [NSString stringWithFormat:@"[%@:",tag]; - if ([aLine hasPrefix:prefix] && [aLine hasSuffix:@"]"]) { - NSUInteger loc = prefix.length; - NSUInteger len = aLine.length - loc - 1; - NSString *info = [aLine substringWithRange:NSMakeRange(loc, len)]; - [tmp setMetadata:info forKey:tag]; - isATag = YES; - break; - } - } - } - - if (isATag) { - continue; - } - - //歌词信息 - NSArray *matches = [re matchesInString:aLine options:0 range:NSMakeRange(0, aLine.length)]; - - for (NSTextCheckingResult *result in matches) { - NSUInteger count = result.numberOfRanges; - if (count >= 2) { - NSRange secRange = [result rangeAtIndex:1]; - NSString *secString = [[aLine substringWithRange:secRange] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - - [re2 enumerateMatchesInString:aLine options:0 range:NSMakeRange(0, aLine.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { - NSUInteger count = result.numberOfRanges; - if (count >= 2) { - NSRange lrcRange = [result rangeAtIndex:1]; - NSString *lrc = [aLine substringWithRange:lrcRange]; - - DDAudioLRCUnit *unit = [DDAudioLRCUnit new]; - unit.secString = secString; - unit.lrc = lrc; - [units addObject:unit]; - } - }]; - } - } - } - tmp.units = [self sortedLRCUnits:units]; - tmp.originLRCText = lrc; - return tmp; -} - -+ (NSArray *)sortedLRCUnits:(NSArray *)units -{ - //按时间排序 - NSArray *sorted = [units sortedArrayUsingComparator:^NSComparisonResult(DDAudioLRCUnit *obj1, DDAudioLRCUnit *obj2) { - if (obj1.sec < obj2.sec) { - return NSOrderedAscending; - }else{ - return NSOrderedDescending; - } - }]; - return sorted; -} - -@end - -NSString *kDDLRCMetadataKeyTI = @"ti"; -NSString *kDDLRCMetadataKeyAR = @"ar"; -NSString *kDDLRCMetadataKeyAL = @"al"; -NSString *kDDLRCMetadataKeyBY = @"by"; -NSString *kDDLRCMetadataKeyOFFSET = @"offset"; -NSString *kDDLRCMetadataKeyTIME = @"t_time"; - -@implementation DDAudioLRC -{ - NSMutableDictionary *_medatata; - NSNumber *_offset; -} - -- (void)setMetadata:(id)value forKey:(NSString *)key -{ - if (!_medatata) { - _medatata = [NSMutableDictionary dictionary]; - } - if (value && key) { - _medatata[key] = value; - } -} - -- (id)metadataForKey:(NSString *)key -{ - return _medatata[key]; -} - -- (float)lrcOffset -{ - if (!_offset) { - _offset = [self metadataForKey:kDDLRCMetadataKeyOFFSET]; - } - return _offset.floatValue; -} - -- (NSRange)linesAtTimeSecondFrom:(NSTimeInterval)from to:(NSTimeInterval)to -{ - if (from > to) { - return NSMakeRange(NSNotFound, 0); - } - - NSTimeInterval start = from + [self lrcOffset]; - NSTimeInterval end = to + [self lrcOffset]; - - NSMutableIndexSet *indexSets = [NSMutableIndexSet indexSet]; - [self.units enumerateObjectsUsingBlock:^(DDAudioLRCUnit *obj, NSUInteger idx, BOOL *stop) { - if (obj.sec >= start && obj.sec <= end) { - [indexSets addIndex:idx]; - } - if (obj.sec > end) { - *stop = YES; - } - }]; - - NSUInteger firstIndex = [indexSets firstIndex]; - NSUInteger lastIndex = [indexSets lastIndex]; - if (firstIndex > 0) { - firstIndex --; - } - - NSUInteger numberOfLines = lastIndex - firstIndex + 1; - NSRange range = NSMakeRange(firstIndex, numberOfLines); - return range; -} - -- (NSUInteger)lineAtTimeSecond:(NSTimeInterval)sec -{ - NSRange range = [self linesAtTimeSecondFrom:sec to:sec+0.001]; - return range.location; -} - -- (NSArray *)LRCUnitsAtTimeSecondFrom:(NSTimeInterval)from to:(NSTimeInterval)end -{ - NSRange range = [self linesAtTimeSecondFrom:from to:end]; - return [self LRCUnitsAtLines:range]; -} - -- (DDAudioLRCUnit *)LRCUnitAtTimeSecond:(NSTimeInterval)sec -{ - return [[self LRCUnitsAtTimeSecondFrom:sec to:sec+0.001] firstObject]; -} - -- (NSArray *)LRCUnitsAtLines:(NSRange)range -{ - return [self safeSubarrayWithRange:range inArray:self.units]; -} - -- (DDAudioLRCUnit *)LRCUnitAtLine:(NSUInteger)line -{ - return [[self LRCUnitsAtLines:NSMakeRange(line, 1)] firstObject]; -} - -/** - * @brief 安全的取子数组。根据范围尽量取到合适的子数组,范围越界时也取。 - * - * @param range 子数组范围 - * @param array 父数组 - * - * @return 子数组 - */ -- (NSArray *)safeSubarrayWithRange:(NSRange)range inArray:(NSArray *)array -{ - if (range.location == NSNotFound || !array || array.count == 0) { - return nil; - } - - NSUInteger count = array.count; - NSUInteger loc = range.location; - NSUInteger len = range.length; - - if (loc >= count) { - return nil; - } - if (count - loc < len) { //防止整形溢出 - len = count - loc; - } - NSRange safeRange = NSMakeRange(loc, len); - return [array subarrayWithRange:safeRange]; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@\nmetedata:%@\n%@",[super description],_medatata,self.units]; -} - -@end - -@implementation DDAudioLRCUnit - -- (void)setSecString:(NSString *)secString -{ - _secString = secString; - - NSInteger m = 0; //分 - NSInteger s = 0; //秒 - NSInteger ms = 0; //毫秒 - - NSScanner *scanner = [NSScanner scannerWithString:secString]; - NSCharacterSet *set = [NSCharacterSet decimalDigitCharacterSet]; - - [scanner scanUpToCharactersFromSet:set intoString:nil]; - [scanner scanInteger:&m]; - [scanner scanUpToCharactersFromSet:set intoString:nil]; - [scanner scanInteger:&s]; - [scanner scanUpToCharactersFromSet:set intoString:nil]; - [scanner scanInteger:&ms]; - - NSTimeInterval time = m*60 + s + ms*0.01; - self->_sec = time; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@, timeSecond:%.0f , LRC:%@",[super description],self.sec,self.lrc]; -} -@end \ No newline at end of file diff --git a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h index f03eedc..4ef4dff 100644 --- a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h +++ b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h @@ -47,8 +47,11 @@ FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyTIME;//时长 @interface DDAudioLRCUnit : NSObject @property (nullable, strong, nonatomic) NSString *secString; -@property (assign, readonly, nonatomic) NSTimeInterval sec; +@property (assign, readonly, nonatomic) NSTimeInterval sec; // 起始时间 +@property (assign, readonly, nonatomic) NSTimeInterval end; // 结束时间 也就是下一个的起始时间 @property (nullable, strong, nonatomic) NSString *lrc; + +- (void)configSecString:(NSString *)secString andIsEnd:(BOOL)isend; @end -NS_ASSUME_NONNULL_END \ No newline at end of file +NS_ASSUME_NONNULL_END diff --git a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m index 69b61c1..e623cf6 100644 --- a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m +++ b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m @@ -27,7 +27,9 @@ + (DDAudioLRC *)parser:(NSString *)lrc kDDLRCMetadataKeyAR, kDDLRCMetadataKeyAL, kDDLRCMetadataKeyBY, - kDDLRCMetadataKeyOFFSET]; + kDDLRCMetadataKeyOFFSET, + kDDLRCMetadataKeyTIME + ]; NSString * reg = @"(\\[\\d{0,2}:\\d{0,2}([.|:]\\d{0,2})?\\])"; NSRegularExpression * eachTimeReg = [NSRegularExpression regularExpressionWithPattern:reg options:NSRegularExpressionCaseInsensitive error:nil]; @@ -104,6 +106,18 @@ + (DDAudioLRC *)parser:(NSString *)lrc return NSOrderedDescending; } }]; + + DDAudioLRCUnit * first; + DDAudioLRCUnit * second; + for (int i = 0; i= sorted.count) { + [first configSecString:@"60000:50:00" andIsEnd:YES]; + }else{ + second = sorted[i+1]; + [first configSecString:second.secString andIsEnd:YES]; + } + } return sorted; } @@ -156,7 +170,7 @@ - (NSRange)linesAtTimeSecondFrom:(NSTimeInterval)from to:(NSTimeInterval)to NSMutableIndexSet *indexSets = [NSMutableIndexSet indexSet]; [self.units enumerateObjectsUsingBlock:^(DDAudioLRCUnit *obj, NSUInteger idx, BOOL *stop) { - if (obj.sec >= start && obj.sec <= end) { + if (start >= obj.sec && start <= obj.end) { [indexSets addIndex:idx]; } if (obj.sec > end) { @@ -166,10 +180,7 @@ - (NSRange)linesAtTimeSecondFrom:(NSTimeInterval)from to:(NSTimeInterval)to NSUInteger firstIndex = [indexSets firstIndex]; NSUInteger lastIndex = [indexSets lastIndex]; - if (firstIndex > 0) { - firstIndex --; - } - + NSUInteger numberOfLines = lastIndex - firstIndex + 1; NSRange range = NSMakeRange(firstIndex, numberOfLines); return range; @@ -239,9 +250,12 @@ - (NSString *)description @implementation DDAudioLRCUnit -- (void)setSecString:(NSString *)secString + +- (void)configSecString:(NSString *)secString andIsEnd:(BOOL)isend { - _secString = secString; + if (!isend) { + _secString = secString; //eg 33:33:21 + } NSInteger m = 0; //分 NSInteger s = 0; //秒 @@ -261,11 +275,17 @@ - (void)setSecString:(NSString *)secString } NSTimeInterval time = m*60 + s + ms*0.001; - self->_sec = time; + if (isend) { + self -> _end = time; + }else{ + self->_sec = time; + } } + + - (NSString *)description { - return [NSString stringWithFormat:@"%@, timeSecond:%.0f , LRC:%@",[super description],self.sec,self.lrc]; + return [NSString stringWithFormat:@"%@, start:%.2f end %.2f, LRC:%@",[super description],self.sec,self.end,self.lrc]; } @end From 71359b57df65640a7c98ee107716f3f3133914ae Mon Sep 17 00:00:00 2001 From: gychao Date: Mon, 26 Sep 2016 11:54:05 +0800 Subject: [PATCH 4/4] 2.0 --- .../LRCParserDemo.xcodeproj/project.pbxproj | 6 + .../LRCParserDemo/DDDetailViewController.h | 2 +- .../LRCParserDemo/DDDetailViewController.m | 25 ++-- .../LRCParserDemo/DDRootViewController.m | 13 +- .../LRCParser/DDAudioLRCParser.h | 24 +++- .../LRCParser/DDAudioLRCParser.m | 85 ++++++++++-- .../LRCParserDemo/LRCParser/ZXCommonTool.h | 48 +++++++ .../LRCParserDemo/LRCParser/ZXCommonTool.m | 130 ++++++++++++++++++ LRCParserDemo/LRCParserDemo/TestLRC1 | 6 +- README.md | 2 +- 10 files changed, 302 insertions(+), 39 deletions(-) create mode 100644 LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.h create mode 100644 LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.m diff --git a/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj b/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj index 48ea4bb..03213b9 100644 --- a/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj +++ b/LRCParserDemo/LRCParserDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0D37A8021D98D0CB00C7A51E /* ZXCommonTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D37A8011D98D0CB00C7A51E /* ZXCommonTool.m */; }; 0D9D08F91D96759800C2B742 /* DDAudioLRCParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D9D08F81D96759800C2B742 /* DDAudioLRCParser.m */; }; 985836911C7E9B66007E6CB5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 985836901C7E9B66007E6CB5 /* main.m */; }; 985836941C7E9B66007E6CB5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 985836931C7E9B66007E6CB5 /* AppDelegate.m */; }; @@ -20,6 +21,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0D37A8001D98D0CB00C7A51E /* ZXCommonTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZXCommonTool.h; sourceTree = ""; }; + 0D37A8011D98D0CB00C7A51E /* ZXCommonTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZXCommonTool.m; sourceTree = ""; }; 0D9D08F71D96759800C2B742 /* DDAudioLRCParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDAudioLRCParser.h; sourceTree = ""; }; 0D9D08F81D96759800C2B742 /* DDAudioLRCParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDAudioLRCParser.m; sourceTree = ""; }; 9858368C1C7E9B66007E6CB5 /* LRCParserDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LRCParserDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -52,6 +55,8 @@ 0D9D08F61D96759800C2B742 /* LRCParser */ = { isa = PBXGroup; children = ( + 0D37A8001D98D0CB00C7A51E /* ZXCommonTool.h */, + 0D37A8011D98D0CB00C7A51E /* ZXCommonTool.m */, 0D9D08F71D96759800C2B742 /* DDAudioLRCParser.h */, 0D9D08F81D96759800C2B742 /* DDAudioLRCParser.m */, ); @@ -185,6 +190,7 @@ files = ( 985836B01C7ECEA8007E6CB5 /* DDRootViewController.m in Sources */, 985836941C7E9B66007E6CB5 /* AppDelegate.m in Sources */, + 0D37A8021D98D0CB00C7A51E /* ZXCommonTool.m in Sources */, 985836911C7E9B66007E6CB5 /* main.m in Sources */, 985836B31C7ECEB8007E6CB5 /* DDDetailViewController.m in Sources */, 0D9D08F91D96759800C2B742 /* DDAudioLRCParser.m in Sources */, diff --git a/LRCParserDemo/LRCParserDemo/DDDetailViewController.h b/LRCParserDemo/LRCParserDemo/DDDetailViewController.h index fca76fb..fe7b7b6 100644 --- a/LRCParserDemo/LRCParserDemo/DDDetailViewController.h +++ b/LRCParserDemo/LRCParserDemo/DDDetailViewController.h @@ -10,5 +10,5 @@ #import "LRCParser/DDAudioLRCParser.h" @interface DDDetailViewController : UITableViewController -@property (strong, nonatomic) DDAudioLRC *lrc; +@property (strong, nonatomic) NSString *lrcPath; @end diff --git a/LRCParserDemo/LRCParserDemo/DDDetailViewController.m b/LRCParserDemo/LRCParserDemo/DDDetailViewController.m index 1a821c9..ae920a7 100644 --- a/LRCParserDemo/LRCParserDemo/DDDetailViewController.m +++ b/LRCParserDemo/LRCParserDemo/DDDetailViewController.m @@ -7,9 +7,11 @@ // #import "DDDetailViewController.h" +#import "LRCParser/DDAudioLRCParser.h" -@interface DDDetailViewController () +@interface DDDetailViewController () +@property (nonatomic,strong)DDAudioLRCParser * lrcParser; @end @implementation DDDetailViewController @@ -17,31 +19,34 @@ @implementation DDDetailViewController - (void)viewDidLoad { [super viewDidLoad]; + + self.lrcParser = [[DDAudioLRCParser alloc] init]; + [self.lrcParser parserLRCTextAtFilePath:self.lrcPath WithDelegate:self]; - NSTimeInterval start = 20.f; - NSTimeInterval end = 46.f; - - NSArray *lrcs = [self.lrc LRCUnitsAtTimeSecondFrom:start to:end]; - NSLog(@"lrcs"); } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.lrc.units.count; + return self.lrcParser.AudioLRC.units.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier" forIndexPath:indexPath]; - - DDAudioLRCUnit *unit = [self.lrc LRCUnitAtLine:indexPath.row]; - cell.textLabel.text = [NSString stringWithFormat:@"%.0f",unit.sec]; + DDAudioLRCUnit *unit = [self.lrcParser.AudioLRC LRCUnitAtLine:indexPath.row]; + cell.textLabel.text = [NSString stringWithFormat:@"%.3f",unit.sec]; cell.detailTextLabel.text = unit.lrc; return cell; } +#pragma mark - lrc parser delegate +- (void)parserDidFinishWithLRC:(DDAudioLRC *)AudioLRC{ + + [self.tableView reloadData]; +} + @end diff --git a/LRCParserDemo/LRCParserDemo/DDRootViewController.m b/LRCParserDemo/LRCParserDemo/DDRootViewController.m index 587e67f..b2776fc 100644 --- a/LRCParserDemo/LRCParserDemo/DDRootViewController.m +++ b/LRCParserDemo/LRCParserDemo/DDRootViewController.m @@ -7,7 +7,6 @@ // #import "DDRootViewController.h" -#import "LRCParser/DDAudioLRCParser.h" #import "DDDetailViewController.h" @interface DDRootViewController () @@ -23,16 +22,10 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath { if (indexPath.row == 0) { NSString *path = [[NSBundle mainBundle] pathForResource:@"TestLRC1" ofType:@""]; - NSString *text = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; - - DDAudioLRC *lrc = [DDAudioLRCParser parserLRCText:text]; - [self performSegueWithIdentifier:@"SegueIdentifier" sender:lrc]; + [self performSegueWithIdentifier:@"SegueIdentifier" sender:path]; }else{ NSString *path = [[NSBundle mainBundle] pathForResource:@"TestLRC2" ofType:@""]; - NSString *text = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; - - DDAudioLRC *lrc = [DDAudioLRCParser parserLRCText:text]; - [self performSegueWithIdentifier:@"SegueIdentifier" sender:lrc]; + [self performSegueWithIdentifier:@"SegueIdentifier" sender:path]; } } @@ -40,7 +33,7 @@ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"SegueIdentifier"]) { DDDetailViewController *vc = segue.destinationViewController; - vc.lrc = sender; + vc.lrcPath = sender; } } diff --git a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h index 4ef4dff..746fa76 100644 --- a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h +++ b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.h @@ -6,15 +6,37 @@ // Copyright © 2016年 Bo Wang. All rights reserved. // + #import + NS_ASSUME_NONNULL_BEGIN @class DDAudioLRC; @class DDAudioLRCUnit; +@protocol DDAudioLRCParserDelegate + +@optional +/** + 构造完成 + @param AudioLRC + */ +- (void)parserDidFinishWithLRC:( DDAudioLRC * _Nullable)AudioLRC; + +- (void)parserDidFailWithError:(NSError *)err; + +@end + + @interface DDAudioLRCParser : NSObject -+ (nullable DDAudioLRC *)parserLRCText:(NSString *)lrc; + +- (void)parserLRCTextAtFilePath:(NSString *)lrcPath WithDelegate:(id)delegate; + +@property (nonatomic,strong,nullable) DDAudioLRC *AudioLRC; +@property (nonatomic,weak,nullable) id delegate; + + @end FOUNDATION_EXTERN const NSString *kDDLRCMetadataKeyTI;//歌曲名 diff --git a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m index e623cf6..d44832e 100644 --- a/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m +++ b/LRCParserDemo/LRCParserDemo/LRCParser/DDAudioLRCParser.m @@ -7,22 +7,32 @@ // #import "DDAudioLRCParser.h" +#import "ZXCommonTool.h" + @implementation DDAudioLRCParser -+ (DDAudioLRC *)parserLRCText:(NSString *)lrc + +- (void)parserLRCTextAtFilePath:(NSString *)lrcPath WithDelegate:(id)delegate; { - return [self parser:lrc]; + self.delegate = delegate; + [self performSelectorInBackground:@selector(parserInBackgroundAtFilePath:) withObject:lrcPath]; } -+ (DDAudioLRC *)parser:(NSString *)lrc + +- (void)parserInBackgroundAtFilePath:(NSString *)lrcPath { - if (!lrc || lrc.length == 0) { - return nil; + if ([ZXCommonTool zx_strIsEmpty:lrcPath]) { + [self deliverFailDelegateWithCode:-1]; + return; + } + NSString * lrc = [NSString stringWithContentsOfFile:lrcPath encoding:NSUTF8StringEncoding error:nil]; + if ([ZXCommonTool zx_strIsEmpty:lrc]) { + [self deliverFailDelegateWithCode:-2]; + return; } DDAudioLRC *tmp = [DDAudioLRC new]; - NSArray *tags = @[kDDLRCMetadataKeyTI, kDDLRCMetadataKeyAR, kDDLRCMetadataKeyAL, @@ -30,7 +40,6 @@ + (DDAudioLRC *)parser:(NSString *)lrc kDDLRCMetadataKeyOFFSET, kDDLRCMetadataKeyTIME ]; - NSString * reg = @"(\\[\\d{0,2}:\\d{0,2}([.|:]\\d{0,2})?\\])"; NSRegularExpression * eachTimeReg = [NSRegularExpression regularExpressionWithPattern:reg options:NSRegularExpressionCaseInsensitive error:nil]; @@ -44,7 +53,6 @@ + (DDAudioLRC *)parser:(NSString *)lrc NSArray *matches; NSString *modifyString; - for (NSString *aLine in lines) { if (aLine.length <= 1) { continue; @@ -76,27 +84,37 @@ + (DDAudioLRC *)parser:(NSString *)lrc /**< 歌词*/ modifyString = [allTimeReg stringByReplacingMatchesInString:aLine options:0 range:NSMakeRange(0, aLine.length) withTemplate:@""]; - for (NSTextCheckingResult *result in matches) { + for (int i = 0; i *)sortedLRCUnits:(NSArray *)units + +- (NSArray *)sortedLRCUnits:(NSArray *)units { //按时间排序 NSArray *sorted = [units sortedArrayUsingComparator:^NSComparisonResult(DDAudioLRCUnit *obj1, DDAudioLRCUnit *obj2) { @@ -121,6 +139,47 @@ + (DDAudioLRC *)parser:(NSString *)lrc return sorted; } + +#pragma mark - deal delegate + +- (NSError *)errWithCode:(NSInteger)code{ + + NSError * err = [NSError errorWithDomain:NSCocoaErrorDomain code:code userInfo:@{@"message":[NSString stringWithFormat:@"error code %ld",(long)code]}]; + return err; +} + +- (void)deliverFailDelegateWithCode:(NSInteger)code{ + if (self.delegate && [self.delegate respondsToSelector:@selector(parserDidFailWithError:)]) { + + __weak __typeof(self) weakself = self; + void (^ block)(void) = ^(void){ + NSError * err = [self errWithCode:code]; + [weakself.delegate parserDidFailWithError:err]; + }; + [self safeExeBlock:block]; + } +} + +- (void)deliverFinishDelegateWithLrc:(DDAudioLRC *)alrc{ + if (self.delegate && [self.delegate respondsToSelector:@selector(parserDidFinishWithLRC:)]) { + + __weak __typeof(self) weakself = self; + void (^ block)(void) = ^(void){ + [weakself.delegate parserDidFinishWithLRC:alrc]; + }; + [self safeExeBlock:block]; + } +} + +- (void)safeExeBlock:(dispatch_block_t)block{ + + if ([NSThread isMainThread]) { + block(); + }else{ + [[NSOperationQueue mainQueue] addOperationWithBlock:block]; + } +} + @end NSString *kDDLRCMetadataKeyTI = @"ti"; diff --git a/LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.h b/LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.h new file mode 100644 index 0000000..f8b6723 --- /dev/null +++ b/LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.h @@ -0,0 +1,48 @@ +// +// ZXCommonTool.h +// yuyou +// +// Created by ganyanchao on 7/27/16. +// Copyright © 2016 Zhang Xiu Inc. All rights reserved. +// + +#import + +@interface ZXCommonTool : NSObject + + ++ (BOOL)zx_strIsEmpty:(NSString *)str; + ++ (BOOL)zx_arrayIsEmpty:(NSArray *)array; + ++ (BOOL)zx_dicIsEmpty:(NSDictionary *)dic; + + ++ (NSString *)replayPlaybackTimeFormatterWith:(long long)seconds; + +/** + * 安全取 str + * + * @param str 传入的str + * + * @return str 本身 或者 @"" + */ ++ (NSString *)safeOfString:(NSString *)str; + + +/** + * 设备型号 + * + * @return + */ ++(NSString *)deviceModel; + + +/** + * 设备code + * + * @return iphone5,5 + */ ++(NSString *)deviceCode; + +@end diff --git a/LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.m b/LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.m new file mode 100644 index 0000000..7d8f305 --- /dev/null +++ b/LRCParserDemo/LRCParserDemo/LRCParser/ZXCommonTool.m @@ -0,0 +1,130 @@ +// +// ZXCommonTool.m +// yuyou +// +// Created by ganyanchao on 7/27/16. +// Copyright © 2016 Zhang Xiu Inc. All rights reserved. +// + +#import "ZXCommonTool.h" +#import "sys/utsname.h" + + +@implementation ZXCommonTool + ++ (BOOL)zx_strIsEmpty:(NSString *)str{ + + return !(str && [str isKindOfClass:[NSString class]] && str.length &&![str isEqual:[NSNull null]]); +} + ++ (BOOL)zx_arrayIsEmpty:(NSArray *)array{ + + return !(array && [array isKindOfClass:[NSArray class]] && array.count && ![array isEqual:[NSNull null]]); +} + + ++ (BOOL)zx_dicIsEmpty:(NSDictionary *)dic{ + + return !(dic && [dic isKindOfClass:[NSDictionary class]] && dic.count && ![dic isEqual:[NSNull null]]); +} + ++ (NSString *)replayPlaybackTimeFormatterWith:(long long)msseconds{ + + long long seconds = ceil(msseconds / 1000); // ms - s + + long min = seconds / 60; + long sec = seconds % 60; + NSString * result = [NSString stringWithFormat:@"%ld:%02ld",min,sec]; + return result; +} + + ++ (NSString *)safeOfString:(NSString *)str{ + + if ([self zx_strIsEmpty:str]) { + return @""; + } + return str; +} + + + ++(NSString *)deviceModel{ + + struct utsname systemInfo; + uname(&systemInfo); + NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + + static NSDictionary * mapping; + if (!mapping) { + mapping = @{ + //iPhone + @"iPhone1,1":@"iPhone 1G", + @"iPhone1,2":@"iPhone 3G", + @"iPhone2,1":@"iPhone 3GS", + @"iPhone3,1":@"iPhone 4", + @"iPhone3,2":@"Verizon iPhone 4", + @"iPhone4,1":@"iPhone 4S", + @"iPhone5,1":@"iPhone 5", + @"iPhone5,2":@"iPhone 5", + @"iPhone5,3":@"iPhone 5C", + @"iPhone5,4":@"iPhone 5C", + @"iPhone6,1":@"iPhone 5S", + @"iPhone6,2":@"iPhone 5S", + @"iPhone7,1":@"iPhone 6 Plus", + @"iPhone7,2":@"iPhone 6", + @"iPhone8,1":@"iPhone 6s", + @"iPhone8,2":@"iPhone 6s Plus", + //iPod + @"iPod1,1":@"iPod Touch 1G", + @"iPod2,1":@"iPod Touch 2G", + @"iPod3,1":@"iPod Touch 3G", + @"iPod4,1":@"iPod Touch 4G", + @"iPod5,1":@"iPod Touch 5G", + //iPad + @"iPad1,1":@"iPad", + @"iPad2,1":@"iPad 2 (WiFi)", + @"iPad2,2":@"iPad 2 (GSM)", + @"iPad2,3":@"iPad 2 (CDMA)", + @"iPad2,4":@"iPad 2 (32nm)", + @"iPad2,5":@"iPad mini (WiFi)", + @"iPad2,6":@"iPad mini (GSM)", + @"iPad2,7":@"iPad mini (CDMA)", + @"iPad4,4":@"iPad mini 2", + @"iPad4,5":@"iPad mini 2", + @"iPad4,6":@"iPad mini 2", + @"iPad4,7":@"iPad mini 3", + @"iPad4,8":@"iPad mini 3", + @"iPad4,9":@"iPad mini 3", + @"iPad3,1":@"iPad 3(WiFi)", + @"iPad3,2":@"iPad 3(CDMA)", + @"iPad3,3":@"iPad 3(4G)", + @"iPad3,4":@"iPad 4 (WiFi)", + @"iPad3,5":@"iPad 4 (4G)", + @"iPad3,6":@"iPad 4 (CDMA)", + @"iPad4,1":@"iPad Air", + @"iPad4,2":@"iPad Air", + @"iPad4,3":@"iPad Air", + @"iPad5,3":@"iPad Air 2", + @"iPad5,4":@"iPad Air 2", + //模拟器 + @"i386":@"iPhone Simulator", + @"x86_64":@"iPhone Simulator", + }; + } + return mapping[deviceString]?mapping[deviceString]:@"iPhone"; +} + ++(NSString *)deviceCode{ + struct utsname systemInfo; + uname(&systemInfo); + NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + return deviceString; +} + + + + + + +@end diff --git a/LRCParserDemo/LRCParserDemo/TestLRC1 b/LRCParserDemo/LRCParserDemo/TestLRC1 index 78191f1..867c72a 100644 --- a/LRCParserDemo/LRCParserDemo/TestLRC1 +++ b/LRCParserDemo/LRCParserDemo/TestLRC1 @@ -3,8 +3,8 @@ [al:我是歌手第四季 第六期] [t_time:(04:03)] [00:00.00] 李克勤 - 友情岁月(Live) -[00:03.00] (我是歌手第四季 第六期) -[00:06.00] 作词:刘卓辉 +[00:03:00] (我是歌手第四季 第六期) +[00:06] 作词:刘卓辉 [00:09.00] 作曲:陈光荣 [00:12.00] 编曲:Johnny Yim [00:15.00] 原唱:郑伊健 @@ -69,4 +69,4 @@ [03:36.42] 飘泊岁月里 [03:37.95] 风吹过已静下 [03:39.74] 将心意再还谁 -[03:41.76] 让眼泪已带走夜憔悴 \ No newline at end of file +[03:41.76] 让眼泪已带走夜憔悴 diff --git a/README.md b/README.md index eaf7ee5..1e4f27c 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,4 @@ Music LRC Text parser 可以识别标准的音乐LRC歌词格式 提供便利的方法,可以根据时间范围取歌词。 支持LRC中的标签:ti ar al by offset t_time -支持时间标签: mm:ss:ms 和 mm:ss.ms \ No newline at end of file +支持时间标签: mm:ss:ms 和 mm:ss.ms 和 mm:ss 三种时间格式 \ No newline at end of file