CODE:
public function LRCPlayer() {
--------------------------------------------------------------------------------
var loader:URLLoader=new URLLoader();
loader.load(new URLRequest("LRC/青花瓷.lrc"));
loader.addEventListener(Event.COMPLETE,LoadFinish);
}
private function LoadFinish(evt:Event):void {
trace(evt.target.data);
}
2.将读取的 LRC 数据按行分割( "\n" 为换行符),数组的每一个元素代表 LRC 的一行内容;
CODE:
function LoadFinish(evt:Event):void {
--------------------------------------------------------------------------------
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
trace(listarray);
}
3.在数组中提取每一行的时间及歌词,解决单时间序列的问题;(注意!此段代码只作讲解,不以应用)
LRC 内容如下:
QUOTE:
[00:43.83]而你嫣然的一笑如含苞待放代码如下:
[00:48.30]你的美一缕飘散
[00:50.77]去到我去不了的地方
[03:01.92]天正在等烟雨
[03:03.57]而我在等你
[03:05.92]炊烟袅袅升起
[03:07.76]隔江千万里
CODE:
function LoadFinish(evt:Event):void {
输出结果:
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
for (var i=0; i<listarray.length; i ) {
var info:String=listarray[i];
//提取每行内容,用变量 info 保存
var lyric:String=info.substr(10);
//将歌词内容提取到 lyric 变量中
var ctime:String =info.substr(0,10);
//提取时间序列字串
var ntime:Number=Number(ctime.substr(1,2))*60 Number(ctime.substr(4,5));
//将时间字串转换为计算机可读取的时间
var obj:Object=new Object();
obj.timer=ntime*1000;
obj.lyric=lyric;
LRCarray.push(obj);
//将时间与歌词保存到一个 Object 中,并压入LRCarray 数组
trace(obj.timer,obj.lyric);
}
}
QUOTE:
43830 而你嫣然的一笑如含苞待放--------------------------------------------------------------------------------
48300 你的美一缕飘散
50770 去到我去不了的地方
181920 天正在等烟雨
183570 而我在等你
185920 炊烟袅袅升起
187760 隔江千万里
QUOTE:
[00:43.83]而你嫣然的一笑如含苞待放代码如下:
[00:48.30]你的美一缕飘散
[00:50.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]隔江千万里
CODE:
function LoadFinish(evt:Event):void {
输出结果:
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
var reg:RegExp=/\[[0-5][0-9]:[0-5][0-9].[0-9][0-9]\]/g;
//建立正则表达式,范围:[00:00.00]~[59:59.99]
for (var i=0; i<listarray.length; i ) {
var info:String=listarray[i];
//提取每行内容,用变量 info 保存
var len:int=info.match(reg).length;
//该行拥有时间序列的个数
var timeAry:Array=info.match(reg);
//将匹配的时间序列保存到 timeAry 数组中
var lyric:String=info.substr(len*10);
//根据每个时间序列占10个字符,找出歌词内容的起点
//将歌词提取到 lyric 变量中
for (var k:int=0; k<timeAry.length; k ) {
var obj:Object=new Object();
var ctime:String=timeAry[k];
var ntime:Number=Number(ctime.substr(1,2))*60 Number(ctime.substr(4,5));
obj.timer=ntime*1000;
obj.lyric=lyric;
LRCarray.push(obj);
trace(obj.timer,obj.lyric);
}
//将时间序列转换为毫秒并与歌词一起保存为一个数组元素
}
}
QUOTE:
43830 而你嫣然的一笑如含苞待放--------------------------------------------------------------------------------
48300 你的美一缕飘散
50770 去到我去不了的地方
181920 天正在等烟雨
145630 天正在等烟雨
56900 天正在等烟雨
183570 而我在等你
147910 而我在等你
58990 而我在等你
185920 炊烟袅袅升起
150440 炊烟袅袅升起
60930 炊烟袅袅升起
187760 隔江千万里
152250 隔江千万里
63490 隔江千万里
CODE:
LRCarray.sort(compare);
结果如下:
private function compare(paraA:Object,paraB:Object):int {
if (paraA.timer>paraB.timer) {
return 1;
}
if (paraA.timer<paraB.timer) {
return -1;
}
return 0;
}
QUOTE:
43830 而你嫣然的一笑如含苞待放--------------------------------------------------------------------------------
48300 你的美一缕飘散
50770 去到我去不了的地方
56900 天正在等烟雨
58990 而我在等你
60930 炊烟袅袅升起
63490 隔江千万里
145630 天正在等烟雨
147910 而我在等你
150440 炊烟袅袅升起
152250 隔江千万里
181920 天正在等烟雨
183570 而我在等你
185920 炊烟袅袅升起
187760 隔江千万里
CODE:
var lrc_txt:TextField=new TextField();
五、全部代码(文档类 LRCPlayer.as):
var LRCarray:Array=new Array();
var sc:SoundChannel;
public function LRCPlayer() {
lrc_txt.width=500;
lrc_txt.selectable=false;
addChild(lrc_txt);
//歌词在文本 lrc_txt 中显示
var loader:URLLoader=new URLLoader();
loader.load(new URLRequest("LRC/青花瓷.lrc"));
loader.addEventListener(Event.COMPLETE,LoadFinish);
var sound:Sound=new Sound();
sound.load(new URLRequest("Music/青花瓷.mp3"));
sc=sound.play();
//播放声音,并生成 sc 变量,SoundChannel 类的实例
stage.addEventListener(Event.ENTER_FRAME,SoundPlaying);
//实时刷新歌词
}
function SoundPlaying(evt:Event):void {
for (var i=1; i<LRCarray.length; i ) {
if (sc.position<LRCarray[i].timer) {
lrc_txt.text=LRCarray[i-1].lyric;
break;
//找到歌词,跳出循环体
}
lrc_txt.text=LRCarray[LRCarray.length-1].lyric;
//找不到歌词,说明已超出了最后一句的时间,因此显示最后一句歌词
}
}
CODE:
package {
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.text.TextField;
import flash.system.System;
public class LRCPlayer extends Sprite {
var lrc_txt:TextField=new TextField();
var LRCarray:Array=new Array();
var sc:SoundChannel;
public function LRCPlayer() {
System.useCodePage=true;
lrc_txt.width=500;
lrc_txt.selectable=false;
addChild(lrc_txt);
var loader:URLLoader=new URLLoader();
loader.load(new URLRequest("LRC/青花瓷.lrc"));
loader.addEventListener(Event.COMPLETE,LoadFinish);
var sound:Sound=new Sound();
sound.load(new URLRequest("Music/青花瓷.mp3"));
sc=sound.play();
stage.addEventListener(Event.ENTER_FRAME,SoundPlaying);
}
function SoundPlaying(evt:Event):void {
for (var i=1; i<LRCarray.length; i ) {
if (sc.position<LRCarray[i].timer) {
lrc_txt.text=LRCarray[i-1].lyric;
break;
}
lrc_txt.text=LRCarray[LRCarray.length-1].lyric;
}
}
function LoadFinish(evt:Event):void {
var list:String=evt.target.data;
var listarray:Array=list.split("\n");
var reg:RegExp=/\[[0-5][0-9]:[0-5][0-9].[0-9][0-9]\]/g;
for (var i=0; i<listarray.length; i ) {
var info:String=listarray[i];
var len:int=info.match(reg).length;
var timeAry:Array=info.match(reg);
var lyric:String=info.substr(len*10);
for (var k:int=0; k<timeAry.length; k ) {
var obj:Object=new Object();
var ctime:String=timeAry[k];
var ntime:Number=Number(ctime.substr(1,2))*60 Number(ctime.substr(4,5));
obj.timer=ntime*1000;
obj.lyric=lyric;
LRCarray.push(obj);
}
}
LRCarray.sort(compare);
}
private function compare(paraA:Object,paraB:Object):int {
if (paraA.timer>paraB.timer) {
return 1;
}
if (paraA.timer<paraB.timer) {
return -1;
}
return 0;
}
}
}
六、*无处不在的优化
至此,该程序已经可以顺利执行了,此处只讨论一下优化问题,看不懂可以跳过。
以这段代码为例:
CODE:
function SoundPlaying(evt:Event):void {
如果要进行优化,那么这个 for 循环,应该写成:
for (var i=1; i<LRCarray.length; i ) {
if (sc.position<LRCarray[i].timer) {
lrc_txt.text=LRCarray[i-1].lyric;
break;
}
lrc_txt.text=LRCarray[LRCarray.length-1].lyric;
}
}
CODE:
for (var i=1,j=LRCarray.length; i<j; i ) {… …}
这样在执行判断时,不必每次都进行 LRCarray.length 操作,该操用于读取数组长度,执行 Array 类的 length 方法,属于高级操作,花费的时间要比低级操作多。其实,只要读取一次长度,然后将结果保存在变量 j 中,每次判断时读取 j 的值即可。取值与赋值都属于低级别的操作,速度较快。同样的道理,在
CODE:
if (sc.position<LRCarray[i].timer) {… …}
中的 sc.position 在每次判断时都要读取一遍,这时就应将它在循环之前保存到一个变量里,这段代码优化后应是这样:
CODE:
function SoundPlaying(evt:Event):void {
在我们的文档类中还有几个地方用到了 for 循环,请大家按照上述方法自行优化。
var now:Number=sc.position;
for (var i=1,j=LRCarray.length; i<j; i ) {
if (now<LRCarray[i].timer) {
lrc_txt.text=LRCarray[i-1].lyric;
break;
}
lrc_txt.text=LRCarray[j-1].lyric;
}
}
其实,代码优化无处不在,其中的学问不胜枚举,有兴趣的朋友可以到我的博客中看一下关于代码优化的总结贴,见附录。
七、附录
1.LRC 文件下载地址:
http://lrc.bzmtv.com/
http://www.5ilrc.com/
2.至于 MP3 的下载,我想大家比我在行,用百度或酷狗都可以。
3.代码优化总结贴地址:
https://www.jb51.net/flash/actionscript-5898.html
4.整个文件包括(歌曲、歌词、LRCPlayer.as 、FLA 文件)打包下载:
http://www.fs2you.com/zh-cn/files/cf760b0f-01a0-11dd-9174-0014221f3995/
八、结束语
恭喜您坚持到了现在,确实内容比较长,同时也涉及了一些知识点。其实做法肯定不只这一种,所以希望大家多多发挥主观能动性,结合上述内容继续将这个播放程序做大做强。好了,就到这里,再次感谢。