有了單個的英文字串,咱們就可以得到整個的英文字串數組,如下:
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檔案後才能開始控制,所以要先關閉.
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事件來進行處理
private void listBox1_SelectedIndexChanged(object sender, EventArgs e){ //一開始載入listBox1的內容時時間對列表可能是空 //這裡假定擷取到的時間對列表和片語清單其順序是一致的 //如果LRC不規範有可能造成不一致的現象發生 //因為他們是分開擷取的 if (時間對列表 != null) { 開始時間 = 時間對列表[listBox片語清單.SelectedIndex].開始時間; 結束時間 = 時間對列表[listBox片語清單.SelectedIndex].結束時間; }}比如,當你點擊第二行時,程式會取得listBox片語清單.SelectedIndex的值,為1,而因為我的時間對列表是一個List<時間對>,理論上他們是一一對應的,所以可以使用下標來訪問,這樣就可以取得相對應的開始和結束時間,
當點擊播放的時候就會按照你選擇的句子所在的時間來播放.
OK,核心的功能已經完成,下面咱們來處理一些控制上的細節.
待續...