• ベストアンサー

MIDIで音を出す

MIDIで音を出したいのですが、MIDIファイルを再生するわけではなく、VB上で音階などを指定し、リアルタイムでMIDIのメッセージを送りたいのです。 最終的にはPCのスピーカーで聞こえればOKです。 環境:VisualBasic 2008 Express Edition (2005も可) MIDIに関するAPIの情報として下記の様なものがありました。(MIDIファイルを再生する) http://homepage1.nifty.com/MADIA/vb/vb_bbs/200408/200408_04080077.html MIDIをリアルタイム出力 http://tokyo.cool.ne.jp/kanain/APIHTM/midiOut.html "リアルタイム"にMIDI出力したいということでお願いいます。 簡単にボタンを押したときに音が流れるソースですとありがたいです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

VB2005のコードです。 Public Class Form4 #Region "MIDI出力系WinAPI関数および定数" Declare Function midiOutOpen Lib "winmm.dll" ( _ ByRef lphMidiOut As Integer, ByVal uDeviceID As Integer, ByVal dwCallback As Integer, _ ByVal dwInstance As Integer, ByVal dwFlags As Integer) As Integer Declare Function midiOutShortMsg Lib "winmm.dll" ( _ ByVal hMidiOut As Integer, ByVal dwMsg As Integer) As Integer Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOut As Integer) As Integer Const MIDI_MAPPER As Integer = -1 Const MMSYSERR_NOERROR As Integer = 0 Const CALLBACK_NULL As Integer = &H0 #End Region ' MIDIデバイスID Private hDevice As Integer Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' MIDIマッパーを使用してMIDIデバイスを開く If midiOutOpen(hDevice, MIDI_MAPPER, 0, 0, CALLBACK_NULL) <> MMSYSERR_NOERROR Then MessageBox.Show("MIDIデバイスを開けませんでした。") hDevice = 0 Return End If End Sub Private Sub Form4_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed ' MIDIデバイスを閉じる If hDevice <> 0 Then midiOutClose(hDevice) End Sub ' マウスダウンで音を出す Private Sub Button1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseDown ' C3の音をベロシティ127でノートオン Dim msg As Byte() = New Byte() {&H90, 60, &H7F, 0} midiOutShortMsg(hDevice, BitConverter.ToInt32(msg, 0)) End Sub ' マウスアップで音を消す Private Sub Button1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseUp ' C3の音をノートオフ Dim msg As Byte() = New Byte() {&H80, 60, 0, 0} midiOutShortMsg(hDevice, BitConverter.ToInt32(msg, 0)) End Sub End Class デバイスのオープン・クローズに関しては音源選択や16CHを超えるインストゥルメントを使用しなければこのまま使っていて問題ないかと。要点はショートメッセージの組み立て方です。 ショートメッセージは3byteで指定します。ただ、APIでは4byteのIntegerで引き渡す必要があるので、 Dim msg As Byte() = New Byte() {&H90, 60, &H7F, 0} このように4byte分のバイト配列を生成し、BitConverterでIntegerに変換して送ります。メッセージの詳細はMIDI規格のサイトを参照してください。とりあえず音を出すなら&h9xでノートオン、&h8xでノートオフだけ覚えればなんとかなるかと。 Dim msg As Byte() = New Byte() {&H9x, 音階, &H7F, 0} ' ノートオン Dim msg As Byte() = New Byte() {&H8x, 音階, 0, 0} ' ノートオフ xにはMIDIチャンネルが入ります。0[ch01]~F[ch16]。9[ch10]はドラムセットです。 音階は60がC3に相当。(YAMAHAだとC4になるんでしたっけ…?) 第3バイトはノートオンのときはベロシティで&h00[0]~&h7f[127]を指定できます。ノートオフのときは常に0です。 MIDI音源のイニシャライズは行っていないので、直前の再生曲でVolが0とかになっていると音が出ないと思います。MIDIの初期化はロングメッセージの送信が必要になるので割愛します。

sakurav2
質問者

お礼

ありがとうございます! 無事MIDIで音を出すことが出来ました。 MIDIの音量は最初0で聞こえなかったようですが、自分であげればなんら問題はありませんでした。

その他の回答 (1)

  • DreamyCat
  • ベストアンサー率56% (295/524)
回答No.1

midiのしくみや操作はけっこう面倒ですよ。 せっかく探して 音の出し方とコードサンプルまで書かれているのに なぜ自分で試そうとしないのでしょう?  理解できないのなら必死で何回でも 読み返しましょう。

sakurav2
質問者

補足

回答ありがとうございます。 サンプルは試したのですが、MIDIデバイスのオープンが失敗し、このような質問をさせていただきました。

関連するQ&A