Music files are. lrc format, take a song as an example,
[Ti: Hourglass of Memories]
[ar: Deng Zi chess]
[AL:G.E.M.]
[By:]
[offset:0]
[00:02.50] Memories of the hourglass-g.e.m. Deng Zi Qi
[00:04.62] ci: Ting Zhu
[00:05.72] Qu: g.e.m.
[00:15.03] Puzzle piece lost
[00:18.56] Like the indifference of the maple leaf
[00:21.87] The clock on the wall
[00:23.79] silently counting the loneliness
[00:29.3] Coffee Fragrance
[00:33.06] remaining bitter to accompany me
[00:36.68] Missing Heart
[00:39.44] bury my fragility in the middle of the night
[00:44.21] The endless firmament
[00:46.15] Constellations of the sky
[00:47.83] Your light shines through
[00:51.34] Just want to remember this timeless moment
[00:57.34] falling like a meteor
[01:01.34] A splendid capture of the contour
[01:05.78] After this instant
[01:07.60] The world is just a memory hourglass
[01:11.78] falling like a meteor
[01:15.73] Brilliant place lights up the whole starry sky
[01:19.93] Like your story left in my life
[01:23.97] Non-fading wounds
[01:29.56] The lake is waiting for silence
[01:33.03] Waiting for the moon in the sky
[01:36.45] The lonely water
[01:38.67] but dark all night
[01:44.12] mists condensation of the tear light
[01:47.64] evaporated in the corner
[01:51.22] and he ruthlessly
[01:54.09] Forgetting the vortex of my recollection
[01:58.82] The endless firmament
[02:00.58] Constellations of the sky
[02:02.29] Your light
[02:03.61] A flash of the past
[02:05.99] Just want to remember this timeless moment
[02:11.85] falling like a meteor
[02:15.83] A splendid capture of the contour
[02:20.33] After this instant
[02:22.25] The world is just a memory hourglass
[02:26.33] falling like a meteor
[02:30.25] Brilliant place lights up the whole starry sky
[02:34.56] Like your story left in my life
[02:38.5] Non-fading wounds
[02:41.9] At the end of the night
[02:43.9] It's your trick.
[02:45.77] and the silent pain
[02:49.07] Only silence is left after burning
[03:00.74] falling like a meteor
[03:04.96] A splendid capture of the contour
[03:09.36] After this instant
[03:11.1] The world is just a memory hourglass
[03:16.73] Meteor fall
[03:19.35] Brilliant place lights up the whole starry sky
[03:23.58] Like your story left in my life
[03:27.58] Non-fading wounds
AR (artist) artist name, Ti (title) song Name, Al (album) album Name, by () editor (refers to the person who edited the LRC lyrics)
The offset () time compensation value, in milliseconds, with positive values indicating overall advance, negative opposite.
The time format in the lyrics is more agreeable: [00:00.20] etc., 00: minutes, 00: seconds,. 50 for the number of milliseconds,
It is more convenient to turn them into milliseconds at the end of the process.
Ext.: http://www.cr173.com/html/20184_1.html
Recently in an Android phone on the music player, learning a lot of things, such as the use of Fragment,actionbar, and so on, here first introduce the lyrics synchronization implementation problem.
The idea of lyrics synchronization is simple: get the time and lyrics content in the lyrics file LRC , and then play the content within a specified time. It's hard to get the lyrics rolling on the phone screen.
First on:
Chess game lobby Bo Yi Master Futures Edition fishing Talent thousand gun United Hall download
Start with the most basic reading of the lyrics file:
public class Lrchandle {private List mwords = new ArrayList (); Private List mtimelist = new ArrayList (); Processing lyrics file public void Readlrc (String path) {File File = new file (path); try {fileinputstream FileInputStream = new FileInputStream (file); InputStreamReader InputStreamReader = new InputStreamReader (FileInputStream, "utf-8"); BufferedReader BufferedReader = new BufferedReader (InputStreamReader); String s = ""; while ((s = bufferedreader.readline ()) = null) {addtimetolist (s); if (S.indexof ("[AR:")! =-1) | | (S.indexof ("[TI:")!! =-1) | | (S.indexof ("[By:")! =-1)) {s = s.substring (S.indexof (":") + 1, s.indexof ("]")); } else {String SS = s.substring (S.indexof ("["), S.indexof ("]") + 1); s = s.replace (ss, ""); } Mwords.add (s); } bufferedreader.close (); Inputstreamreader.close (); Fileinputstream.close (); } catch (FileNotFoundException e) {e.printstacktrace (); Mwords.add ("No lyrics files, hurry to download"); } catch (IOException e) {e.printstacktrace (); Mwords.add ("No reading to lyrics"); }} public List Getwords () {return mwords; } public List GetTime () {return mtimelist; }//separates the time private int Timehandler (string string) {string = String.Replace (".", ":"); string Timedata[] = String.Split (":");//split out minutes, seconds and convert int minute = Integer.parseint (timedata[0]); int second = Integer.parseint (timedata[1]); int millisecond = Integer.parseint (timedata[2]); Calculates the time of the previous row and the next line converted to milliseconds int currenttime = (minute * + second) * + millisecond * 10; return currenttime; } private void Addtimetolist (String string) {  &Nbsp; Matcher Matcher = Pattern.compile ( "\\[\\d{1,2}:\\d{1,2} ([\\.:]\\d{1,2}) \ \]"). Matcher (String); if (Matcher.find ()) { String str = matcher.group (); Mtimelist.add (New Lrchandle (). Timehandler (Str.substring (1, str.length ()-1)); } }}
The format of the general lyrics file is as follows:
[ar: Artist name]
[Ti: Song name]
[Al: Album Name]
[By: Editor (referring to the person who edited the LRC lyrics)]
[Offset: Time compensation value] whose unit is milliseconds, positive value indicates overall advance, negative opposite. This is for the overall adjustment display speed.
But not necessarily, sometimes there are no previous ar: such identifiers, so we also provide another way of parsing.
The time format in the lyrics file is more uniform: [00:00.50] and so on, 00: minutes, 00. Represents the number of seconds,. 50 represents the number of milliseconds, of course, we finally have to convert them into milliseconds processing is more convenient.
After processing the lyrics file and getting the data we want, we need to think about how to scroll through the lyrics on the phone and synchronize with the time we get.
First, the layout file:
<relativelayout xmlns:android= "Http://schemas.android.com/apk/res/android"
Xmlns:tools= "Http://schemas.android.com/tools"
Android:layout_width= "Match_parent"
android:layout_height= "Match_parent"
Tools:context= ". Mainactivity ">
<button
Android:id= "@+id/button"
Android:layout_width= "60dip"
android:layout_height= "60dip"
android:text= "@string/Stop"/>
<com.example.slidechange.wordview
Android:id= "@+id/text"
Android:layout_width= "Match_parent"
android:layout_height= "Match_parent"
android:layout_below= "@id/button"/>
Wordview is a custom TextView, which inherits from TextView:
public class Wordview extends TextView {
Private List mwordslist = new ArrayList ();
Private Paint Mlosefocuspaint;
Private Paint Monfocusepaint;
private float MX = 0;
private float Mmiddley = 0;
private float MY = 0;
private static final int DY = 50;
private int mindex = 0;
Public Wordview (context context) throws IOException {
Super (context);
Init ();
}
Public Wordview (context context, AttributeSet Attrs) throws IOException {
Super (context, attrs);
Init ();
}
Public Wordview (context context, AttributeSet attrs, int defstyle)
Throws IOException {
Super (context, attrs, Defstyle);
Init ();
}
@Override
protected void OnDraw (canvas canvas) {
Super.ondraw (canvas);
Canvas.drawcolor (Color.Black);
Paint p = mlosefocuspaint;
P.settextalign (Paint.Align.CENTER);
Paint P2 = monfocusepaint;
P2.settextalign (Paint.Align.CENTER);
Canvas.drawtext (Mwordslist.get (Mindex), MX, Mmiddley, p2);
int alphavalue = 25;
float tempy = Mmiddley;
for (int i = mIndex-1; I >= 0; i--) {
Tempy-= DY;
if (Tempy < 0) {
Break
}
P.setcolor (Color.argb (255-alphavalue, 245, 245, 245));
Canvas.drawtext (Mwordslist.get (i), MX, Tempy, p);
Alphavalue + = 25;
}
Alphavalue = 25;
Tempy = Mmiddley;
for (int i = Mindex + 1, len = Mwordslist.size (); i < Len; i++) {
Tempy + = DY;
if (Tempy > MY) {
Break
}
P.setcolor (Color.argb (255-alphavalue, 245, 245, 245));
Canvas.drawtext (Mwordslist.get (i), MX, Tempy, p);
Alphavalue + = 25;
}
mindex++;
}
@Override
protected void onsizechanged (int w, int h, int ow, int oh) {
Super.onsizechanged (W, H, Ow, OH);
MX = w * 0.5f;
MY = h;
Mmiddley = h * 0.3f;
}
@SuppressLint ("Sdcardpath")
private void Init () throws IOException {
Setfocusable (TRUE);
Lrchandle Lrchandler = new Lrchandle ();
LRCHANDLER.READLRC ("/sdcard/accompany me to stray. LRC");
Mwordslist = Lrchandler.getwords ();
Mlosefocuspaint = new Paint ();
Mlosefocuspaint.setantialias (TRUE);
Mlosefocuspaint.settextsize (22);
Mlosefocuspaint.setcolor (Color.White);
Mlosefocuspaint.settypeface (Typeface.serif);
Monfocusepaint = new Paint ();
Monfocusepaint.setantialias (TRUE);
Monfocusepaint.setcolor (Color.yellow);
Monfocusepaint.settextsize (30);
Monfocusepaint.settypeface (Typeface.sans_serif);
}
}
The main thing is to cover TextView's OnDraw () and onsizechanged ().
In OnDraw () we redraw the TextView, which is the key to implement the lyrics scrolling implementation. The idea of the lyrics scrolling is not complicated: moving the lyrics upward, the current lyrics are larger, and the color becomes yellow and highlighted.
We need to set the displacement amount dy = 50. Color and font size can be achieved by setting the paint.
We notice that, in the effect I've achieved, lyrics that are farther away from the current lyrics will become transparent, which can be achieved through P.setcolor (Color.argb (255-alphavalue, 245, 245, 245)).
Then there is the main code:
public class Mainactivity extends Activity {
Private Wordview Mwordview;
Private List mtimelist;
Private MediaPlayer MPlayer;
@SuppressLint ("Sdcardpath")
@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Button button = (button) Findviewbyid (R.id.button);
Button.setonclicklistener (New Onclicklistener () {
@Override
public void OnClick (View v) {
Mplayer.stop ();
Finish ();
}
});
Mwordview = (Wordview) Findviewbyid (R.id.text);
MPlayer = new MediaPlayer ();
Mplayer.reset ();
Lrchandle Lrchandler = new Lrchandle ();
try {
LRCHANDLER.READLRC ("/sdcard/accompany me to stray. LRC");
Mtimelist = Lrchandler.gettime ();
Mplayer.setdatasource ("/sdcard/accompany me to stray. mp3");
Mplayer.prepare ();
} catch (IOException e) {
E.printstacktrace ();
} catch (IllegalArgumentException e) {
E.printstacktrace ();
} catch (SecurityException e) {
E.printstacktrace ();
} catch (IllegalStateException e) {
E.printstacktrace ();
}
Final Handler Handler = new Handler ();
Mplayer.start ();
New Thread (New Runnable () {
int i = 0;
@Override
public void Run () {
while (Mplayer.isplaying ()) {
Handler.post (New Runnable () {
@Override
public void Run () {
Mwordview.invalidate ();
}
});
try {
Thread.Sleep (Mtimelist.get (i + 1)-mtimelist.get (i));
} catch (Interruptedexception e) {
}
i++;
if (i = = Mtimelist.size ()-1) {
Mplayer.stop ();
Break
}
}
}
}). Start ();
}
}
The lyrics display requires a thread to be reopened because the main thread is playing the song.
The code is very simple, the function is very simple, the most important thing is to try a lot of changes, you can understand the principle of the code.
Lyrics sync issues in Android music player