(原创)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,核心的功能已经完成,下面咱们来处理一些控制上的细节.

待续...

你可能感兴趣的:(C#)