前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flash/Flex学习笔记(32):播放音乐并同步显示lyc歌词(适用于Silverlight)

Flash/Flex学习笔记(32):播放音乐并同步显示lyc歌词(适用于Silverlight)

作者头像
菩提树下的杨过
发布2018-01-23 15:24:57
7260
发布2018-01-23 15:24:57
举报

题外话:个别朋友总是问我同样的问题,做为一名c#/silverlight程序员为啥还要学flash ?

回 答:看日本片时,就不能对照看欧美的么? 不体会日本的细腻,又怎能感觉到欧美的粗放;同样都是web相关的技术,不必报门户之见;何况这二者有很多可以相互借鉴的东西。

注:这个例子来自[FL车在臣](在blueidea上又名“寂寞火山”)翻译的“Animation in ActionScript3.0”一书,下面的原理分析也来自他的思路

原 理:

1.先分析一下lyc的格式:

[ti:Going Home] [ar:Sophie Zelmani] [al:] [by:yitian1977] [offset:500] [00:01.52]Going Home [00:06.66]Sophie Zelmani [00:11.32] [00:36.60]Not very often have we met / [00:42.94]But the music's been too bad [00:48.92]Can only sense happiness [00:55.68]if the music is sad [00:59.34] [01:00.29]So, I'm going home [01:06.30]I must hurry home [01:11.88]Where a life goes on [01:16.05] [01:20.14]We're too old to make a mess [01:26.16]Dreams will keep me young [01:32.78]Old enough to stress [01:38.86]Only mirrors tell the time [01:41.76] [02:52.99][01:42.80]So, I'm going home [02:59.19][01:48.91]I must hurry home [03:05.33][01:55.04]So will my life go on [03:09.29][02:00.56] [03:17.40][02:07.45]Yes, I'm going home [03:23.70][02:13.43]Going home alone [03:29.80][02:19.77]And your life goes on [03:40.16][02:34.09] [04:05.13][03:52.01](edit by Nathan_na@msn.com)

基本上就是: [时:分.秒](一个或多个) + 本句歌词 2.不管是Flash还是Silverlight,在播放声音时,都可以得到播放进度:即当前播放到了第多少(豪)秒

3.看懂了第1,2点的分析后,可以这么干:

创建一个全局数组(或字典对象,反正只要能满足key-value结构就行),key为该句歌词对应的(豪)秒数,而value即为对应的歌词,然后将其按key(即歌词出现的时间)升序排序

注:对于"[02:52.99][01:42.80]So, I'm going home"这种写法的歌词,在数组中要拆分成二条,即相当于:

[02:52.99]So, I'm going home [01:42.80]So, I'm going home 播放时,根据当前播放的时间进度,找到对应的数组元素,然后显示

Flash版:

As3代码

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;
    import flash.text.TextFieldAutoSize;
    import flash.events.MouseEvent;

    public class LycPlayer extends Sprite {

 var lrc_txt:TextField=new TextField();
 var LRCarray:Array=new Array();//全局数组
 var sc:SoundChannel;
 var sound:Sound;

        public function LycPlayer() {

 //定位歌词显示文本框 
            lrc_txt.width=500;
            lrc_txt.selectable=false;
            lrc_txt.autoSize=TextFieldAutoSize.CENTER;
            lrc_txt.x=stage.stageWidth/2-lrc_txt.width/2;
            lrc_txt.y=0;
            addChild(lrc_txt);

 //加载歌词
 var loader:URLLoader=new URLLoader();
            loader.load(new URLRequest("http://images.24city.com/jimmy/flash/LycPlayer/lyc/GoingHome.txt"));
            loader.addEventListener(Event.COMPLETE,LoadFinish);

 //加载mp3
            sound=new Sound();
            sound.load(new URLRequest("http://www.apple520.com/templates/default/images/new/3.mp3"));
 
 //开始播放
            sc=sound.play();

 //监听Enter_Frame事件
            stage.addEventListener(Event.ENTER_FRAME,SoundPlaying);
            btnStop.addEventListener(MouseEvent.MOUSE_DOWN,StopMouseDownHandler);
            btnPlay.addEventListener(MouseEvent.MOUSE_DOWN,PlayMouseDownHandler);
        }

 function StopMouseDownHandler(e:MouseEvent) {
 if (sc!=null){
                sc.stop();
                sc = null;
            }
        }
 
 function PlayMouseDownHandler(e:MouseEvent) {
 if (sc==null){
                sc = sound.play();
            }
        }

 function SoundPlaying(evt:Event):void {
 if (sc==null){return;}
 //trace(sc.position);
 for (var i:uint=2,j:uint=LRCarray.length-1; i <j; i++) {
 if (sc.position<LRCarray[i].timer) {
                    lrc_txt.text=" "+LRCarray[i-2].lyric+"\n→"+LRCarray[i-1].lyric+"\n "+LRCarray[i].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("\r\n");


 //分析歌词,填充到全局歌词数组中
 var reg:RegExp=/\[[0-5][0-9]:[0-5][0-9].[0-9][0-9]\]/g;
 for (var i:uint=1,j:uint=listarray.length; i <j; 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);

 if (lyric.length<=0) {
 continue;
                }

 for (var k:uint=0,t:uint=timeAry.length; k < t; k++) {
 var obj:Object = new Object();
 var ctime:String=timeAry[k];
 var ntime:uint = 1000 * (parseInt(ctime.substr(1,2),10)*60 + parseInt(ctime.substr(4,5),10)) + parseInt(ctime.substr(7,8),10);
                    obj.timer=ntime;
                    obj.lyric=lyric;
                    LRCarray.push(obj);
                }

            }

 //数组排序
            LRCarray.sort(compare);

 var objFirst:Object = new Object();
            objFirst.timer=1;
            objFirst.lyric="Loading...";
            LRCarray.unshift(objFirst);

 var objLast:Object = new Object();
            objLast.timer=999999;
            objLast.lyric="the end.";
            LRCarray.push(objLast);

 for (var m:Number=0,n =LRCarray.length; m<n; m++) {
                trace(LRCarray[m].timer + "\t" + LRCarray[m].lyric);
            }
        }

 //数组排序辅助方法
        private function compare(paraA:Object,paraB:Object):int {
 if (paraA.timer>paraB.timer) {
 return 1;
            }
 if (paraA.timer<paraB.timer) {
 return -1;
            }
 return 0;
        }
    }
}

