(原创)C#LRC复读机-2

有了单个的英文字符串,咱们就可以得到整个的英文字符串数组,如下:

public List<string> 得到短语列表()
{
    List<string> phraseContent = new List<string>();

    //获取短语列表和时间有点不同,因为循环会多一次
    for (int i = 0; i < LRC文件内容.Length; i++)
    {
        if (获取匹配英文短语(LRC文件内容[i]) == null)//没有找到匹配项,继续
        {
            continue;
        }
        else
        {
            phraseContent.Add(获取匹配英文短语(LRC文件内容[i]));
        }
    }
    return phraseContent;
}

这儿的循环和获取时间对不同,相信看官能够领悟到为什么.

 

如何到获取文件内容呢?LrC是个文本文件,用C#自带的File.ReadAllLines就可以得到所有的行:

private string[] 读取LRC文件(string 媒体文件名)
{
    //将文件名后缀改为lrc以便得到一个新的文件名
    //如果用IndexOf有可能因为文件中有两个.而造成故障
    //所以需要使用最后一个匹配
    int 点处的位置 = 媒体文件名.LastIndexOf('.');
    string lrc文件名 = 媒体文件名.Replace(媒体文件名.Substring(点处的位置+1,3), "lrc");

    if (File.Exists(媒体文件名) && File.Exists(lrc文件名))
    {
        
        try
        {
            return File.ReadAllLines(lrc文件名);
        }
        catch (Exception)
        {
            string output = string.Format("{0}文件读取错误", lrc文件名);
            throw new Exception(output);
        }
        
    }
    else
    {
        string output = string.Format("{0}或{1}不存在!", 媒体文件名,lrc文件名);
        throw new Exception(output);
    }
}
public LRC(string 媒体文件名)
{
    this.LRC文件内容 = 读取LRC文件(媒体文件名);
}

这段程序对需要播放的媒体文件有个要求,就是需要你的媒体文件名和lrc要同时存在,并且其文件名要相同

构造函数中有一个this.LRC文件内容,这是一个字符串数组,所有的时间对和英文短语都以它为基础.

OK,到现在为止,一个读取LRC,并且能够从中产生时间对和字符串的类就完成了,下面咱们就可以配合WMP来使用它了.

先来看看如何播放和停止声音中的某些片段:

private void button播放_Click(object sender, EventArgs e)
{
    //axWindowsMediaPlayer1.Ctlcontrols.currentPosition = 11.01;表示11.01秒
    //对currentPosition赋值就表示你想从什么时间开始
    //和下面的时钟配合就可以做到精确的片段播放
    axWindowsMediaPlayer1.Ctlcontrols.currentPosition = 开始时间;
    axWindowsMediaPlayer1.Ctlcontrols.play();
}
private void timer1_Tick(object sender, EventArgs e)
{

    var 毫秒时间 = 取得毫秒(axWindowsMediaPlayer1);
    //这里需要用>=判断,用==有时候会失灵,推断可能是浮点数的不确定造成的
    if (毫秒时间 >= 结束时间)
    {
        axWindowsMediaPlayer1.Ctlcontrols.pause();
    }
    //不停的显示当前播放时间
    label1.Text = 毫秒时间.ToString();
}
private static double 取得毫秒(AxWindowsMediaPlayer 媒体控件)
{
    //直接返回当前时间也是OK的
    //return 媒体控件.Ctlcontrols.currentPosition;
    //不过为了显示的好看,还是只取小数点后两位

    //比如3.45986*100=345.986
    //Math.Floor(345.986)取最小整数变成345
    //再除以100,变成3.45,就实现了只取2位小数,并且不四舍五入
    return Math.Floor(媒体控件.Ctlcontrols.currentPosition * 100) / 100;

    //如果想取三位,可以这样:
    //return Math.Floor(媒体控件.Ctlcontrols.currentPosition * 1000) / 1000;
}

主要用到WMP中的几个最常用的片段播放控制

Ctlcontrols.currentPosition ,从你指定的时间开始,后面跟上Ctlcontrols.play(); 就会一直播放,如果你没有设置结束时间,那么会一直播放到媒体文件结束.

对结束的控制,用了一个Timer控件,这个timer会不停的循环,每隔10毫秒(Interval)就会执行一次,注意其起始状态是关闭的(Enabled=False),因为程序运行的时候只有在读取完lrc文件后才能开始控制,所以要先关闭.

image

Ctlcontrols.pause是暂停,一开始我用的是Ctlcontrols.Stop,结果开始时间变为0,这个是需要注意的地方.

现在可以控制片段播放了,那么如何得到我所需要的时间对呢?这个需要用到listBox以及获取到的短语列表.

先选择一个媒体文件:

private void button选择文件_Click(object sender, EventArgs e)
{
    //所有的初始化都在读取LRC文件后开始!
    openFileDialog1.Filter = "音乐文件(*.mp3)(*.wma)|*.mp3;*.wma|所有文件(*.*)|*.*";

    if (openFileDialog1.ShowDialog() == DialogResult.OK)
    {

        axWindowsMediaPlayer1.URL = openFileDialog1.FileName;
        LRC myLRC = new LRC(openFileDialog1.FileName);

        时间对列表 = myLRC.得到时间对列表();

        //将所有的英文短语读取到一个listBox中
        短语列表=myLRC.得到短语列表();
        listBox短语列表.DataSource = 短语列表;

        //手动调用以便一开始就朗读!
        button全部播放.PerformClick();
        
        
        button上一句.Visible = true;
        button下一句.Visible = true;
        button播放.Visible = true;
        //一开始时钟是停止的
        timer1.Start();
    }
}

在窗体中我先定义了几个变量

private double 开始时间;
private double 结束时间;
private List<时间对> 时间对列表;
private List<string> 短语列表;

现在listBox中有了文本显示,当你点击listBox中的某一项时,程序就会得到那一句的时间对,使用listBox的一个SelectedIndexChanged事件来进行处理

image
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    //一开始加载listBox1的内容时时间对列表可能是空
    //这里假定获取到的时间对列表和短语列表其顺序是一致的
    //如果LRC不规范有可能造成不一致的现象发生
    //因为他们是分开获取的
    if (时间对列表 != null)
    {
        开始时间 = 时间对列表[listBox短语列表.SelectedIndex].开始时间;
        结束时间 = 时间对列表[listBox短语列表.SelectedIndex].结束时间;
    }
}
比如,当你点击第二行时,程序会取得listBox短语列表.SelectedIndex的值,为1,而因为我的时间对列表是一个List<时间对>,理论上他们是一一对应的,所以可以使用下标来访问,这样就可以取得相对应的开始和结束时间,

当点击播放的时候就会按照你选择的句子所在的时间来播放.

OK,核心的功能已经完成,下面咱们来处理一些控制上的细节.

待续...

posted @ 2011-04-26 12:17  爱玩的安哥  阅读(705)  评论(0编辑  收藏  举报