VBAからGDI+を使う資料集
inet上の達人の方々から御教示いただいたコードを少しアレンジさせてもらっています(切り貼りとも言います)。
  1. ホーム
  2. Other
  3. キー操作を記録し、同期してBeep音をON/OFFする


キー操作をリアルタイムにCSVに記録し、併せてキーを押している間はBeep音を出す

キー操作のログ(押した、離した時刻)をリアルタイムでCSVファイルに記録します。
また、キーを押している間はBeep音を出します。
QAサイトで回答したものの使い途がよく分かりませんが、Beep音のWaveファイル生成にまで手を出してみました。
MIDを左辺に置く文字列操作を覚えたので使ってみましたが、どうせ最後に書き込むなら配列に収納していく方が速いかもしれません。


☆ここはおまけ
単一周波数(正弦波)のWaveファイルを生成します

'コードの出典
'http://www.gizcollabo.jp/vbtomo/boards/vbhajikari_spread_3403.html
'正弦波のデータ生成部のみアレンジさせていただいております。
'   ofs Data
'   +0  "RIFF":=&h46464952&
'   +4  <続くデータのバイト数>
'   +8  "WAVE":=&h45564157&
'   +12 "fmt ":=&h20746d66&
'   +16 Len(WAVEFORMAT_my):=16
'   +20 <WAVEFORMAT_myの実体>
'   +36 "data":=&h61746164&
'   +40 <波形データのバイト数>
'   +44 <波形データ>
Private Const WAVE_FORMAT_PCM = 1
Private Const hdr_RIFF      As Long = &H46464952
Private Const hdr_WAVE      As Long = &H45564157
Private Const hdr_fmt       As Long = &H20746D66
Private Const hdr_data      As Long = &H61746164
Private Const WAVEFORMAT_myLen As Long = 16

Private Type WAVEFORMAT_my
        wFormatTag          As Integer  'WAVE_FORMAT_PCMを利用
        nChannels           As Integer  'MONO Channelにする
        nSamplesPerSec      As Long     'Sample rate, in samples per second.
        nAvgBytesPerSec     As Long     'For example, 16-bit stereo at 44.1 kHz has an average data rate of 176,400 bytes per second
                                    '=<量子化数/8*サンプリングレート*チャンネル数>?
        nBlockAlign         As Integer  'For example, the block alignment for 16-bit stereo PCM is 4 bytes
                                    '=<量子化数/8*チャンネル数>?
        wBitsPerSample      As Integer  '量子化数
End Type

'メインルーチン

Sub test0()
  makeWave 659.255114, ThisWorkbook.Path & "\" & "sample.wav", 5
End Sub

'freq Waveファイルを作成する単音の周波数Hz
'filePath出力するWaveのファイルフルパス(拡張子 .wavもつける事)
'SamSecLen 出力する音の長さ(sec)

Private Sub makeWave(freq As Double, filePath As String, Optional SamSecLen As Double)
    Const Gain              As Long = 30000     'ほぼ最大のゲイン
    Const pi = 3.1415926
    
    Dim i                   As Long             '一般変数
    Dim ff                  As Integer          'ファイルナンバー用
'    Dim SamSecLen           As Double           'サンプル時間(秒)
    Dim wf                  As WAVEFORMAT_my    'WAVEFORMAT_myの実体
    Dim sintable(0 To 359)  As Integer          'サインテーブル
    Dim WaveDataLen         As Long             '波形データ長
    Dim WaveData()          As Integer          '実波形データ
    Dim dataArray() As Variant
    
    With wf
        .wBitsPerSample = 16
        .wFormatTag = WAVE_FORMAT_PCM
        .nChannels = 1
        .nSamplesPerSec = 44.1 * 1000   '44.1kHz
        .nAvgBytesPerSec = .wBitsPerSample / 8 * .nSamplesPerSec * .nChannels
        .nBlockAlign = .wBitsPerSample / 8 * .nChannels
    End With
    
    'サンプル時間の初期値
    If IsMissing(SamSecLen) Then
        SamSecLen = 1
    End If
    
    'サンプル時間を収められるWaveDataを作る
    WaveDataLen = wf.nSamplesPerSec * SamSecLen
    ReDim WaveData(1 To WaveDataLen)
    
    'WaveDataを決定する
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    For i = 1 To WaveDataLen
         WaveData(i) = Gain * Sin(2 * pi * freq * (1 / wf.nSamplesPerSec) * i)
    Next i
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
    
    'データをファイルに書き込む
    ff = FreeFile
    Open filePath For Binary As ff
        Put #ff, 1, hdr_RIFF        '   +0  "RIFF":=&h46464952&
        Put #ff, , 0&               '   +4  <続くデータのバイト数>
        Put #ff, , hdr_WAVE         '   +8  "WAVE":=&h45564157&
        Put #ff, , hdr_fmt          '   +12 "fmt ":=&h20746d66&
        Put #ff, , WAVEFORMAT_myLen '   +16 Len(WAVEFORMAT_my):=16
        Put #ff, , wf               '   +20 <WAVEFORMAT_myの実体>
        Put #ff, , hdr_data         '   +36 "data":=&h61746164&
        Put #ff, , WaveDataLen * 2  '   +40 <波形データのバイト数>
        Put #ff, , WaveData         '   +44 <波形データ>
        '最後に +4 の<続くデータのバイト数>を書き込む
        Put #ff, 1 + 4, Seek(ff) - 4 - 1
    Close ff
