エクセルで自動演奏できるようになりましたが、色々と苦労したので今後のための備忘録としてのブログラム解説です。
MIDI演奏のための宣言文
WindowAPIを使うための宣言文は4行あります。①最初の3行のDeclareはMIDIを使うための宣言なのでこのままコピーします。
Declare Function midiOutOpen Lib "winmm.dll" (ByRef lphMidiOut As Long, ByVal uDeviceID As Long, ByVal dwCallback As Long, ByVal dwInstance As Long, ByVal dwFlags As Long) As Long
Declare Function midiOutShortMsg Lib "winmm.dll" (ByVal hMidiOutDevice As Long, ByVal dwMsg As Long) As Long
Declare Function midiOutClose Lib "winmm.dll" (ByVal hMidiOutDevice As Long) As Long
②4行目のDeclareは音を鳴らす時間のために使ったコマンドの宣言ですが、他に方法があれば不要です。
Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
マクロ内定義
最初にマクロ内の定義を以下のように記述します。Dim hDevice, StrCont, Note, Tempo, i As Long
Dim StrLen As String
Const Timbre As Long = 1 '1~128 音色
Const Volume As Long = 127 '1~127
Const Channel As Long = 0 '0~15 9の場合はドラム
セル上にピアノ鍵盤を作画
鍵盤の形を指定して、以下、For~Nextで鍵盤を作画。前半は白い鍵盤用、後半は黒い鍵盤用の作画コマンドです。Range(Columns(3), Columns(60)).ColumnWidth = 1
Range("3:4").RowHeight = 30
For i = 0 To 16
Range(Cells(4, 3 + 3 * i), Cells(4, 5 + 3 * i)).MergeCells = True
Range(Cells(4, 3 + 3 * i), Cells(4, 5 + 3 * i)).Borders.LineStyle = xlContinuous
Next
For i = 5 To 50
Select Case i
Case 5, 11, 14, 20, 23, 26, 32, 35, 41, 44, 47
Range(Cells(3, i), Cells(3, i + 1)).Interior.Color = RGB(0, 0, 0)
End Select
Next
音楽データ用数列の処理
セル「B1」に入力されるデータ一度、文字列に変更してから不要な文字を削除します。小数点のないランダムな数字を入力すると、エクセルのセル仕様が「標準」の場合、自動で指数表示の数値として扱われてしまうことを回避する対策です。
Cells(1, 1) = "入力数列"
Cells(1, 2).Select
Selection.NumberFormatLocal = "@"
Cells(1, 2) = Replace(Cells(1, 2), ".", "")
Cells(1, 2) = Replace(Cells(1, 2), " ", "")
StrLen = Len(Cells(1, 2))
文字列の最後の部分にゴミが残る場合、演奏回数を1回減らす処理。
たまに、コピー&ペーストで持ってきた数列の最後にゴミが残ることがありました。そのままで使うとゴミの部分でエラーになります。
If Not IsNumeric(Mid(Cells(1, 2), StrLen, 1)) Then
StrLen = StrLen - 1
End If
セル「B2」のテンポに数値が設定していない時、初期値を設定する。
Cells(2, 1) = "テンポ"
If Cells(2, 2) > 30 And 230 > Cells(2, 2) Then
Else
Cells(2, 2) = 120
End If
Tempo = Cells(2, 2)
Range(Cells(1, 1), Cells(2, 2)).Font.Name = "Meiryo UI"
MIDI音源を操作
MIDI音源をアクティブ化
MIDIを使うときは必ず宣言する必要があります。Call midiOutOpen(hDevice, -1, 0, 0, 0)
数値を音階に割り当て
Note番号はMIDI音源の番号をそのまま、割り当てています。For i = 1 To StrLen
StrCont = Mid(Cells(1, 2), i, 1)
Select Case StrCont
Case 0 'シ
Note = 71
Case 1 'ド
Note = 72
Case 2 'レ
Note = 74
Case 3 'ミ
Note = 76
Case 4 'ファ
Note = 77
Case 5 'ソ
Note = 79
Case 6 'ラ
Note = 81
Case 7 'シ
Note = 83
Case 8 'ド
Note = 84
Case 9 'レ
Note = 86
End Select
アクティブ鍵盤表示
セルの塗りつぶしの色を指定しています。「Color」の代わりに「ColorIndex」で指定することもできます。黒い鍵盤は飾りです。Range(Cells(4, 3 + 3 * StrCont), Cells(4, 5 + 3 * StrCont)).Interior.Color = RGB(127, 127, 127)
MIDI音源にデータ送信
今回はVolumeは内部のデータを使い、固定になっています。Call midiOutShortMsg(hDevice, (Timbre - 1) * 256 + 192 + Channel)
Call midiOutShortMsg(hDevice, Volume * 65536 + Note * 256 + 144 + Channel)
Sleep 60000 / Tempo
演奏時間設定
この方法しか、私には上手く動かせませんでした。If i = StrLen Then
Sleep 60000 / Tempo
End If
鍵盤作画の初期化
作画は時間がかかるので何回か描いていると反応しなくなることがあります。なので一度、エクセルからOS制御に戻してから再度、エクセルに制御を戻して白く色塗りします。DoEvents
Range(Cells(4, 3), Cells(4, 54)).Interior.Color = RGB(255, 255, 255)
MIDI音源の切離し
これを送らないとエクセルが終了しても、MIDI動作がアクティブのまま、待機状態になります。Call midiOutClose(hDevice)
以上がMIDI音源操作の基本説明になります。
midiOutShortMsg()のパラメータを変えて送信すれば和音や色々な楽器や音を組み合わせることが簡単に実現できます。
VBA全体は『エクセルで「数列」を自動演奏してみる』でリンクできます。
続きは
>>