卡拉OK歌詞原理和實現高仿Android網易雲音樂

你們好,咱們是愛學啊,繼上一篇講解了【LRC歌詞原理和實現高仿Android網易雲音樂】,今天給你們帶來一篇關於卡拉OK歌詞原理和在Android上如何實現歌詞逐字滾動的效果,本文來自【Android開發項目實戰個人云音樂】課程。java

效果圖

相信你們都懂一張圖賽過千言萬語。canvas

圖片描述

效果和如今市面上大部分播放器差很少,固然若是要運用到商業項目中,確定還須要進行一些優化,例如:滾動效果有彈性,字體大小,字體顏色等。架構

什麼是卡拉OK歌詞

要明白什麼是卡拉OK歌詞,就先要搞明白什麼是卡拉OK,簡單來說就是卡拉OK是一種伴奏系統,演唱者能夠在預先錄製的音樂伴奏下參與唱歌,現多叫KTV(Karaoke);卡拉OK歌詞默認格式爲ksc,固然如今市面上的一些軟件在他的基礎上作了定製,具體的在咱們的課程中講解了;咱們這裏就講解ksc,由於卡拉OK歌詞的核心就是精確到每個字,因此搞明白他的原理,咱們也就能夠在他的基礎上定製了。學習

LRC歌詞格式

在實現歌詞功能前,確定須要搞明白ksc歌詞格式,例如:咱們找了一段LRC歌詞:字體

karaoke := CreateKaraokeObject;
karaoke.rows := 2;
karaoke.TimeAfterAnimate := 2000;
karaoke.TimeBeforeAnimate := 4000;
karaoke.clear;
karaoke.add('00:20.699', '00:27.055', '[●●●●●●]', '7356',RGB(255,0,0));

karaoke.add('00:27.487', '00:32.068', '一時失志難免怨嘆', '347,373,1077,320,344,386,638,1096');
karaoke.add('00:33.221', '00:38.068', '一時落魄難免膽寒', '282,362,1118,296,317,395,718,1359');
karaoke.add('00:38.914', '00:42.164', '那通失去但願', '290,373,348,403,689,1147');
karaoke.add('00:42.485', '00:44.530', '每日醉茫茫', '298,346,366,352,683');
karaoke.add('00:45.273', '00:49.029', '無魂有體親像稻草人', '317,364,380,351,326,351,356,389,922');
karaoke.add('00:50.281', '00:55.585', '人生可比是海上的波浪', '628,1081,376,326,406,371,375,1045,378,318');
karaoke.add('00:56.007', '01:00.934', '有時起有時落', '303,362,1416,658,750,1438');
karaoke.add('01:02.020', '01:04.581', '好運歹運', '360,1081,360,760');
karaoke.add('01:05.283', '01:09.453', '總嘛要照起來行', '303,338,354,373,710,706,1386');
karaoke.add('01:10.979', '01:13.029', '三分天註定', '304,365,353,338,690');
karaoke.add('01:13.790', '01:15.950', '七分靠打拼', '356,337,338,421,708');
karaoke.add('01:16.339', '01:20.870', '愛拼纔會贏', '325,1407,709,660,1430');

能夠看到內容是用換行符分割的,若是這些數據是經過接口返回,而不是直接返回一個文件,那麼這裏面的換行符應該變爲n換行符,這一點咱們也在課程中講解到了。優化

每一行是一句歌詞;每一行歌詞又分爲四部分:spa

第一部分:這一行開始時間
第二部分:這一行結束時間
第三部分:這一句歌詞
第四部分:每一個字持續的毫秒

其中頂部的一些信息是元數據:不一樣的播放器可能實現不同。rest

查看上面的歌詞,咱們能夠發現有大部分的重複內容,因此能夠定製。code

歌詞滾動原理

將每行歌詞前面的時間解析後,轉爲毫秒,這樣播放器在播放的時候能夠獲取到播放時間,而後拿着時間查找當前時間對應哪一行歌詞,而後在查看當前時間對應該行的哪個字,而後進行相應的繪製,具體的在能夠有講解。接口

歌詞解析

歌詞解析就很簡單了,就是字符串拆分,因此就不貼代碼了;但但願你們在寫代碼的時候不要只侷限於功能,也要注重架構;歌詞有不少種,因此能夠搞成用不一樣的類來解析,對外暴露統一的接口;這部分在課程中有講解。

歌詞繪製

不一樣的平臺也不同,咱們這裏是Android,因此繪製用Canvas。咱們這裏的思路是:歌詞View的高度是固定的,因爲咱們但願當前行歌詞始終顯示到歌詞View中間,因此先算出View的中心高度,而後在該位置繪製當前行歌詞,這一步根據不一樣的歌詞處理的邏輯也不同,但歌詞可分爲兩類,一類是逐行,一類是逐字,對於逐行來講就直接繪製就好了,只是顏色,大小不同而已;逐字下一節講解;而後從當前行歌詞位置像前繪製歌詞,直到超出View頂部爲止,在從當前行歌詞向下歌詞繪製,直到超出View底部爲止;當前你可使用LinearLayout添加全部歌詞當前容器內,而後滾動。

相對於LRC歌詞,只須要添加ksc格式格式時繪製:

if (lyric.isAccurate()) {
    //精確到字歌詞,格式能夠有不少種
    //只是解析的時候不同,但都組成成通用的model
    //因此在歌詞View中,咱們已經不須要知道是ksc,仍是QQ歌詞,仍是酷狗歌詞等。
    canvas.drawText(line.getLineLyrics(), x, y, backgroundTextPaint);

    if (lyricCurrentWordIndex == -1) {
        //該行已經播放完了
        lineLyricPlayedWidth = textWidth;
    } else {
        String[] lyricsWord = line.getLyricsWord();
        int[] wordDuration = line.getWordDuration();

        //獲取當前時間前面的文字
        String beforeText = line.getLineLyrics().substring(0, lyricCurrentWordIndex);
        float beforeTextWidth = getTextWidth(foregroundTextPaint, beforeText);

        //當前字
        String currentWord = lyricsWord[lyricCurrentWordIndex];
        float currentWordTextWidth = getTextWidth(foregroundTextPaint, currentWord);

        //當前字已經演唱的寬度
        float currentWordWidth = currentWordTextWidth / wordDuration[lyricCurrentWordIndex] * wordPlayedTime;

        lineLyricPlayedWidth = beforeTextWidth + currentWordWidth;
    }

    canvas.save();
    //裁剪一個矩形用來繪製已經唱的歌詞
    canvas.clipRect(x, y - textHeight, x + lineLyricPlayedWidth,
            y + textHeight);


    //這個矩形包是文字的高度+行高
    //canvas.drawRect(x, y - textHeight, x + lineLyricPlayedWidth,
    //        y + textHeight,foregroundTextPaint);

    canvas.drawText(line.getLineLyrics(), x, y, foregroundTextPaint);

    canvas.restore();
} else {
    //精確到行
}

歌詞滾動

歌詞和LRC是同樣的。

到這裏歌詞View核心功能基本就實現完成了,若是要深刻學習能夠查看咱們的【高仿Android網易雲音樂】課程,或者在線電子書【電子書】。

相關文章
相關標籤/搜索