lrc格式 :

[al:这首歌所在的唱片集 ]
[ar:歌词作者 ]
[by:本LRC文件的创建者 ]
[offset:+/- 以毫秒为单位整体时间戳调整,+增加,-减小 ]
[re:创建此LRC文件的播放器或编辑器 ]
[ti:歌词(歌曲)的标题 ]
[ve:程序的版本 ]

时间标记的格式为[mm:ss.xx] 其中mm 为分钟数,ss 为秒数并且xx 为百分之一秒

例子:

[ti:爱]

[ar:小虎队]

[al:华纳国语情浓13首]

[by:爱上你了音乐网]

百度百科关于lrc的解释:

http://baike.baidu.com/view/80650.htm

[ti:青花瓷]
[ar:周杰伦]
[al:我很忙]
[by:张琪]
[00:00.00]发送短信18到291199下载该歌曲到手机
[00:01.11]青花瓷
[03:36.49]
[00:21.39]素眉勾勒秋千话北风龙转丹 
[00:26.08]屏层鸟绘的牡丹一如你梳妆
[00:30.46]黯然腾香透过窗心事我了然 
[00:34.93]宣纸上皱边直尺各一半
[00:39.49]油色渲染侍女图因为被失藏 
[00:43.83]而你嫣然的一笑如含苞待放
[00:48.30]你的美一缕飘散 
[00:50.77]去到我去不了的地方
[02:23.97][00:55.77]
[03:01.92][02:25.63][00:56.90]天正在等烟雨 
[03:03.57][02:27.91][00:58.99]而我在等你 
[03:05.92][02:30.44][01:00.93]炊烟袅袅升起 
[03:07.76][02:32.25][01:03.49]隔江千万里
[03:10.36][02:34.85][01:05.84]在平地书刻你房间上的飘影 
[03:14.67][02:38.73][01:09.87]就当我为遇见你伏笔
[03:18.83][02:43.35][01:14.34]天正在等烟雨 
[03:21.20][02:45.60][01:16.68]而我在等你 
[03:23.71][02:48.01][01:18.99]月色被打捞起 
[03:25.74][02:50.10][01:21.18]掩盖了结局
[03:28.33][02:52.54][01:23.72]如传世的青花瓷在独自美丽 
[03:32.30][02:56.67][01:27.65]你眼的笑意
[01:50.25]色白花青的景已跃然于碗底 
[01:54.69]临摹宋体落款时却惦记着你
[01:59.22]你隐藏在药效里一千年的秘密 
[02:03.75]急溪里犹如羞花沾落地
[02:08.32]林外芭蕉 惹咒语 
[02:10.57]梦幻的铜绿
[02:12.84]而我路过那江南小镇的等你
[02:17.19]在泼墨山水画里 
[02:19.75]你从墨色深处被隐去

前面“[ ]”中的数字表示其后歌词的开始时间。例如,“[01:50.25]色白花青的景已跃然于碗底”表示在1分50.25秒时,歌词内容是“色白花青的景已跃 然于碗底”。
还有一种形式是“[03:01.92][02:25.63][00:56.90]天正在等烟雨”这种形式常用于赋格部分(俗称:歌曲的高潮部分),它表示 在 03:01.92, 02:25.63, 00:56.90 时的歌词都是“天正在等烟雨”。

代码实现,歌词类

package com.android.music; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Collections; import java.util.Comparator; import java.util.Vector; import android.util.Log; public class LRCUtils { private static final String TAG = "LRCUtils"; MediaPlayActivity mediaPlay; private static Vector<timelrc> lrclist; private boolean IsLyricExist = false; private int lastLine = 0; public LRCUtils(MediaPlayActivity mediaPlayActivity) { mediaPlay = mediaPlayActivity; } public void RefreshLRC(int current) { if (IsLyricExist){ for(int i = 0; i < lrclist.size(); i++) { if(current < lrclist.get(i).getTimePoint()) if(i == 0 || current >= lrclist.get(i-1).getTimePoint()) { Log.d(TAG,"string = "+lrclist.get(i-1).getLrcString()); mediaPlay.setLRCText(lrclist.get(i-1).getLrcString(),lastLine!=(i-1)); lastLine = i-1; // playlrcText.setText(lrclist.get(i-1).getLrcString()); } } } } public void ReadLRC(File f) { try { if (!f.exists()) { Log.d(TAG,"not exit the lrc file"); IsLyricExist = false; // strLRC = main.getResources().getString(R.string.lrcservice_no_lyric_found); } else { lrclist = new Vector<timelrc>(); IsLyricExist = true; InputStream is = new BufferedInputStream(new FileInputStream(f)); BufferedReader br = new BufferedReader(new InputStreamReader(is, GetCharset(f))); String strTemp = ""; while ((strTemp = br.readLine()) != null) { // Log.d(TAG,"strTemp = "+strTemp); strTemp = AnalyzeLRC(strTemp); // ���з��� LRC } br.close(); is.close(); Collections.sort(lrclist, new Sort()); for(int i=0;i<lrclist.size();i++){ Log.d(TAG,"time = "+lrclist.get(i).getTimePoint()+" string = "+lrclist.get(i).getLrcString()); } } } catch (Exception e) { e.printStackTrace(); } } private String AnalyzeLRC(String LRCText) { try { int pos1 = LRCText.indexOf("["); // ��һ����ǿ�ʼ�� int pos2 = LRCText.indexOf("]"); // ��һ����ǽ���� // ������ǰ���Ƿ���ȷ����һλӦΪ��ǿ�ͷ��[���� if (pos1 == 0 && pos2 != -1) {// ��ȷ Long time[] = new Long[GetPossiblyTagCount(LRCText)]; time[0] = TimeToLong(LRCText.substring(pos1 + 1, pos2)); // ��¼��һ�ε�ʱ�� if (time[0] == -1) // ����ȷ��ʱ�� return ""; // LRCText String strLineRemaining = LRCText; int i = 1; while (pos1 == 0 && pos2 != -1) { strLineRemaining = strLineRemaining.substring(pos2 + 1); // ʣ�µ����� pos1 = strLineRemaining.indexOf("["); pos2 = strLineRemaining.indexOf("]"); if (pos2 != -1) { time[i] = TimeToLong(strLineRemaining.substring(pos1 + 1, pos2)); if (time[i] == -1) // ����ȷ��ʱ�� return ""; // LRCText i++; } } timelrc tl = new timelrc(); for (int j = 0; j < time.length; j++) { if (time[j] != null) { // Log.d(TAG,"time["+j+"] = "+time[j].intValue()+" strLineRemaining = "+strLineRemaining); tl.setTimePoint(time[j].intValue()); tl.setLrcString(strLineRemaining); lrclist.add(tl); tl = new timelrc(); // map.put(time[j], strLineRemaining); // lstTimeStamp.add(time[j]); } } return strLineRemaining; } else return ""; } catch (Exception e) { return ""; } } private int GetPossiblyTagCount(String Line) { String strCount1[] = Line.split("//["); String strCount2[] = Line.split("//]"); if (strCount1.length == 0 && strCount2.length == 0) return 1; else if (strCount1.length > strCount2.length) return strCount1.length; else return strCount2.length; } public long TimeToLong(String Time) { try { String[] s1 = Time.split(":"); int min = Integer.parseInt(s1[0]); String[] s2 = s1[1].split("//."); int sec = Integer.parseInt(s2[0]); int mill = 0; if (s2.length > 1) mill = Integer.parseInt(s2[1]); return min * 60 * 1000 + sec * 1000 + mill * 10; } catch (Exception e) { return -1; } } public String GetCharset(File file){ String charset = "GBK"; byte[] first3Bytes = new byte[3]; try { boolean checked = false; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); bis.mark(0); int read = bis.read(first3Bytes, 0, 3); if (read == -1) return charset; if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) { charset = "UTF-16LE"; checked = true; } else if (first3Bytes[0] == (byte) 0xFE && first3Bytes[1] == (byte) 0xFF) { charset = "UTF-16BE"; checked = true; } else if (first3Bytes[0] == (byte) 0xEF && first3Bytes[1] == (byte) 0xBB && first3Bytes[2] == (byte) 0xBF) { charset = "UTF-8"; checked = true; } bis.reset(); if (!checked) { int loc = 0; while ((read = bis.read()) != -1) { loc++; if (read >= 0xF0) break; if (0x80 <= read && read <= 0xBF) // ��������BF���µģ�Ҳ����GBK break; if (0xC0 <= read && read <= 0xDF) { read = bis.read(); if (0x80 <= read && read <= 0xBF) // ˫�ֽ�(0xC0-0xDF),(0x80-xBF)Ҳ������GB������ continue; else break; } else if (0xE0 <= read && read <= 0xEF) {// Ҳ�п��ܳ��?���Ǽ��ʽ�С read = bis.read(); if (0x80 <= read && read <= 0xBF) { read = bis.read(); if (0x80 <= read && read <= 0xBF) { charset = "UTF-8"; break; } else break; } else break; } } } bis.close(); } catch (Exception e) { e.printStackTrace(); } return charset; } private class Sort implements Comparator<timelrc> { public Sort() { } public int compare(timelrc tl1, timelrc tl2) { return sortUp(tl1, tl2); } private int sortUp(timelrc tl1, timelrc tl2) { if (tl1.getTimePoint() < tl2.getTimePoint()) return -1; else if (tl1.getTimePoint() > tl2.getTimePoint()) return 1; else return 0; } } public static class timelrc { private String lrcString; private int sleepTime; private int timePoint; timelrc() { lrcString = null; sleepTime = 0; timePoint = 0; } public void setLrcString(String lrc) { lrcString = lrc; } public void setSleepTime(int time) { sleepTime = time; } public void setTimePoint(int tPoint) { timePoint = tPoint; } public String getLrcString() { return lrcString; } public int getSleepTime() { return sleepTime; } public int getTimePoint() { return timePoint; } }; }

实现思路:

定义一个类,timelrc,用来存放每一句歌词的内容和时间,每当播放的歌曲的时间改变时,即显示播放的seekbar改变时,刷新歌词RefreshLRC(int),并将取得的歌词的getLrcString()显示到应用程序中。

使用方法:

在音乐播放的activity界面,获取当前播放歌曲的path,歌词路径。

private void getLrcPath(String path) { Log.d(TAG,"path = "+path); if (path != null) { path = path.substring(0, path.lastIndexOf(".")).concat(".lrc"); File file = new File(path); lrcService.ReadLRC(file); } }

通过该函数的调用,如上类会将歌词存储起来。

当播放时间改变时,调用lrcService.RefreshLRC(current); 刷新

在播放界面显示正在播放的歌词内容

public void setLRCText(String lrcString,boolean changeLine) {
if(changeLine){
flipperLrc.showNext();
}
playlrcText.setText(lrcString);

}

(未完待续。。。)

android 音乐播放器-------歌词同步 lrc相关推荐

  1. android 本地lrc 歌词同步,android 音乐播放器-------歌词同步 lrc

    lrc格式 : [al:这首歌所在的唱片集 ] [ar:歌词作者 ] [by:本LRC文件的创建者 ] [offset:+/- 以毫秒为单位整体时间戳调整,+增加,-减小 ] [re:创建此LRC文件 ...

  2. javafx音乐播放器----歌词同步实时显示(包含获取酷我歌词方式,歌词同步方法)

    首先我是爬虫获取的酷我的音源,因此歌词也是通过爬虫获取的,下面这个方法可以获取到歌曲对应的歌词信息.简单说下,在搜索歌曲之后会返回一个歌曲列表,查看源代码是包含在li标签里面的,这个li标签里面就有请 ...

  3. android 音乐播放器----歌词在线下载

    本文来自CSDN丹丹博客,转载请必须注明出处: http://blog.csdn.net/dany1202/archive/2011/06/09/6533513.aspx 使用百度的歌词API,如: ...

  4. android音乐播放器之歌词下载、处理、开始、同步

    android音乐播放器之歌词下载.处理.开始.同步 ** 程序源代码在底部 ** 先来看看效果 下载 /*** 自定义下载方法,调用系统DownloadManager下载* * @param myU ...

  5. 乐乐音乐:Android音乐播放器及动感(KTV)歌词相关博客汇总

    相关简介 Java Swing PC版本乐乐音乐播放器 乐乐音乐PC播放器单机版本,支持ape,wav,flac,mp3等多种格式,支持动态ksc.hrc.krc歌词文件和支持和显示翻译歌词和音译歌词 ...

  6. Android音乐播放器源码(歌词.均衡器.收藏.qq5.0菜单.通知)

    一款Android音乐播放器源码,基本功能都实现了 qq5.0菜单(歌词.均衡器.收藏.qq5.0菜单.通知) 只有向右滑动出现,菜单键和指定按钮都还没有添加. 源码下载:http://code.66 ...

  7. android七大主流Android音乐播放器横向评测

    随着智能手机和3G网络的普及,移动互联网日益成为人们生活娱乐的重心之一.在音乐领域,竞争也十分激烈,在PC之后,几大提供音乐服务的厂商正在加紧占据手机客户端. 本期我们在Android平台挑选了七家国 ...

  8. android音乐播放器ppt,基于Android音乐播放器设计与开发.ppt

    基于Android音乐播放器设计与开发 毕业设计 基于Android的音乐播放器 设计与开发 设计概述 研究背景 研究意义 研究目标 系统演示 研究背景 随着Android智能手机的普及,用户越来越能 ...

  9. android版音乐播放器开发教程,Android音乐播放器开发文档(20200907152026).pdf

    Android 音乐播放器 撰写人:张 XX 2011-3-15 一. 问题定义 本软件是为了用户智能手机 Android 而开发的一套智能软件, 提供在线 下载音乐,在线播放音乐,读取 SD 卡音乐 ...

最新文章

  1. NoticeView
  2. 智能车技术与实践_ROS入门
  3. PHP/TP5 接口设计中异常处理
  4. MONO源码编译笔记-版本:unity-2018.4-mbe
  5. leetcode-283-移动零
  6. 关于Hibernate 3
  7. java getmonth_Java LocalDateTime类| 带示例的getMonth()方法
  8. js获取a标签的value值_js逆向 | 某住房网跳转链接生成逻辑分析
  9. 专门为某种用途而设计的计算机 称为,专门为某种用途而设计的计算机,称为计算机...
  10. 802.11介质访问控制——CSMA/CD协议详解
  11. MongoDB vs MySQL,哪个效率更高?
  12. 牛客网-C++剑指offer-第三十二题(把数组排成最小的数)
  13. 获得代理ippython_Python3.x:免费代理ip的批量获取并入库
  14. ora-01045 :user system lacks create session privilege; logon denied
  15. 《创世纪语录》1、只要有梦想,什么都能够实现。3、做得越多机会越多。
  16. head和tail命令--用Enki学Linux系列(8)
  17. 求1!+2!+3!+…+n!(2种方式)
  18. Ubuntu如何安装搜狗输入法
  19. [渗透测试学习靶机03] vulnhub靶场 Empire LupinOne
  20. P15 Collections

热门文章

  1. WebService处理Map
  2. iOS 8下应用中仅有几个页面需要横屏其余均为竖屏的处理办法
  3. 51CTO网站博客改版意见寻求
  4. 数据库表TreeView树的快速生成
  5. Top 5 Agile Project Management Books
  6. python连接mysql的操作
  7. ajax-登陆+验证码
  8. mysql的字段为bit时,插入数据报Data too long
  9. 修改zepto源代码,使支持wp8的ie10
  10. [Vue] Computed property XXX was assigned to but it has no setter.