// LrcParser.h
#import <Foundation/Foundation.h>
@interface LRCParser : NSObject
/** 保存时间的数组 */
@property (nonatomic, strong) NSMutableArray *timeArray;
/** 保存歌词的数组 */
@property (nonatomic, strong) NSMutableArray *wordArray;
/**
* 开始解析歌词
*/
- (void)startParseWithLrc:(NSString *)lrc;
@end
// LrcParser.m
#import "LRCParser.h"
@implementation LRCParser
#pragma mark - 懒加载
- (NSMutableArray *)timeArray {
if (_timeArray == nil) {
_timeArray = [[NSMutableArray alloc] init];
}
return _timeArray;
}
- (NSMutableArray *)wordArray {
if (_wordArray == nil) {
_wordArray = [[NSMutableArray alloc] init];
}
return _wordArray;
}
- (void)startParseWithLrc:(NSString *)lrc {
[self.wordArray removeAllObjects];
[self.timeArray removeAllObjects];
int start;
if ([lrc isEqualToString:@"林俊杰-背对背拥抱.lrc"]) {
start = 1;
} else if ([lrc isEqualToString:@"情非得已.lrc"]) {
start = 3;
} else if ([lrc isEqualToString:@"梁静茹-偶阵雨.lrc"]) {
start = 5;
}
// 获取歌词内容
NSString *content = [self contentFromLrc:lrc];
// 1. 以‘[’进行分割
NSArray *strArray = [content componentsSeparatedByString:@"["];
for (int i = start; i < strArray.count; i++) {
NSString *itemStr = strArray[i];
// 2. 以']'进行分割
NSArray *itmStrArray = [itemStr componentsSeparatedByString:@"]"];
if (itmStrArray.count == 2) {
[self.timeArray addObject:itmStrArray[0]];
[self.wordArray addObject:itmStrArray[1]];
}
}
}
/**
* 返回文件内容 NSString
*/
- (NSString *)contentFromLrc:(NSString *)lrc {
NSString *path = [[NSBundle mainBundle] pathForResource:lrc ofType:nil];
return [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
}
@end
// ViewController.m
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import "LRCParser.h"
@interface ViewController () <UITableViewDataSource,UITableViewDelegate>
#pragma mark - properties
/** 播放按钮 */
@property (weak, nonatomic) IBOutlet UIButton *playBtn;
/** 歌词解析器 */
@property (nonatomic, strong) LRCParser *lrcParser;
/** 用来显示歌词的tableView */
@property (weak, nonatomic) IBOutlet UITableView *tableView;
/** 进度 */
@property (weak, nonatomic) IBOutlet UISlider *slider;
/** 播放器 */
@property (nonatomic, strong)AVAudioPlayer *player;
/** 已播放时长 */
@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
/** 总时长 */
@property (weak, nonatomic) IBOutlet UILabel *allLabel;
/** 当期播放的哪首 */
@property (nonatomic, assign) NSInteger currentIndex;
/** 更新定时器 */
@property (nonatomic, strong) NSTimer *updateTimer;
/** 总时间 */
@property (nonatomic, assign) NSTimeInterval totalSeconds;
/** MP3数组 */
@property (nonatomic, copy) NSArray *musics;
/** 当前歌词显示的行 */
@property (nonatomic, assign) NSInteger tableViewRow;
#pragma mark - methods
/** 播放进度指示条 */
- (IBAction)proSlider:(UISlider *)sender;
/** 上一首 */
- (IBAction)pre:(UIButton *)sender;
/** 播放*/
- (IBAction)play:(UIButton *)sender;
/** 下一首 */
- (IBAction)next:(UIButton *)sender;
@end
@implementation ViewController
#pragma mark - 懒加载
- (NSArray *)musics {
if (_musics == nil) {
_musics = @[@"情非得已.mp3",@"林俊杰-背对背拥抱.mp3",@"梁静茹-偶阵雨.mp3"];
}
return _musics;
}
- (AVAudioPlayer *)player {
if (_player == nil) {
NSURL *url = [self urlWithFileName:self.musics[_currentIndex]];
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
// -1 左声道 0 双声道 1右声道
_player.pan = 0;
// 音量 0.0~1.0
_player.volume = 1;
// -1 表示单曲循环
_player.numberOfLoops = -1;
// 对应的歌词文件
NSMutableString *musicName = [self.musics[_currentIndex] mutableCopy];
[musicName replaceCharactersInRange:NSMakeRange(musicName.length-3, 3) withString:@"lrc"];
[_lrcParser startParseWithLrc:musicName];
[self.tableView reloadData];
// 获取当前音频的总时间
_totalSeconds = _player.duration;
self.allLabel.text = [NSString stringWithFormat:@"%02d:%02d", (int)_totalSeconds / 60, (int)_totalSeconds % 60];
/*
// 当前时间
[_player currentTime];
// 总时间
[_player duration];
// 播放
[_player play];
// 停止
[_player stop];
// 播放
[_player pause];
// 音量
_player.volume;
// 循环次数
_player.numberOfLoops;
*/
}
return _player;
}
- (void)viewDidLoad {
[super viewDidLoad];
_updateTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateTimeAction:) userInfo:nil repeats:YES];
// 歌词解析
_lrcParser = [[LRCParser alloc] init];
// 注册cell
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
/**
* 更新当前显示的歌词 和 时间进度
*/
- (void)updateTimeAction:(NSTimer *)timer {
// 01 获取当前时间
NSTimeInterval currentSecond = self.player.currentTime;
// 02 更新当前时间 00:00
self.timeLabel.text = [NSString stringWithFormat:@"%02d:%02d", (int)currentSecond / 60, (int)currentSecond % 60];
// 03 更新进度
self.slider.value = (float)currentSecond/_totalSeconds;
// 04 根据当前时间获取当前歌词行
_tableViewRow = [self currentIndexPathRowWithCurrentSecond:currentSecond];
// 05 刷新tableView
[self.tableView reloadData];
// 06 滚动到当前行
NSIndexPath *currentIndexPath = [NSIndexPath indexPathForRow:_tableViewRow inSection:0];
[self.tableView scrollToRowAtIndexPath:currentIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
/**
* 获取当前行
*/
- (NSInteger)currentIndexPathRowWithCurrentSecond:(NSTimeInterval)currentSecond {
__block NSInteger row = 0;
// 遍历时间数组
[_lrcParser.timeArray enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL *stop) {
NSArray *timeStrArray = [obj componentsSeparatedByString:@":"];
NSInteger minute = [timeStrArray[0] integerValue];
float second = [timeStrArray[1] floatValue];
NSTimeInterval compareSecond = minute * 60 + second;
// 如果播放器里的当前时间大于 数组中的时间 就赋值
if (currentSecond > compareSecond) {
row = idx;
} else {
*stop = YES;
}
}];
return row;
}
/**
* 根据文件名返回url
*/
- (NSURL *)urlWithFileName:(NSString *)fileName {
return [[NSBundle mainBundle] URLForResource:fileName withExtension:nil];
}
#pragma mark - actions
/**
* 通过控制当前时间来控制进度
*/
- (IBAction)proSlider:(UISlider *)sender {
self.player.currentTime = _totalSeconds * sender.value;
}
/**
* 上一首
*/
- (IBAction)pre:(UIButton *)sender {
if (_currentIndex == 0) {
_currentIndex = self.musics.count-1;
} else {
_currentIndex--;
}
[self stopPlayer];
[self.player prepareToPlay];
}
/**
* 播放和暂停
*/
- (IBAction)play:(UIButton *)sender {
sender.selected = !sender.selected;
if (sender.selected) { // 被点击了 显示暂停 执行播放
[self.player play];
// 启动定时器 如果播放就启动定时器
[_updateTimer setFireDate:[NSDate distantPast]];
} else { // 被点击了 显示播放 执行暂停
[self.player pause];
// 暂停定时器 如果暂停就关闭定时器
[_updateTimer setFireDate:[NSDate distantFuture]];
}
}
/**
* 下一首
*/
- (IBAction)next:(UIButton *)sender {
if (_currentIndex == self.musics.count-1) {
_currentIndex = 0;
} else {
_currentIndex++;
}
[self stopPlayer];
[self.player prepareToPlay];
}
/**
* 如果当前播放器正在播放则停止播放
*/
- (void)stopPlayer {
// 如果当前的播放器正在播放
if ([self.player isPlaying]) {
// 停止播放
[self.player stop];
}
self.player = nil;
self.playBtn.selected = NO;
}
#pragma mark - UITableView 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.lrcParser.timeArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.textLabel.textAlignment = NSTextAlignmentCenter;
cell.textLabel.font = [UIFont systemFontOfSize:15.0f];
cell.textLabel.text = [self.lrcParser.wordArray objectAtIndex:indexPath.row];
cell.textLabel.textColor = [UIColor blackColor];
if (indexPath.row == _tableViewRow) {
cell.textLabel.textColor = [UIColor redColor];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
@end