Flash/Flex学习笔记(32):播放音乐并同步显示lyc歌词(适用于Silverlight)
2010-11-22 17:10
465 查看
题外话:个别朋友总是问我同样的问题,做为一名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版:
Xaml.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/ (安全沙箱原因,无法在播客园上正常播放,所以只能给出地址)
下载:示例源文件代码
回 答:看日本片时,就不能对照看欧美的么? 不体会日本的细腻,又怎能感觉到欧美的粗放;同样都是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版:
Xaml.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/ (安全沙箱原因,无法在播客园上正常播放,所以只能给出地址)
下载:示例源文件代码
相关文章推荐
- Flash/Flex学习笔记(32):播放音乐并同步显示lyc歌词(适用于Silverlight)
- Android VLC播放器二次开发3——音乐播放(歌曲列表+歌词同步滚动)
- Android 实现歌曲播放时歌词同步显示
- Android 实现歌曲播放时歌词同步显示
- 手机影音第十六天,集成eventbus代替广播 ;在音乐播放页面中间部分显示歌词
- AVAudioPlayer本地音乐播放、后台播放、歌词同步,都告诉你
- android 音乐播放歌词同步,歌词自动滚动,歌词换行等功能完美解决方案
- Android实现歌曲播放时歌词同步显示具体思路
- AVAudioPlayer实现音乐播放+歌词与播放进度同步
- iOS播放音乐锁屏后显示歌词
- Android VLC播放器二次开发3——音乐播放(歌曲列表+歌词同步滚动)
- Android 实现歌曲播放时歌词同步显示
- Android VLC播放器二次开发3——音乐播放(歌曲列表+歌词同步滚动)
- Android VLC播放器二次开发3——音乐播放(歌曲列表+歌词同步滚动)
- 一步一步学Silverlight 2系列(32):图形图像综合实例—“功夫之王”剧照播放
- iOS_33_音乐播放(后台播放+锁屏歌词)
- iOS开发之MPNowPlayingInfoCenter 锁屏显示正在播放的音乐
- 桌面歌词的同步显示
- 根据歌名歌手专辑搜索音乐的播放地址和歌词地址
- 初级音乐播放器——播放存储卡上的一首音乐,能够显示歌曲名和播放进度,并且能够播放和暂停(没有SD卡会报错)