エクセルでMIDI音源を制御するマクロ




エクセルで自動演奏できるようになりましたが、色々と苦労したので今後のための備忘録としてのブログラム解説です。






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全体は『エクセルで「数列」を自動演奏してみる』でリンクできます。




続きは
>>