End Sub

☆標準モジュール
'空のUserFormを表示し、スペースキーの操作に同期してBeep音を奏で、キー操作を記録します。フォームを閉じるときCSVに保存します。
Sub test()
  UserForm1.Show
End Sub

☆クラスモジュール
Public Event keyPushed(ByVal upEdge As Boolean)

Private Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Const VK_SPACE = &H20 '[Space]
Private myStopFlag As Boolean

Public Property Let stopFlag(newStopFlag As Boolean)
If newStopFlag Then myStopFlag = True
End Property

Public Sub start()
Dim MyKeyState As Long
Dim previousState As Long
Dim testFlag As Long
Do
MyKeyState = GetAsyncKeyState(VK_SPACE)
If MyKeyState <> &H0 And previousState = &H0 Then
RaiseEvent keyPushed(True)
Else
If MyKeyState = &H0 And previousState <> &H0 Then
RaiseEvent keyPushed(False)
Else
testFlag = 0
End If
End If
previousState = MyKeyState
' Call Sleep(10)
DoEvents
Loop Until myStopFlag
End Sub

☆UserForm1モジュール
Private WithEvents keyCheck As keyCheckClass
Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" ( _
ByRef pszSound As Byte, _
ByVal hmod As Long, _
ByVal fdwSound As Long _
) As Long
'PlaySound(0,0,0)では止まらないので苦肉の策
Private Declare Function PlaySound2 Lib "winmm.dll" Alias "PlaySoundA" _
(ByVal pszSound As String, ByVal hmod As Long, ByVal fdwSound As Long) As Long

Private Const SND_ASYNC = &H1
Private Const SND_MEMORY = &H4
Private Const SND_LOOP = &H8

Dim BufSndTest() As Byte
Dim buf As String * 50000 '2^16文字が最大か
Dim pos As Long

Private Sub keyCheck_keyPushed(ByVal upEdge As Boolean)
  If upEdge Then
    startSound
    Mid(buf, pos, 13) = "1,&H" & Right("0000000" & Hex(GetTickCount), 7) & vbCrLf
    pos = pos + 13
  Else
    StopSound
    Mid(buf, pos, 13) = "0,&H" & Right("0000000" & Hex(GetTickCount), 7) & vbCrLf
    pos = pos + 13
  End If
End Sub

Private Sub UserForm_Initialize()
Set keyCheck = New keyCheckClass
pos = 1
End Sub

Private Sub UserForm_Activate()
  ReadSoundBuffer
  keyCheck.start
End Sub

Private Sub UserForm_Terminate()
  Dim buf2 As String
  Dim FSO As Object
  
  On Error GoTo errHandler
  keyCheck.stopFlag = True
  Set keyCheck = Nothing
  buf2 = Left(buf, pos - 3) '最後のvbCrLfも削除
  '最後にまとめてファイルに書き出す
  Set FSO = CreateObject("Scripting.FileSystemObject")
  With FSO.CreateTextFile(ThisWorkbook.Path & "\Sample.csv")
  .Write buf2
  .Close
  End With
  Set FSO = Nothing
errHandler:
  If Err.Number <> 0 Then MsgBox Err.Number & ":" & Err.Description
End Sub

Private Function ReadSoundBuffer()
    Dim WrkSndFile As String
    Dim WrkNumber As Long
    
    WrkSndFile = ThisWorkbook.Path & "\sample.wav"
    WrkNumber = FreeFile()
    Open WrkSndFile For Binary As WrkNumber
    ReDim BufSndTest(LOF(WrkNumber))
    Get WrkNumber, , BufSndTest
    Close WrkNumber
End Function

Private Sub startSound()
  PlaySound BufSndTest(0), 0, SND_ASYNC + SND_MEMORY + SND_LOOP
End Sub

Private Sub StopSound()
  Call PlaySound2(vbNullString, 0, 0)
End Sub