2007/09/12 | 写了一个 LRC 歌词解析函数。
类别(Flash学习笔记) | 评论(0) | 阅读(1120) | 发表于 09:28

  UC教室里有一节MTV的课程,用的是动态加载歌词,于是想到网上众多的LRC歌词,如果直接能从这种类型的歌词里提取需要的内容,一定会很方便,于是就写了这么个函数。

  functin splitLRC(src:String):Object;

  该函数的参数是LRC歌词的内容,返回值是一个对象,该对象具有以下的属性:

lrcObj.ar [ar:艺人名]
 lrcObj.ti [ti:曲名]
 lrcObj.al[al:专辑名]
 lrcObj.by [by:编者(指编辑LRC歌词的人)]
 lrcObj.offset [offset:时间补偿值] 单位是毫秒, 用来指定歌词整体推迟或提前显示。
 lrcObj.dataArray

  前五个属性分别对应LRC歌词中常用的五种标签。后面的数组属性中保存的是由时间和歌词构成的一个轻量级对象。调用的形式是 lrcObj.dataArray[i].t   和 lrcObj.dataArray[i].s 前者表示应该出现的时间,后者表示需要显示的内容。

  LRC格式实际上仍旧是一个文本文件,只是扩展名不一样,可以用下面的代码将文件内容全部加载进来。

var mObj:Object = new Object();

var loadit_lv:LoadVars = new LoadVars();
loadit_lv.onData = function(src:String) {
  if (src != undefined) {
        mObj = splitLRC(src);
     } else {
       trace("Could not load text file.");
     }
};
loadit_lv.load("moon.lrc");

  在应用该对象时,可以用下面的语句,写在onEnterFrame事件处理函数中,或是自定义的interval 事件中。

if (myObj.dataArray[index].t + myObj.offset < the_sound.position) {
  song_txt.text = myObj.dataArray[index].s;
  index++;
 }

  完整示例如下:音乐从网站外加载,LRC歌词从本博客中加载。(本博客中不支持lrc格式上传,因此文件名改成txt来代替。)

源文件下载:

 压缩包下载

函数代码:

function splitLRC(s:String) :Object{
 s = trim(s);
 //以回车符做为拆分的依据,每行尾还保留有一个换行符需要进一步处理
 var m:Array = s.split("\n");
 //trace(m[9]);
 var lrcObj:Object = new Object();
 lrcObj.ar = "";//[ar:艺人名]
 lrcObj.ti = "";//[ti:曲名]
 lrcObj.al = "";//[al:专辑名]
 lrcObj.by = "";//[by:编者(指编辑LRC歌词的人)]
 lrcObj.offset = 0;//[offset:时间补偿值] 单位是毫秒, 用来指定歌词整体推迟或提前显示。
 lrcObj.dataArray = new Array();

 //目前lrc格式的标签共有五种,可任选搭配,但不能重复使用
 var index:Number = 5;

 for (var i = 0; i < 5; i++) {
  var t = m[i].indexOf(":");
  var e = m[i].length;
  var str = m[i].substring(1, t);
  //String类 substring函数字符串首位索引号为0,终止位不包含在返回串中。
  var val = m[i].substring(t + 1, e - 2);
  //trace([str, val]);
  if (str === "ar" || str === "ti" || str === "al" || str === "by" || str === "offset") {
   lrcObj[str] = val;
   //按照对象的属性名称引用对象的属性。
  } else {
   index = i;
   break;
  }
 }
 lrcObj.offset = Number(lrcObj.offset);
 //将offset转换成数值型。

 for (var i = index; i < m.length; i++) {
  //对剩余行的内容进行精确处理。

  //首先根据"]"将时间和歌词拆开,如果有多个时间的情况下,也将同时拆开。 
  var temp:Array = m[i].split("]");
  //trace(temp);

  //获取歌词内容,并将行尾的换行符剔除掉
  var len:Number = temp.length;
  var song:String = rtrim(temp[len - 1]);
  //trace(song);

  for (var j = 0; j < temp.length - 1; j++) {
   //获取分钟数
   var min = temp[j].substring(1, 3);
   //trace(min);

   //获取秒数   
   var sec = temp[j].substring(4);
   //默认情况下,substring将从第四位截取到字串尾。
   //trace( temp[j]);
   //trace( sec );

   //计算歌词出现的时间,单位为毫秒
   var time = 1000 * (Number(min) * 60 + Number(sec));
   //trace(time);

   //将时间和歌词内容保存到lrc对象中去,为便于排序,对数据进行了处理
   lrcObj.dataArray.push({t:10000000 + time, s:song});
  }
 }
 //数组中使用sortOn方法排序时,是按字符串排序,解决办法加上一个大数字,排完序后再减去该数。
 lrcObj.dataArray.sortOn("t");
 for (var i = 0; i < lrcObj.dataArray.length; i++) {
  lrcObj.dataArray[i].t -= 10000000;
  trace([lrcObj.dataArray[i].t, lrcObj.dataArray[i].s]);
 } 
 return lrcObj;
}
//ltrim 消除左边空格
function ltrim(str:String):String {
 var size = str.length;
 for (var i = 0; i < size; i++) {
  if (str.charCodeAt(i) > 32) {
   return str.substring(i);
  }
 }
 return "";
}
//rtrim 消除右边空格
function rtrim(str:String):String {
 var size = str.length;
 for (var i = size; i > 0; i--) {
  if (str.charCodeAt(i) > 32) {
   return str.substring(0, i + 1);
  }
 }
 return "";
}
//trim 消除两边空格
function trim(str:String):String {
 return rtrim(ltrim(str));
}

最后三个字符串处理函数来自于黑羽天翔,在此向他致敬。

0

评论Comments