前段時間一時興起,參考各種資料文檔,各種程式碼。
連基本樂理知識都去瞭解了一些,弄清楚了什麼是十二平均律,什麼是半音、全音等等,終於弄出了這麼個東東,如:
其功能就是輸入“簡譜”就能演奏出優美的旋律。
“連音”奏法一直沒辦法實現,是較為遺憾的一個事。
程式中的簡譜也是有規則的:
- 以01234567為基本四分音符號,每個音符用英文逗號分開,如:1,2,3,4等,0代表休止符。
- 在音符前輸入:“+-#!” 加號表示此音升高八度,減號則降八度,井號升半音,歎號降半音。
- 在基本音符後加斜杠“/”表示此音時值減一半,半成8分音符號,雙斜杠則變成16分音符號。
- 可在以上基礎上再加入延音線“-”(減號),一個減號表示延長一倍時值,和簡譜裡用法一樣。
- 還可在以上基礎上再加入附點音符“.”(英文的句號),作用與簡譜一樣(允許雙附點)。
================================
程式中主要使用的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寫的鋼琴鍵盤,也很有參考價值。