C#+Midi 類比各種樂器演奏

來源:互聯網
上載者:User

前段時間一時興起,參考各種資料文檔,各種程式碼。

連基本樂理知識都去瞭解了一些,弄清楚了什麼是十二平均律,什麼是半音、全音等等,終於弄出了這麼個東東,如:


其功能就是輸入“簡譜”就能演奏出優美的旋律。

“連音”奏法一直沒辦法實現,是較為遺憾的一個事。

程式中的簡譜也是有規則的:

  1. 以01234567為基本四分音符號,每個音符用英文逗號分開,如:1,2,3,4等,0代表休止符。
  2. 在音符前輸入:“+-#!” 加號表示此音升高八度,減號則降八度,井號升半音,歎號降半音。
  3. 在基本音符後加斜杠“/”表示此音時值減一半,半成8分音符號,雙斜杠則變成16分音符號。
  4. 可在以上基礎上再加入延音線“-”(減號),一個減號表示延長一倍時值,和簡譜裡用法一樣。
  5. 還可在以上基礎上再加入附點音符“.”(英文的句號),作用與簡譜一樣(允許雙附點)。

================================

程式中主要使用的Windows API函數

View Code

/// <summary>
/// 複置midi輸出
/// </summary>
/// <param name="handle"></param>
/// <returns></returns>
[DllImport("winmm.dll")]
protected static extern int midiOutReset(int handle);

/// <summary>
/// 向輸出連接埠發送資訊
/// </summary>
/// <param name="handle"></param>
/// <param name="message"></param>
/// <returns></returns>
[DllImport("winmm.dll")]
protected static extern int midiOutShortMsg(int handle, int message);
/// <summary>
/// 開啟midi輸出裝置
/// </summary>
/// <param name="handle"></param>
/// <param name="deviceID"></param>
/// <param name="proc"></param>
/// <param name="instance"></param>
/// <param name="flags"></param>
/// <returns></returns>
[DllImport("winmm.dll")]
protected static extern int midiOutOpen(ref int handle, int deviceID,
MidiOutProc proc, int instance, int flags);

/// <summary>
/// 關閉
/// </summary>
/// <param name="handle"></param>
/// <returns></returns>
[DllImport("winmm.dll")]
protected static extern int midiOutClose(int handle);

最核心的是向midi發送資訊的部份,要瞭解發送指令的格式,請參考百度百科。

當開啟裝置後就可以發送資訊了,用的是上面的midiOutShortMsg函數,以下是經過封裝的類比鍵盤按下或抬起的函數

private void Send(int iStatus, int iChannel, int iData1, int iData2)
{
midiOutShortMsg(hndle, iStatus | iChannel | (iData1 << 8) | (iData2 << 16));
}
/// <summary>
/// 鍵盤按下,預設為第一通道
/// </summary>
/// <param name="iData1"></param>
/// <param name="iData2"></param>
public void Note_On(int iData1, int iData2)
{
Note_On(0, iData1, iData2);
}
public void Note_On(int iChannel, int iData1, int iData2)
{
Send(0x90, iChannel, iData1, iData2);
}
public void Note_Off(int iData1, int iData2)
{
Note_Off(0, iData1, iData2);
}
public void Note_Off(int iChannel, int iData1, int iData2)
{
Send(0x80, iChannel, iData1, iData2);
}

注音看,0x90代表中的9代表鍵盤按下(開始發聲),0代表第一通道,共16個通道,就是說可以有16個樂器同時演奏,iCannel是通道號,iData1是音符代號,0為最低音,127是最高音,鋼琴的鍵盤中央C是60,iData2是音量或力度(我也不是很明白,一盤用100就行了)。這些資訊在Send函數中進行與運算、移位元運算後,得到諸如0x92 48 96 的資訊,表示通道3 開始彈奏C2

0x80就表示鍵盤抬起,作用就是停止發聲,一般我們都是用0x90 + 音量為0來實現靜音的(具體為什麼,忘了,好像是這樣的命令能有效減小mid檔案的儲存長度)

更多命令請百度或穀哥吧,現提供者及源碼下載。

簡譜播放器下載

原始碼下載(vs2010)

另外本程式引用一CodeProject中一個項目C# MIDI Toolkit部份Api聲明的代碼,此項目是一個鍵盤鋼琴程式,運行介面如下:

還有還在一個網站找到了一些VB寫的鋼琴鍵盤,也很有參考價值。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.