I found some code that uses API functions to play MIDI music at a French site. I adapted the code so it’s easy to use. Copy the code below and paste it into a VBA module.
Private Declare Function midiOutOpen Lib “winmm.dll” _
(lphMidiOut As Long, _
ByVal uDeviceID As Long, _
ByVal dwCallback As Long, _
ByVal dwInstance As Long, _
ByVal dwFlags As Long) As Long
Private Declare Function midiOutClose Lib “winmm.dll” _
(ByVal hMidiOut As Long) As Long
Private Declare Function midiOutShortMsg Lib “winmm.dll” _
(ByVal hMidiOut As Long, _
ByVal dwMsg As Long) As Long
Private Declare Sub Sleep Lib “Kernel32” (ByVal dwMilliseconds As Long)
Dim hMidiOut As Long
Public lanote As Long
Sub PlayMIDI(voiceNum, noteNum, Duration)
Dim Note As Long
On Error Resume Next
midiOutOpen hMidiOut, 0, 0, 0, 0
midiOutShortMsg hMidiOut, RGB(192, voiceNum – 1, 127)
lanote = 12 + CLng(noteNum)
Note = RGB(144, lanote, 127)
midiOutShortMsg hMidiOut, Note
The PlayMIDI Sub procedure accepts three arguments, and plays a single note. The argument are:
- voiceNum: A number from 1-128 that represents the instrument sound. Here’s a list of the MIDI voice numbers.
- noteNum: A number that indicates the note to play. For reference, C is 0, 12, 24, 36, etc. C# is 1, 13, 25, 37, etc.
- Duration: A number that indicates how long to play the note, in milliseconds (1,000 equals 1 second).
To play around with this, I set up a worksheet that has a 4-column list of notes. A lookup table provides the actual note letters for the values in column B. In the figure, I have it set up to generate random notes and durations. Then, a simple macro plays the song.
Then, a simple macro plays the song represented by the worksheet data.
Dim r As Long
For r = 2 To Application.CountA(Range(“A:A”))
Call PlayMIDI(Cells(r, 1), Cells(r, 2), Cells(r, 3))
By the way, I have no idea how this code works. Using the RGB function is a mystery to me. One final note. Avoid stopping the code by pressing Ctrl+Break. If you do that, you may get a stuck note that requires closing Excel.