这个是歌词,大家假如要让这个歌词和当前歌词的进度相匹配,应该怎么匹配时间呢?
本人匹配的慢了2秒的样子,估计是循环嵌套的比较深。
大家有什么高效的做法吗?
解决方案
35
给你看看本人的测试代码
public class SubTitle { public Bitmap bmp1 = new Bitmap(1, 1); public Bitmap bmp2 = new Bitmap(1, 1); public bool Eof = true; Style style = Style.DoubleRow; Font font = new Font("黑体", 24); public enum Style { SingleRow, //单行 DoubleRow, //双行 DoubleRowAlternation, //双行交替 } class Krc { public int StartTime; public int EndTime; public string Word; public int[] Durations; public GraphicsPath path; public int last = 0; public int point = 0; public bool IsTimeOut(int msec) { if (last == 0) point = 0; if (msec >= StartTime + last) { last += Durations[point++]; return true; } return false; } } List<Krc> dat = new List<Krc>(); int sp = 0; public void Prepare(Font f = null, SubTitle.Style s = SubTitle.Style.DoubleRow) { if (f is Font) font = f; style = s; var rect = RectangleF.Empty; foreach (var x in dat) { x.path = new GraphicsPath(); x.path.AddString(x.Word, font.FontFamily, 1, font.Size, Point.Empty, new StringFormat()); rect = RectangleF.Union(rect, x.path.GetBounds()); x.last = 0; } bmp1 = new Bitmap((int)Math.Ceiling(rect.X + rect.Width) + 2, (int)Math.Ceiling(rect.Y + rect.Height) + 2); bmp2 = new Bitmap((int)Math.Ceiling(rect.X + rect.Width) + 2, (int)Math.Ceiling(rect.Y + rect.Height) + 2); sp = 0; Eof = false; } public bool Open(string fname) { foreach (var buf in File.ReadAllLines(fname, Encoding.GetEncoding("gbk"))) { var m = Regex.Matches(buf, @""([\d\w:.,]+)"").Cast<Match>().ToArray(); if (m.Length == 4) { var krc = new Krc(); krc.StartTime = (int)(TimeSpan.Parse("00:" + m[0].Groups[1].Value).TotalMilliseconds); krc.EndTime = (int)(TimeSpan.Parse("00:" + m[1].Groups[1].Value).TotalMilliseconds); krc.Word = m[2].Groups[1].Value; krc.Durations = m[3].Groups[1].Value.Split(",").Select(x => int.Parse(x)).ToArray(); dat.Add(krc); } } if (dat.Count == 0) return false; return Eof = true; } public bool IsTimeOut(int msec) { if (sp >= dat.Count) { Eof = true; return false; } if (msec >= dat[sp].StartTime) return draw(msec); return false; } bool draw(int msec) { if (msec >= dat[sp].EndTime) sp++; if (sp >= dat.Count) { Eof = true; return false; } if (!dat[sp].IsTimeOut(msec)) return false; switch (style) { case Style.DoubleRow: return doubleRow(); case Style.DoubleRowAlternation: return doubleRowAlternation(); } return false; } bool doubleRow() { var g1 = Graphics.FromImage(bmp1); var g2 = Graphics.FromImage(bmp2); if (sp % 2 == 0) { g1.Clear(Color.FromArgb(0, 0, 0, 0)); g1.FillPath(Brushes.Black, dat[sp].path); if (sp + 1 < dat.Count) { g2.Clear(Color.FromArgb(0, 0, 0, 0)); g2.FillPath(Brushes.Black, dat[sp + 1].path); } } var g = sp % 2 == 0 ? g1 : g2; var pr = dat[sp].path.GetBounds(); int w = (int)Math.Ceiling(pr.X + pr.Width * dat[sp].point / dat[sp].Durations.Length); int h = (int)Math.Ceiling(pr.Y + pr.Height); g.Clip = new Region(new Rectangle(0, 0, w, h)); g.DrawPath(Pens.Green, dat[sp].path); return true; } bool doubleRowAlternation() { var g1 = Graphics.FromImage(bmp1); var g2 = Graphics.FromImage(bmp2); if (sp == 0) { g1.Clear(Color.FromArgb(0, 0, 0, 0)); g1.FillPath(Brushes.Black, dat[sp].path); if (sp + 1 < dat.Count) { g2.Clear(Color.FromArgb(0, 0, 0, 0)); g2.FillPath(Brushes.Black, dat[sp + 1].path); } } else { if (sp % 2 == 0 && sp + 1 < dat.Count) { g2.Clear(Color.FromArgb(0, 0, 0, 0)); g2.FillPath(Brushes.Black, dat[sp + 1].path); } if (sp % 2 == 1 && sp + 1 < dat.Count) { g1.Clear(Color.FromArgb(0, 0, 0, 0)); g1.FillPath(Brushes.Black, dat[sp + 1].path); } } var g = sp % 2 == 0 ? g1 : g2; var pr = dat[sp].path.GetBounds(); int w = (int)Math.Ceiling(pr.X + pr.Width * dat[sp].point / dat[sp].Durations.Length); int h = (int)Math.Ceiling(pr.Y + pr.Height); g.Clip = new Region(new Rectangle(0, 0, w, h)); g.DrawPath(Pens.Red, dat[sp].path); return true; } }
歌词
karaoke := CreateKaraokeObject; karaoke.rows := 2; karaoke.clear; // 歌曲附加信息(便于检索) karaoke.tag("歌名", "偶然"); karaoke.internalnumber := 1461; // 歌曲编号 karaoke.tag("缩写", "or"); karaoke.tag("歌手", "蔡琴"); karaoke.tag("字数", "2"); karaoke.tag("语种", "国语"); // 国语/粤语/台语/外语 karaoke.tag("歌类", "女"); // 男/女/乐队/合唱/戏曲/舞曲 karaoke.tag("风格", "流行"); karaoke.videofilename := "pt85440"; karaoke.audiofilename := "*.wav"; karaoke.add("01:05.001", "01:07.284", "你本人相逢", "300,431,474,1078"); karaoke.add("01:07.971", "01:11.374", "在黑夜的海上", "431,431,473,387,474,1207"); karaoke.add("01:12.709", "01:14.819", "你有你的", "387,431,516,776"); karaoke.add("01:15.508", "01:18.823", "本人有本人的方向", "345,433,471,474,472,1120"); karaoke.add("01:21.061", "01:22.956", "你记得也好", "603,172,258,344,518"); karaoke.add("01:24.980", "01:28.037", "最好你忘掉", "259,559,603,861,775"); karaoke.add("01:28.774", "01:31.140", "在那交会时", "429,431,517,474,515"); karaoke.add("01:31.529", "01:36.955", "互放的光亮", "430,603,1636,1336,1421"); karaoke.add("01:42.727", "01:48.326", "本人是天空的一片云", "259,301,344,1292,216,216,1895,1076"); karaoke.add("01:49.662", "01:54.183", "偶尔投影在你的波心", "345,344,429,431,388,431,559,862,732"); karaoke.add("01:57.103", "02:02.055", "你不心讶异无须欢欣", "259,344,345,344,430,345,474,1722,689"); karaoke.add("02:03.132", "02:08.689", "在转瞬间消灭了踪影", "259,302,430,1465,344,430,474,861,992"); karaoke.add("02:12.478", "02:17.863", "本人是天空的一片云", "390,343,387,1034,172,260,1764,1035"); karaoke.add("02:19.025", "02:23.374", "偶尔投影在你的波心", "302,344,431,387,430,475,473,775,732"); karaoke.add("02:26.002", "02:31.557", "你不心讶异无须欢欣", "345,301,517,431,473,388,473,1938,689"); karaoke.add("02:32.247", "02:39.137", "在转瞬间消灭了踪影", "431,474,516,1378,432,473,644,1594,948"); karaoke.add("02:42.583", "02:45.555", "你本人相逢", "602,603,562,1205"); karaoke.add("02:46.201", "02:49.517", "在黑夜的海上", "387,430,431,474,475,1119"); karaoke.add("02:50.851", "02:52.918", "你有你的", "390,557,431,689"); karaoke.add("02:53.564", "02:57.269", "本人有本人的方向", "518,430,473,432,603,1249"); karaoke.add("02:58.432", "03:01.144", "你记得也好", "516,431,516,560,689"); karaoke.add("03:03.428", "03:06.915", "最好你忘掉", "429,560,603,863,1032"); karaoke.add("03:09.205", "03:11.877", "在那交会时", "604,516,517,691,344"); karaoke.add("03:12.608", "03:19.672", "互放的光亮", "430,776,2239,2240,1379");
测试代码
var krc = new SubTitle(); krc.Open("偶然(蔡琴).ksc"); krc.Prepare(null, SubTitle.Style.DoubleRowAlternation); label1.Text = "运行"; //用一个循环来模拟播放器,i 对应播放器的已播放时长(毫秒) int i = 0; while(! krc.Eof) { if (krc.IsTimeOut(i)) { pictureBox1.Image = krc.bmp1; pictureBox2.Image = krc.bmp2; Application.DoEvents(); System.Threading.Thread.Sleep(500); //太快看不清,挂起0.5秒。实用时是不需要的 } i++; } label1.Text = "结束"; }