每台 PC 內建一支「16 人樂隊」——符合 MIDI(樂器數位介面)標準的電子音樂合成器,雖然常被忽視,卻是 Windows 多媒體功能中極具潛力的組件。.NET Framework 本身不支援 MIDI,但在 WPF 或 WinForms 中可透過 P/Invoke 或外部庫(如 NAudio)來存取。
CodePlex 上的 NAudio 聲音庫提供了完整的 MIDI 支援。本文使用 NAudio 1.3.8 版,可從 codeplex.com/naudio 下載庫及原始碼。專案需引用 NAudio.dll 並引入命名空間:
using NAudio.Midi;
播放 1 秒長的中央 C(鋼琴音色):
MidiOut midiOut = new MidiOut(0);
midiOut.Send(MidiMessage.StartNote(60, 127, 0).RawData);
Thread.Sleep(1000);
midiOut.Send(MidiMessage.StopNote(60, 0, 0).RawData);
Thread.Sleep(1000);
midiOut.Close();
midiOut.Dispose();
MidiOut(0):選擇 ID 為 0 的預設 MIDI 合成器StartNote(60, 127, 0):音符 60(中央 C),力度 127(最大),通道 0Thread.Sleep:簡易計時(UI 執行緒中應避免使用)同時發送多個 StartNote 即可實現複音。C 大調和弦範例:
midiOut.Send(MidiMessage.StartNote(60, 127, 0).RawData); // C4
midiOut.Send(MidiMessage.StartNote(64, 127, 0).RawData); // E4
midiOut.Send(MidiMessage.StartNote(67, 127, 0).RawData); // G4
midiOut.Send(MidiMessage.StartNote(72, 127, 0).RawData); // C5
// ...對應的 StopNote
MidiMessage.ChangePatch(47, 0) 切換至定音鼓(General MIDI 標準中第 48 號樂器,從 0 起算)MidiMessage.StartNote(56, 127, 9) 播放鈴鐺聲音為貼合 WPF/XAML 風格,作者設計了 MIDI 字串 格式,可直接在 XAML 嵌入樂曲片段:
C4、C#3、Eb4(大寫 A-G + 升降號 + 八度號)R1/4(四分音符)、/8(八分音符,分子預設 1)-3/16(以減號前綴區分)I40(小提琴)、V64(音量)、T120(節拍 120 BPM)(C4 E4 G4 C5)| 分隔,如 T100 I56 G4 ... | T200 I40 ...P 標記,如 P56(鈴鐺)經典「Charge!」號角曲範例:
"T100 I56 G4 /12 C5 E5 G5 3/16 -3/32 E5 /16 G5 /2"
Petzold.Midi 庫提供 MidiStringPlayer 類別(繼承 FrameworkElement),可嵌入 XAML 視覺樹:
<midi:MidiStringPlayer Name="player"
PlayOnLoad="True"
MidiString="{Binding ElementName=chargeButton, Path=Tag}" />
屬性與事件:
MidiString:樂曲字串PlayOnLoad:載入時自動播放Play()/Stop():控制播放IsPlaying:唯讀狀態Ended:播放完成事件Failed:語法錯誤事件(含位移與說明)目前使用 DispatcherTimer(UI 執行緒,約 60Hz 精度),簡單音樂足夠,複雜節奏可能不準。NAudio 尚未封裝 Win32 高解析度 MIDI 計時器。範例包含兩個 WPF 程式: