この人頭いいなと思ったエピソード

MIDIで音を出したいのですが、MIDIファイルを再生するわけではなく、VB上で音階などを指定し、リアルタイムでMIDIのメッセージを送りたいのです。

最終的にはPCのスピーカーで聞こえればOKです。

環境:VisualBasic 2008 Express Edition (2005も可)

MIDIに関するAPIの情報として下記の様なものがありました。(MIDIファイルを再生する)
http://homepage1.nifty.com/MADIA/vb/vb_bbs/20040 …

MIDIをリアルタイム出力
http://tokyo.cool.ne.jp/kanain/APIHTM/midiOut.html

"リアルタイム"にMIDI出力したいということでお願いいます。
簡単にボタンを押したときに音が流れるソースですとありがたいです。

A 回答 (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の初期化はロングメッセージの送信が必要になるので割愛します。
    • good
    • 2
この回答へのお礼

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

お礼日時:2009/11/11 07:32

midiのしくみや操作はけっこう面倒ですよ。


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

この回答への補足

回答ありがとうございます。

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

補足日時:2009/11/11 07:29
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報