lrc格式:
[al:这首歌所在的唱片集]
[ar:歌词作者]
[by:本LRC文件的创建者]
[offset:+/- 以毫秒为单位整体时间戳调整,+增加,-减小]
[re:创建此LRC文件的播放器或编辑器]
[ti:歌词(歌曲)的标题]
[ve:程序的版本]
时间标记的格式为[mm:ss.xx]其中mm为分钟数,ss为秒数并且xx为百分之一秒
例子:
[ti:爱]
[ar:小虎队]
[al:华纳国语情浓13首]
[by:爱上你了音乐网]
百度百科关于lrc的解释:
/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 时的歌词都是“天正在等烟雨”。
代码实现,歌词类
packagecom.android.music;
importjava.io.BufferedInputStream;
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.util.Collections;
parator;
importjava.util.Vector;
importandroid.util.Log;
publicclassLRCUtils{
privatestaticfinalStringTAG="LRCUtils";
MediaPlayActivitymediaPlay;
privatestaticVectorlrclist;
privatebooleanIsLyricExist=false;
privateintlastLine=0;
publicLRCUtils(MediaPlayActivitymediaPlayActivity){
mediaPlay=mediaPlayActivity;
}
publicvoidRefreshLRC(intcurrent)
{
if(IsLyricExist){
for(inti=0;i
{
if(current
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());
}
}
}
}
publicvoidReadLRC(Filef)
{
try
{
if(!f.exists())
{
Log.d(TAG,"notexitthelrcfile");
IsLyricExist=false;
//strLRC=main.getResources().getString(R.string.lrcservice_no_lyric_found);
}
else
{
lrclist=newVector();
IsLyricExist=true;
InputStreamis=newBufferedInputStream(newFileInputStream(f));
BufferedReaderbr=newBufferedReader(newInputStreamReader(is,GetCharset(f)));
StringstrTemp="";
while((strTemp=br.readLine())!=null)
{
//Log.d(TAG,"strTemp="+strTemp);
strTemp=AnalyzeLRC(strTemp);//???з???LRC
}
br.close();
is.close();
Collections.sort(lrclist,newSort());
for(inti=0;i
Log.d(TAG,"time="+lrclist.get(i).getTimePoint()+"string="+lrclist.get(i).getLrcString());
}
}
}
catch(Exceptione)
{
e.printStackTrace();
}
}
privateStringAnalyzeLRC(StringLRCText)
{
try
{
intpos1=LRCText.indexOf("[");//????????????
intpos2=LRCText.indexOf("]");//????????????
//????????????????????λ?????????[????
if(pos1==0&&pos2!=-1)
{//???
Longtime[]=newLong[GetPossiblyTagCount(LRCText)];
time[0]=TimeToLong(LRCText.substring(pos1+1,pos2));//???????ε????
if(time[0]==-1)//??????????
return"";//LRCText
StringstrLineRemaining=LRCText;
inti=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++;
}
}
timelrctl=newtimelrc();
for(intj=0;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=newtimelrc();
//map.put(time[j],strLineRemaining);
//lstTimeStamp.add(time[j]);
}
}
returnstrLineRemaining;
}
else
return"";
}
catch(Exceptione)
{
return"";
}
}
privateintGetPossiblyTagCount(StringLine)
{
StringstrCount1[]=Line.split("//[");
StringstrCount2[]=Line.split("//]");
if(strCount1.length==0&&strCount2.length==0)
return1;
elseif(strCount1.length>strCount2.length)
returnstrCount1.length;
else
returnstrCount2.length;
}
publiclongTimeToLong(StringTime)
{
try
{
String[]s1=Time.split(":");
intmin=Integer.parseInt(s1[0]);
String[]s2=s1[1].split("//.");
intsec=Integer.parseInt(s2[0]);
intmill=0;
if(s2.length>1)
mill=Integer.parseInt(s2[1]);
returnmin*60*1000+sec*1000+mill*10;
}
catch(Exceptione)
{
return-1;
}
}
publicStringGetCharset(Filefile){
Stringcharset="GBK";
byte[]first3Bytes=newbyte[3];
try
{
booleanchecked=false;
BufferedInputStreambis=newBufferedInputStream(newFileInputStream(file));
bis.mark(0);
intread=bis.read(first3Bytes,0,3);
if(read==-1)
returncharset;
if(first3Bytes[0]==(byte)0xFF&&first3Bytes[1]==(byte)0xFE)
{
charset="UTF-16LE";
checked=true;
}
elseif(first3Bytes[0]==(byte)0xFE&&first3Bytes[1]==(byte)0xFF)
{
charset="UTF-16BE";
checked=true;
}
elseif(first3Bytes[0]==(byte)0xEF&&first3Bytes[1]==(byte)0xBB&&first3Bytes[2]==(byte)0xBF)
{
charset="UTF-8";
checked=true;
}
bis.reset();
if(!checked)
{
intloc=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;
}
elseif(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(Exceptione)
{
e.printStackTrace();
}
returncharset;
}
privateclassSortimplementsComparator{
publicSort(){
}
publicintcompare(timelrctl1,timelrctl2){
returnsortUp(tl1,tl2);
}
privateintsortUp(timelrctl1,timelrctl2){
if(tl1.getTimePoint()
return-1;
elseif(tl1.getTimePoint()>tl2.getTimePoint())
return1;
else
return0;
}
}
publicstaticclasstimelrc{
privateStringlrcString;
privateintsleepTime;
privateinttimePoint;
timelrc(){
lrcString=null;
sleepTime=0;
timePoint=0;
}
publicvoidsetLrcString(Stringlrc){
lrcString=lrc;
}
publicvoidsetSleepTime(inttime){
sleepTime=time;
}
publicvoidsetTimePoint(inttPoint){
timePoint=tPoint;
}
publicStringgetLrcString(){
returnlrcString;
}
publicintgetSleepTime(){
returnsleepTime;
}
publicintgetTimePoint(){
returntimePoint;
}
};
}
实现思路:
定义一个类,timelrc,用来存放每一句歌词的内容和时间,每当播放的歌曲的时间改变时,即显示播放的seekbar改变时,刷新歌词RefreshLRC(int),并将取得的歌词的getLrcString()显示到应用程序中。
使用方法:
在音乐播放的activity界面,获取当前播放歌曲的path,歌词路径。
privatevoidgetLrcPath(Stringpath){
Log.d(TAG,"path="+path);
if(path!=null){
path=path.substring(0,path.lastIndexOf(".")).concat(".lrc");
Filefile=newFile(path);
lrcService.ReadLRC(file);
}
}
通过该函数的调用,如上类会将歌词存储起来。
当播放时间改变时,调用lrcService.RefreshLRC(current); 刷新
在播放界面显示正在播放的歌词内容
public void setLRCText(String lrcString,boolean changeLine) {
if(changeLine){
flipperLrc.showNext();
}
playlrcText.setText(lrcString);
}
(未完待续。。。)