Silverlight版:

Xaml部分:

<UserControl x:Class="SilverlightLyricPlayer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="60" d:DesignWidth="400">

 <Grid x:Name="LayoutRoot" Background="White">
 <TextBlock x:Name="txtLyc" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
 <StackPanel Orientation="Horizontal" Height="20" HorizontalAlignment="Right" Margin="0,0,10,0">
 <Button x:Name="btnPlay" Width="40" Margin="5,0,5,0" Content="Play" Click="btnPlay_Click"></Button>
 <Button x:Name="btnStop" Width="40" Content="Stop" Click="btnStop_Click"></Button>
 </StackPanel>
 <MediaElement AutoPlay="True" x:Name="mePlayer" Visibility="Collapsed" />
 </Grid>
</UserControl>

cs部分:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Media;

namespace SilverlightLyricPlayer
{
 public partial class MainPage : UserControl
    {
        List<KeyValuePair<int, string>> lstLycs;

 public MainPage()
        {
            InitializeComponent();
 this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

 void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            lstLycs = new List<KeyValuePair<int, string>>();
            WebClient _wcLyc = new WebClient();
            Uri _uriLyc = new Uri(HtmlPage.Document.DocumentUri, "http://images.24city.com/jimmy/flash/LycPlayer/lyc/GoingHome.txt");
            _wcLyc.OpenReadCompleted += new OpenReadCompletedEventHandler(wcLyc_OpenReadCompleted);
            _wcLyc.OpenReadAsync(_uriLyc);
        }

 void wcLyc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
 if (e.Error == null)
            {
                Dictionary<int, string> dicLyc = new Dictionary<int, string>();

                StreamReader _srReader = new StreamReader(e.Result);
 string _strlyc = _srReader.ReadToEnd().Replace(Environment.NewLine, "\n");
 string[] _arrTemp = _strlyc.Split('\n');
                Regex _reg = new Regex("\\[[0-5][0-9]:[0-5][0-9].[0-9][0-9]\\]");
 int _key = -1;
 string _lyc = "";
 foreach (string item in _arrTemp)
                {
                    MatchCollection _mc = _reg.Matches(item);
 foreach (Match m in _mc)
                    {
                        _key = 1000 * (int.Parse(m.Value.Substring(1, 2)) * 60 + int.Parse(m.Value.Substring(4, 2))) + int.Parse(m.Value.Substring(7, 2));//将时间换成总毫秒数
                        _lyc = item.Substring(item.LastIndexOf(']') + 1);
 if (!dicLyc.ContainsKey(_key) && _lyc.Length > 0)
                        {
                            dicLyc.Add(_key, _lyc);
                        }
                    }

 
                }
                dicLyc.Add(1, "Loading...");
                dicLyc.Add(999999, "the end.");

                lstLycs = dicLyc.OrderBy(c => c.Key).ToList();

 foreach (var item in lstLycs)
                {
                    Debug.WriteLine(item.Key + "\t" + item.Value);
                }

                mePlayer.Source = new Uri(HtmlPage.Document.DocumentUri, "http://www.apple520.com/templates/default/images/new/3.mp3");
                mePlayer.Volume = 0.9;
                mePlayer.Play();
                CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);//相当于As3.0中的addEventListener(Enter.ENTER_FRAME,EnterFrameHandler);
            }
        }

 void CompositionTarget_Rendering(object sender, EventArgs e)
        {
 for (int i = 2; i < lstLycs.Count-1; i++)
            {
 if (mePlayer.Position.TotalMilliseconds < lstLycs[i].Key)
                {
                    txtLyc.Text = " " + lstLycs[i - 2].Value + Environment.NewLine + "→" + lstLycs[i - 1].Value + Environment.NewLine + " " + lstLycs[i].Value;
 break;
                }
                txtLyc.Text = lstLycs.Last().Value;
            }
        }

 private void btnPlay_Click(object sender, RoutedEventArgs e)
        {
            mePlayer.Play();
        }

 private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            mePlayer.Stop();
        }
    }
}

Silverlight演示地址:http://images.24city.com/jimmy/LycPlayer/ (安全沙箱原因,无法在播客园上正常播放,所以只能给出地址)

下载:示例源文件代码

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2010-04-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档