AS3对LRC歌词的解析
2010-01-10上午-AS相关-as3-lrc
MP3播放器的Demo完成已经一些日子,早想写下一点自己的心的,但是因为工作比较忙,
所以耽误了,现在补上:
首先在读取LRC歌词文件的时候,很多人用AS3第一选择会是loader,但是会出现中文
字符编码的问题,而为了避免这个问题的出现,选择URLStream是个不错的选择:
PLAINTEXT
ACTIONSCRIPT:
functionloadLRC(url:String):void
2.{
._stream=newURLStream();
._ntListener(TE,onLoadComplete)
;
:URLRequest=newURLRequest(url);
._(req);
7.}
随后我们对数据读取结果进行处理
PLAINTEXT
ACTIONSCRIPT:
efunctiononLoadComplete(evt:Event):void
2.{
p:String=
._ltiByte(this._vailabl
e,”gb2132″);
ck(temp);
6.}
上面的onLoadComplete中首先对数据进行gb2132的编码转换,这样可以避免中文字
符乱码的问题,lrcCheck这个方法则是处理数据的核心
PLAINTEXT
ACTIONSCRIPT:
efunctionlrcCheck(lrcStr:String):void
2.{
3.__All();
pArr:Array=('rn');
(vari:int;i{
pStr:String=e(“[","");
pA:Array=("]“);
(varj:uint=0;j{
pB:Array=tempA[j].split(“:”);
(tempB[0])
11.{
“ti”:
=tempB[1];
;
“ar”:
=tempB[1];
;
“al”:
=tempB[1];
;
“by”:
=tempB[1];
;
“offt”:
t:
pTime:int=0;
:Object=newObject();
[0]=tempB[0].replace(“[","");
me+=parInt(tempB[0])*60000;
me+=tempB[1]*1000;
=tempTime;
t=tempA[-1];
34.__m(obj);
;
36.}
37.}
38.}
_sort:Sort=newSort();
40._=[newSortField("head")];
41.__=_sort;
42.__h();
43.}
因为自己之前的设想是歌词存储到数组里面,由于程序采取单模式,即临时数据保存在
model里面;
首先按照“rn”进行分割,然后去除数据中的"[",因为我觉得这个符号对于自己的处理没
有什么用处,后面的分割用"]"来进行;而这样分割的原因还有一个因素,那就是歌词的格
式可能是这样的:
[01:05.01][03:01.80]好多年没有再一次翻开它
这就是LRC的复试歌词,以"]"来分割可以将
[01:05.01]
这样的时间独立存储到数组里面,而在所有数据都存储完毕后,用
PLAINTEXT
ACTIONSCRIPT:
_sort:Sort=newSort();
2._=[newSortField("head")];
3.__=_sort;
4.__h();
这段程序,对数组进行重新排序,规则则按照"head",也就是时间排序,这样,
[01:05.01][03:01.80]好多年没有再一次翻开它
的数据就变成了:
[01:05.01]好多年没有再一次翻开它
和
[03:01.80]好多年没有再一次翻开它
两条不同数据,而对于sort的具体用法,请大家查看Flash的帮助手册。
好了今天写到这里,后面会对歌词数据的同步进行简单的总结。
今天心情不错,用FLASH写了一个用于读取LRC同步歌词的类,只要25行代码,完全用是用FLASH的字符
串操作来分析标签的。
下面就是这个类:
复制内容到剪贴板
代码:
packageLRC{
publicclassreadlrc{
publicfunctionreadlrcastime(mp3playtime:Number,gc:String):String{
varqsd:int;//起始点
varfhz:String;
for(varj:int=0;j<;j++){
if(deAt(j)==58){
if(int((j-2,j))*60+int((j
+1,j+3))==mp3playtime){
vari:int=0;
do{
i++;
if(deAt(j+i)==93){
qsd=j+i;
}
if(deAt(j+i)==13)
{
fhz=(qsd+
1,j+i);
}
}while(deAt(j+i)!=
13&&j+i}
}
}
returnfhz;
}
}
}
将此文件保存为。
注意:一定要把此AS文件放入一个名为LRC的文件夹中,才可以使用。
下面就用一个小示例来说明如何用这个类,新建一个AS文件,写入以下代码:
复制内容到剪贴板
代码:
package{
lip;
;
der;
uest;
;
hannel;
;
eld;
c;
publicclassmp3extendsMovieClip{
privatevarlrcreq:URLRequest=newURLRequest("日不落.lrc");
privatevarmp3url:URLRequest=newURLRequest("日不
落.mp3");
privatevarmymp3:Sound=newSound();
privatevarchannel:SoundChannel=newSoundChannel();
privatevarlrcurl:URLLoader=newURLLoader();
privatevartbgc:String;
privatevarmylrc:readlrc=newreadlrc();
ePage=true;
publicfunctionmp3(){
(mp3url);
channel=();
(lrcreq);
ntListener(TE,loaded);
}
privatefunctionenterframe(event:Event){
try{
gc_=castime(int(on/1000),tbgc);
}catch(error:Error){
//
}
}
privatefunctionloaded(event:Event){
tbgc=String();
addEventListener(_FRAME,enterframe);
}
}
}
保存此文件为。
写完后,我们还需要一个FLA文件来编译这些代码,新建一个FLA文件,名字随意,在场景中拖出一
个动态文本域,实例名称填写gc_txt,在FLA文件的文档类中填写mp3,将此FLA文件与文件,日
不落.mp3文件,日不落.lrc文件和名为LRC的文件夹放入同一个目录下,测试影片,就可以看到效果了。
as3.0正则处理lrc
e{
y.*;
.*;
.*;
.*;
6.
SingleLineLyrics;
8.
classLyricsFormat/*extendsEventDispatcher*/*/{
10.
evarpath:String;
evarAllLineLyrics:Array;
13.
14.//歌曲信息;
vartitle:String;
varautor:String;
varalbum:String;
varby:String;
19.
20.//事件类,我就不写了,
varonComplete:Function;
22.
23.
24./*
*接收一个路径上的lrc;
*/
functionLyricsFormat(path:String){
(path==null){
ewError("必须要有至少一个参数");
28.}
eLyrics=newArray();
30.
der:URLLoader=newURLLoader();
rmat=;
ntListener(TE,completeHand
er);
34.
uest:URLRequest=newURLRequest();
=path;
(request);
38.}
39.
40./*
*加载完成;
*/
oncompleteHander(event:Event):void{
42.
der:URLLoader=URLLoader();
()
EventListener(TE,completeH
ander);
46.
47.}
48.
49./*
*开始进行比对.存储;
*/
onbulid(data:String){
51.
=Single(/[ti:(.+)]/i,data,"标
题:");
=Single(/[ar:(.+)]/i,data,"歌
手:");
=Single(/[al:(.+)]/i,data,"专
辑:");
=Single(/[by:(.+)]/i,data,"制
作:");
56.
([title,autor,album,by]);
58.
59.
:RegExp=/n[d+:.+][^[rn]*/img;
ics:Array=(RE);
62.
h(vari:StringinLyrics){
gleLineTime:String=Single(/[(
.+)].*/,i);
gleLineTimeArray:Array=
it("][");
gleLineText:String=Single(/.+
](.*)/,i);
67.
each(singleLineTimeinsingleLineTimeArray){
69.
eTimeArray:Array=
(":");
71.
lineTime:Number=Number(LineTimeArray[0])*60*1000+Number(LineTim
eArray[1])*1000;
73.
(newSingleLineLyrics(line
Time,singleLineText));
75.
76.}
77.
78.}
();
80.
81.//触发;
lete();
83.}
84.
85./*
*进行排序比较;
*/
functionEquals(a,b){
SingleLineLyrics(a).Equals(b);
88.}
89.
90./*
*返回所需数组;
*/
functiontoArray():Array{
92.
eLyrics;
94.}
95.
96./*
*用正则选择单个所需内容;
*/
onlectSingle(RE:RegExp,data:String,typeS:String
=""):String{
((data)){
typeS+""+(data)[1];
100.}
101.//没有记录此项;
"";
103.}
104.
105.}
106.}
这几天CSDN的通栏广告放着正则表达式培训的广告。正则表达式这玩意很有意思,
在AS3中,也新增了正则表达式。正则表达式描述用于查找和处理字符串中的匹配文本的
模式。正则表达式类似于字符串,但是可以包含特殊代码以描述模式和重复。切记,不同的
编程环境实现正则表达式的方式也不同,所以,从别的地方看过来的正则表达式在AS3中
未必合用。
具体的正则表达式语法规则请查看帮助文档。在网络上没看到过AS3正则表达式
写的LRC歌词分析程序,下面,就给出一段使用正则表达式来分析LRC格式歌词的程序。
functionlrc(str:String):void
...{
varresults:Array;
results=(/[ar:(.+)]/i);
varar:String=results?results[1]:'';
results=(/[ti:(.+)]/i);
varti:String=results?results[1]:'';
results=(/[al:(.+)]/i);
varal:String=results?results[1]:'';
results=(/[by:(.+)]/i);
varby:String=results?results[1]:'';
results=(/[offt:(.+)]/i);
varofft:int=results?int(results[1]):0;
results=(/[d+:.+][^[]*/ig);
if(!results)
...{
results=(/[d+:.+][^[]*/ig);
}
if(!results)
...{
return;
}
vargc:Array=newArray();
for(vari:int=0;i<;i++)
...{
varln:String=results[i];
vartm:String=(/[(.+)].*/)[1];
varwd:String=(/.+](.*)/)[1];
varts:Array=('][');
foreach(vart:Stringints)
...{
varc:Array=(':');
(...{time:int((c[0]*60+c[1])*1000),word:wd});
}
}
("time",C);
foreach(varg:Objectingc)
...{
trace('时间:',,'毫秒,歌词:',);
}
}使用LRC歌词和SoundMixer配合,我们就能够开发出很好的音乐播放器了。
本文来自CSDN博客,转载请标明出处:
/l__yong/archive/2008/01/07/
1./加载歌词
varlrcUrl:String=[currIndex].lrc;
if(lrcUrl!=null&&lrcUrl!="")
{varlrc:URLLoader=newURLLoader();
//rmat=LES;
(newURLRequest(lrcUrl));
ntListener(TE,LRC_Complete);
ntListener(_ERROR,LRC_IOError);
}
lrcArr=null;
outPutLRCString="";
startIndexOf=0;
="";
2.然后在加载完成的事件里,我们能得到lrc文本字符串,这时候我们需要
对字符串进行处理,把它转换成一个Array数组,函数方法如下:
3.
functiongetLRCArray(lrc:String):Array{varlrcArr:A
rray=newArray;lrc+="r";
for(vari:int=0;i<;i++){vartime:
Number=0;if((i)==":"){time
=Number((i-2,i))*60+Number((i+1,i
+3));if(String(time)!="NaN"){v
arj:uint=0;varstartIndex:uint=0;
varendIndex:uint=0;do{
j++;if((i+j)=="]"){
startIndex=i+j+1;
}}while(i+j
endIndex=f("r",i);
if(startIndex!=0&&endIndex!=0){
([time,(startIndex,endIndex)
]);}}}}returnl
rcArr;}
5.解析歌词返回的Array数组为多围数组,数组里的每一项是为一个二围数
组,item[0]为当前秒数,item[1]为该秒显示的歌词(句),比如item[0]=
歌曲名:你最近还好吗、item[5]=演唱:S.H.E,就是代表第0秒显示歌
曲名:你最近还好吗,而从第5秒起则显示演唱:S.H.E,这样通过
getLRCArray方法就能得到歌曲所有的时间段显示的歌词拉。本例中把所
有歌词放在一个editable="fal"不可修改的mx:TextArea文本域
内。
6.
7.歌词同步显示的问题
8.
9.歌词能全部加载显示了,问题是怎么随着歌曲的播放而高亮显示当前行歌
词呢?不过还好Flex提供一个TextRange能对TextArea内文本进行选择
性的处理,你只需要设置beginIndex和endIndex就能自动匹配到
TextArea中间区域的文本,我这里只是简单的改变了一下颜色,不过我
们从TextArea中找某一个句歌词索引的时候需要注意歌词有很多是重复
的,所以我们需要用一个变量保存当前歌词播放位置索引startIndexOf,
以确保我们高亮选择到的歌词是正确的。同时将TextArea滚动条设置到
对应的高度,主要的代码如下:
10.
11.//同步显示歌词
if(lrcArr!=null&&>0){varc:Number=int(c
on/1000);for(varj:int=0;j<;j++){
if(lrcArr[j][0]==c){varcurrentLrc:Stri
ng=lrcArr[j][1];if(currentLrc!=
xt){=currentLrc;
//高亮显示,先清空之前高亮部
分vartr:TextRange=newTextRange(txtLrc);
=le("color");
varbeginIndex:int=
dexOf(currentLrc,startIndexOf);startIndexOf+=
;varendIndex:int=beginInd
ex+;ndex=beginInd
ex;ex=endIndex;if(
!=""){=
"yellow";
}//设置滚动条位
置alScrollPosition=j*
ticalScrollPosition/;if(
-j<=5)alScrollPosition=
ticalScrollPosition;}
break;}}}
在主时间轴上加上
ePage=true;
以免读取中文SRT字符串乱码。
复制内容到剪贴板
代码:
package{
.*;
.*;
publicclassMySrt{
privatevar_title:String="";
privatevar_arrList:Array=newArray();
privatevar_lastTime:uint=0;
privatevar_lastIndex:uint=0;
publicfunctionMySrt(path:String,srtName:String){
_title=srtName;
varurl:URLRequest=newURLRequest(path);
varloader:URLLoader=newURLLoader();
ntListener(TE,
OnLoadComplete);
(url);
}
privatefunctionOnLoadComplete(event:Event):void{
varloader:URLLoader=URLLoader();
vartxt:String=;
if(txt!=""){
varregStr:String=
"d+rn(d{2}:d{2}:d{2},d{3})-->
(d{2}:d{2}:d{2},d{3})rn(.*?)rnrn";
varreg:RegExp=newRegExp(regStr,"gism");
varrst:Object=null;
while(true){
rst=(txt);
if(rst!=null){
varsrtItem:Object={"bt":ParTime(rst[1]),
"et":ParTime(rst[2]),"txt":rst[3]};
_(srtItem);
}el{
break;
}
}
}
}
privatefunctionParTime(str:String):uint{
varnRet:uint=0;
if(str!=""){
vararr1:Array=(",");
varnMs:uint=parInt(arr1[1]);
vararr2:Array=arr1[0].split(":");
varnH:uint=parInt(arr2[0]);
varnM:uint=parInt(arr2[1]);
varnS:uint=parInt(arr2[2]);
nRet+=nS*1000;
nRet+=nM*60*1000;
nRet+=nH*60*60*1000;
nRet+=nMs;
}
returnnRet;
}
publicfunctionGetText(time:uint):String{
varstrRet:String="";
if(time<_lastTime){
_lastIndex=0;
}
for(vari:uint=_lastIndex;i<_;i++)
{
varobj:Object=_arrList[i];
if(<=time&&time<=){
strRet=;
_lastTime=;
_lastIndex=i;
break;
}
}
returnstrRet;
}
publicfunctionGetTitle():String{
return_title;
}
}
}
本文发布于:2022-11-26 09:23:12,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/24217.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |