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

龙哲
2023-12-01

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 时的歌词都是“天正在等烟雨”。

代码实现,歌词类

packagecom.android.music;

importjava.io.BufferedInputStream;

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.util.Collections;

importjava.util.Comparator;

importjava.util.Vector;

importandroid.util.Log;

publicclassLRCUtils {

privatestaticfinalString TAG ="LRCUtils";

MediaPlayActivity mediaPlay;

privatestaticVector lrclist;

privatebooleanIsLyricExist =false;

privateintlastLine =0;

publicLRCUtils(MediaPlayActivity mediaPlayActivity) {

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(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 = newVector();

IsLyricExist = true;

InputStream is = newBufferedInputStream(newFileInputStream(f));

BufferedReader br = newBufferedReader(newInputStreamReader(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, newSort());

for(inti=0;i

Log.d(TAG,"time = "+lrclist.get(i).getTimePoint()+"   string = "+lrclist.get(i).getLrcString());

}

}

}

catch(Exception e)

{

e.printStackTrace();

}

}

privateString AnalyzeLRC(String LRCText)

{

try

{

intpos1 = LRCText.indexOf("[");// ????????????

intpos2 = LRCText.indexOf("]");// ????????????

// ????????????????????λ?????????[????

if(pos1 ==0&& pos2 != -1)

{// ???

Long time[] = newLong[GetPossiblyTagCount(LRCText)];

time[0] = TimeToLong(LRCText.substring(pos1 +1, pos2));// ???????ε????

if(time[0] == -1)// ??????????

return"";// LRCText

String strLineRemaining = 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++;

}

}

timelrc tl = 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(Exception e)

{

return"";

}

}

privateintGetPossiblyTagCount(String Line)

{

String strCount1[] = Line.split("//[");

String strCount2[] = Line.split("//]");

if(strCount1.length ==0&& strCount2.length ==0)

return1;

elseif(strCount1.length > strCount2.length)

returnstrCount1.length;

else

returnstrCount2.length;

}

publiclongTimeToLong(String Time)

{

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(Exception e)

{

return-1;

}

}

publicString GetCharset(File file){

String charset = "GBK";

byte[] first3Bytes =newbyte[3];

try

{

booleanchecked =false;

BufferedInputStream bis = 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(Exception e)

{

e.printStackTrace();

}

returncharset;

}

privateclassSortimplementsComparator {

publicSort() {

}

publicintcompare(timelrc tl1, timelrc tl2) {

returnsortUp(tl1, tl2);

}

privateintsortUp(timelrc tl1, timelrc tl2) {

if(tl1.getTimePoint() 

return-1;

elseif(tl1.getTimePoint() > tl2.getTimePoint())

return1;

else

return0;

}

}

publicstaticclasstimelrc {

privateString lrcString;

privateintsleepTime;

privateinttimePoint;

timelrc() {

lrcString = null;

sleepTime = 0;

timePoint = 0;

}

publicvoidsetLrcString(String lrc) {

lrcString = lrc;

}

publicvoidsetSleepTime(inttime) {

sleepTime = time;

}

publicvoidsetTimePoint(inttPoint) {

timePoint = tPoint;

}

publicString getLrcString() {

returnlrcString;

}

publicintgetSleepTime() {

returnsleepTime;

}

publicintgetTimePoint() {

returntimePoint;

}

};

}

实现思路:

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

使用方法:

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

privatevoidgetLrcPath(String path) {

Log.d(TAG,"path = "+path);

if(path !=null) {

path = path.substring(0, path.lastIndexOf(".")).concat(".lrc");

File file = newFile(path);

lrcService.ReadLRC(file);

}

}

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

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

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

public void setLRCText(String lrcString,boolean changeLine) {

if(changeLine){

flipperLrc.showNext();

}

playlrcText.setText(lrcString);

}

(未完待续。。。)

 类似资料: