最近想恶补下英语,找了很多MP3播放软件,但是没有哪个能按照句子播放时间来播放声音的,想想自己学习过的WinForm,为什么不自己写一个程序呢?一个想法出现在脑海中,说干就干,花了一天时间,先研究了一下LRC文件的结构,windows media player控件的使用,加上一些简单的控制,这个简陋的LRC复读机就诞生了!在网上得到很多朋友的帮助,现将全部源程序公开,以表谢意,您可以随意使用,修改.如果程序造成了死机及至电脑起火爆炸,很抱歉,不是我运行的!

代码很简单,思路那就更简单,有句英文怎么说呢:it’s ugly, it’s simple, but it works!

这个复读机功能如下:

可以播放带有lrc文件的mp3文件,按照每个句子的的时间来进行声音片段的播放.

使用方法:

先点击选择文件,选择一个有配套LRC的mp3,注意文件名必须相同,不然程序会报错

然后,程序就会自动载入LRC文件,并将文本内容读取到右边的listBox中,你可以在listBox中双击,键盘上下,回车什么的随便你,总之,想听哪句点哪句,读完就暂停了.或者你将英文显示关掉,只用上一句和下一句控制朗读,觉得一句一句听得不过瘾,就点全部播放,相信到这儿你看出来了,这个小软件就是用来练习听力的

要开发,先研究最基本的东西,这个小软件需要用到lrc,为什么用它呢?

先说说LRC文件的结构:

比如这个新概念的一个MP3的LRC文件内容

[al:新概念英语(二)]
[ar:MP3 同步字幕版(美音)]
[ti:A Private Conversation]
[by:更多学习内容,请到VeryCD.com搜索“露珠”]
[00:09.77]Why did the writer complain to the people behind him?
[00:15.91]Last week I went to the theatre.
[00:19.39]I had a very good seat.
[00:22.07]The play was very interesting.
[00:25.10]I did not enjoy it.
[00:27.43]A young man and a young woman were sitting behind me.
[00:31.96]They were talking loudly.
[00:34.59]I got very angry.
[00:37.41]I could not hear the actors.
[00:40.64]I turned round.
[00:42.80]I looked at the man and the woman angrily.
[00:47.27]They did not pay any attention.
[00:50.69]In the end, I could not bear it.
[00:54.98]I turned round again.
[00:57.75]'I can't hear a word!' I said angrily.
[01:03.45]'It's none of your business,'
[01:06.27]the young man said rudely.
[01:09.00]'This is a private conversation!'

前四行不用看,咱们关心的是下面,[]内部就是时间了,比如第一行[00:09.77]表示从09.77秒开始,在下面一句的15.91秒处结束;

[00:15.91]Last week I went to the theatre.这行从15.91秒处开始,在下面一句19.39秒处结束,下面的都一样,最后一句

[01:09.00]'This is a private conversation!'从1分9秒开始,结束时间?mp3播放的结束时间

现在的问题是:如何取得时间以及文本的内容呢?

先说时间,全部都是分钟在前,秒在后,格式都一样[??:??.??],这种非常规律的文本用正则表达式来取值是最简单不过了,如果你还不懂正则表达式,请先去学习了再继续往下看:

/d{2}:/d{2}./d{2}就可以得到整个时间字符串,把全部的时间取出来,再做成时间对,比如

00:09.77    00:15.91

00:15.91    00:19.39

以开始时间和结束时间命名,这样就可以用一个struct来保存每一对:

struct 时间对
{
public double 开始时间;
public double 结束时间;
//如果想在listBox中显示开始时间和结束时间,需要重载ToString方法
public override string ToString()
{
return string.Format("{0,8}-{1,8}", 开始时间, 结束时间);
}
}

有了时间对,咱们不就可以在WMP中按照某一段时间来播放了?在WMP的研究中发现要想在WMP中从09.77秒处播放,需要使用double数据类型!

如上图所示Ctlcontrols.currentPosition只接受double,这个double和时间是个什么关系?网上没有找到相关的资料,只好自己做实验来研究了,弄了个mp3,给这个currentPosition赋值,发现其实很简单,就是个秒数,比如currentPosition=09.77,播放条一下就跑到09.77秒处了;那么1分9秒呢?1*60+9,OK,知道如何来控制播放的时间了,讲这些是因为需要将01:09.00这种字符串转换成double类型,需要单独取出分钟01和秒数09.00,奈何?

正则表达式可以从一个匹配字符串中一次取出二个,上面的/d{2}:/d{2}./d{2},改成(/d{2}):(/d{2}./d{2})就可以了,然后在程序中取出这二组,转换成double即可:

private static double 获取匹配时间(string 内容来源)
{
Regex 时间匹配 = new Regex("(//d{2}):(//d{2}.//d{2})", RegexOptions.None);
if (时间匹配.IsMatch(内容来源))
{
Match ma = 时间匹配.Match(内容来源);
double 分钟 = Convert.ToDouble(ma.Groups[1].Value);
double 秒数 = Convert.ToDouble(ma.Groups[2].Value);
return 分钟 * 60 + 秒数;
}
else
{
return -1;
}
}

有了能够取出一个字符串中的时间的方法,再使用一个File.ReadAllLines将lrc文件的每一行都读取进一个string[]中,弄一个循环就可以得到整个lrc文件的时间对:

public List<时间对> 得到时间对列表()
{
List<时间对> 时间对列表 = new List<时间对>();
时间对 coupleTime = new 时间对();
//读取LRC文件的每一行并获取时间
for (int i = 0; i < LRC文件内容.Length - 1; i++)
{
if (获取匹配时间(LRC文件内容[i]) < 0)//没有找到匹配项,继续
{
continue;
}
else
{
coupleTime.开始时间 = 获取匹配时间(LRC文件内容[i]);
coupleTime.结束时间 = 获取匹配时间(LRC文件内容[i + 1]);
时间对列表.Add(coupleTime);
}
}
//最后一个结束时间需要用MP3的总长度赋值,或者偷懒,double.MaxValue:)
coupleTime.开始时间 = 获取匹配时间(LRC文件内容[LRC文件内容.Length - 1]);
coupleTime.结束时间 = double.MaxValue;
时间对列表.Add(coupleTime);
return 时间对列表;
}
OK,时间的问题解决掉;文本内容如何得到呢?其实也可以和时间一起获取,效率高,不过考虑到正则表达式不好写,再加上反正lrc文件小,现在计算机速度快,用简单清晰略带冗余的方式来处理好喽:
 
private static string 获取匹配英文短语(string 内容来源)
{
//注意,如果正则是[a-zA-Z/s/./?'!,]+$,也就是没有两边的()
//那么取的值就是空,因为并没有组存在!
//要使用Groups来获取,必须在两边加上()
//Regex 文字匹配 = new Regex(@"([a-zA-Z/d/s/./?'!,_-]+$)", RegexOptions.None);
string 纯英文LRC=@"([a-zA-Z/s/./?'’!,,_/d-]+$)";
string 中英文LRC=@"";//留一个位置,以后还可以读取带中文翻译的LRC
string regexString=纯英文LRC+中英文LRC;
Regex 文字匹配 = new Regex(regexString, RegexOptions.Multiline);
if (文字匹配.IsMatch(内容来源))
{
Match ma = 文字匹配.Match(内容来源);
return string.IsNullOrEmpty(ma.Groups[1].Value) ? ma.Groups[2].Value : ma.Groups[1].Value;
}
else
{
return null;
}
//这样也可以得到正确的值
//Regex 文字匹配 = new Regex(@"[a-zA-Z/s/./?'!,]+$", RegexOptions.None);
//if (文字匹配.IsMatch(内容来源))
//{
//    Match ma = 文字匹配.Match(内容来源);
//    return ma.Value;
//}
//else
//{
//    return null;
//}
}

这个获取有一点儿小小问题,就是只能获取到仅仅含有英文的lrc文件,如果有中文,那么就只会得到null,因为正则表达式([a-zA-Z/d/s/./?'!,_-]+$)最后是以$结束的.

比如这种lrc文件:

[00:00.440]--- lesson1 SCHOOLS AND EDUCATION 学校和教育
[00:06.160]--- Basic Patterns 基本句型
[00:09.160]What college should I attend in the fall?^秋季我上哪一所大学好呢?
[00:14.080]I’m majoring in history.^我学的是历史专业。
[00:17.880]Can you tell me where is the dormitory?^你能告诉我宿舍在哪吗?
[00:22.240]I’m taking extra classes this semester.^这个学期我额外选修了一些课程。
[00:26.720]Are you having problems with chemistry?^你在化学方面有困难吗?
[00:30.760]I’m not worried about this test.^我并不担心这次考试。
[00:34.520]The prices on textbooks have gone up.^课本的价格上涨了。
[00:38.880]Our class has a meeting after lunch.^午餐后我们班要开一个会议。

英文字符串就获取不到了,因为最后结束的是中文字符,有非常懂正则表达式的还请赐教,如何从上面的字符串中一次性取得英文字符串和中文字符串呢?我自己研究了一下,这个英文标点和中文标点可真是让人头大,少写一个或者写错,什么也得不到!

待续...

(原创)C# LRC复读机-1相关推荐

  1. 复读机java群管脚本_JS让浏览器实现复读机的功能_js

    几年前,看到一台湾人写的一段程序(好像是<日语基础>),在网页上实现音视频与文字的同步播放(就是音视频播到哪部分,相应的文字就亮显,点击某一句话,播放器将从这句话开始播放.)当时觉得这个很 ...

  2. 英语复读机软件测试大乐,‎App Store 上的“点滴复读机 - 英语听力口语学习神器”...

    先说一下为什么收费? 1:点滴复读机是专业的软件复读机,专门为英语听力练习而设计,提供了超越传统复读机的功能体验,对您的英语听力口语学习会有很大的帮助: 2:会免费共享一些英语听力学习资源: 3:点滴 ...

  3. EnMp3Player 学习英语口语的好软件(MP3复读机)

      最好用--英语口语学习软件(MP3复读机) EnMp3Player 一.软件用途 轻松进行听力练习:MP3断句复读.同步字幕显示.屏幕取词翻译(解决生词问题). 软件适用人群范围:小学生.初中生. ...

  4. [集训队作业2018] 复读机(生成函数,单位根反演)

    传送门 subtask 1:d=1d=1d=1 答案为knk^nkn. subtask 2:n≤1000,k≤100n\leq1000,k\leq 100n≤1000,k≤100 设f[i][j]f[ ...

  5. 【牛客 - 327G】处女座与复读机(可编辑距离问题,dp)

    题干: 链接:https://ac.nowcoder.com/acm/contest/327/G 来源:牛客网 一天,处女座在牛客算法群里发了一句"我好强啊",引起无数的复读,可是 ...

  6. 简单复读机LR如何成为推荐系统精排之锋?

    文 | 水哥 源 | 知乎 saying 1. 众所周知, 人类(划掉)推荐的本质是复读机 2. 精排之锋,粗排之柔,召回之厚 3. 在推荐里谈"过拟合"很容易给我们造成心理上的松 ...

  7. 问题 J: 寻找复读机【模拟】

    问题 J: 寻找复读机 时间限制: 1 Sec  内存限制: 128 MB 提交: 131  解决: 50 [提交] [状态] [讨论版] [命题人:admin] 题目描述 某个QQ群里一共有n个人, ...

  8. (江西财经大学第二届程序设计竞赛同步赛)E-是不是复读机

    E-是不是复读机 题目描述: 在复读纪元2140年,复读机(们)已经放弃了如下所示的低级复读方式: "哟,小伙汁,想不到你也是个复读机" "哟,小伙汁,想不到你也是个复读 ...

  9. UOJ#450. 【集训队作业2018】复读机 排列组合 生成函数 单位根反演

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ450.html 题解 首先有一个东西叫做"单位根反演",它在 FFT 的时候用到过: ...

最新文章

  1. 前端知识点回顾之重点篇——JavaScript异步机制
  2. 上周热点回顾(6.20-6.26)
  3. VTK:vtkCubeAxesActor用法实战
  4. 媒体声音 | 阿里云王伟民:阿里云数据库的策略与思考
  5. 全球服务器系统市场份额,IDC发布2017年第一季度全球融合系统报告 超融合市场最火爆...
  6. 一台服务器的黑道生涯之八 谁信任谁
  7. python多任务_【python】多任务(1. 线程)
  8. 数据展示_使用Cadvisor监控容器并展示数据
  9. 【原创文章】通过英文电影突破英语
  10. RedisTemplate 常用方法、序列化方式、基于 Redis 实现分布式锁
  11. 求每个月最后一天mysql函数_计算指定年月的最后一天的自定义MYSQL函数_MySQL
  12. PTA|团体程序设计天梯赛-练习集|JAVA版
  13. 解决Tomcat在cmd乱码问题
  14. ESP8266 读取MPU-6050数据OLED显示
  15. 通过 Amazon EFS 对 NFS 文件系统权限进行细粒度控制
  16. Android 9.0 蓝牙电话BluetoothHeadsetClient
  17. 终于更新了!利用黎曼几何分析EEG脑电信号(三)
  18. 春夏喝绿茶花茶、秋冬喝乌龙普洱红茶
  19. 国内云服务地域选择和测速
  20. [英语阅读]投机者-Lame duck

热门文章

  1. PVE 下解决 iKuai 断流、重启问题
  2. sparksql agg用法
  3. ACW3302表达式求值
  4. 问题: Schrodinger方程的非齐次Strichartz估计
  5. input函数以及while处理列表和字典
  6. 计算机软件著作权侵权行为的认定,计算机软件著作权侵权行为认定方法探讨.doc...
  7. 电脑声卡驱动正常但是没有声音怎么办 电脑声卡坏了怎么办
  8. 无主复制系统(2)-读修复和反熵
  9. 扎心了!当代大学生孤独等级测试,你是第几级?
  10. WK2124 驱动移植