エクセルのVBAで「mciSendString」コマンドを使ってWAVEファイルを再生してみる




Visual Basicと言っても一般のVBとエクセルにあるVBAでは少し違うところがります。ネットで調べてVBのコードをそのままコピーしても動かないことがたまにあります。

でもエクセルでプログラムが簡単に作れると言うところが気に入って色々な使い方に応用しています。

エクセルではユーザーフォームとmciSendStringコマンドを使うとちょっとした汎用ぽいソフトが作れてしまいます。エクセルでWAVEファイルを再生してどういう意味があるかわかりませんが試してみました(笑)

Windows APIを使うので、取り合えず、module1の先頭に以下を宣言します。

Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long

Public FileName As String
Dim str As String * 8


次にファイルを操作するためのマクロ命令を以下のように準備します。

①再生
Sub PlaySound(FileName As String)
    Call mciSendString("play " & FileName, "", 0, 0)
End Sub

②停止
Sub StopSound(FileName As String)
    Call mciSendString("close " & FileName, "", 0, 0)
End Sub

ファイルを指定しないで停止する場合は
  Call mciSendString("close all", "", 0, 0)

③一時停止
Sub PauseSound(FileName As String)
    Call mciSendString("pause " & FileName, "", 0, 0)
End Sub

④一時停止解除
Sub ResumeSound(FileName As String)
    Call mciSendString("resume " & FileName, "", 0, 0)
End Sub

⑤演奏環境設定 (⑥のために必要)
Sub OpenSound(FileName As String)
        Call mciSendString("open "" & FileName", str, Len(str), 0)
End Sub

⑥演奏状態検出
Sub StatusSound(FileName As String)
    Call mciSendString("status " & FileName & "" & " mode", str, Len(str), 0)
End Sub





基本はそれぞれの操作をユーザーフォーム上の各コマンドボタンで呼び出せば音楽プレーヤーぽく動作します。

以下は試しにSoundWave.wavファイルを演奏するときのVBAコードです。

****************************************
****************************************

Sub sound_test()
        
    FileName = ThisWorkbook.Path & "\" & SoundWave.wav
’ 最初の[ThisWorkbook.Path & "\" & ]はエクセルファイルがあるディレクトリを自動的に指定します。

    Call mciSendString("close all", "", 0, 0)
’ すべてのファイルを一度、停止します。

    Call OpenSound(FileName)
' 演奏状態を確認するための準備です。

    Call PlaySound(FileName)
' 演奏を開始します。
  
    Do While InStr(str, "stopped") = 0
        Call StatusSound(FileName)
    Loop
' 演奏状態を確認し終わっている場合は以下の命令を実行します。
  
    Call StopSound(FileName)
' 演奏停止します。

    MsgBox "end of sound"
' 演奏が終ったことを表示します。

End Sub

PlaySound()は複数のファイルを同時再生できます。なので完全に停止しておかないと複数の局が同時に流れてきてしまいます(笑)

今回のマクロは多分MP3ファイルも再生できると思いますが、確認はしていません。


ここまでで当初の目的は達したのですが、ボリューム機能も追加したくなりました。しかし、ネットで調べながら、色々試してみたのですが、「volume」コマンドは残念ながら、mciSendStringコマンドでは機能しませんでした。

そこでwaveOutSetVolumeコマンドで設定することにしました。

最初に宣言文を二つ追加します。今回「fadeInOut」マクロを試したので、時間関数としてsleep関数を使うために2行目の"kernel32" が必要になっていますが、音量制御だけなら不要です。

'Windows APIを使うための宣言文
Private Declare Function waveOutSetVolume Lib "winmm.dll" (ByVal uDeviceID As Long, ByVal dwVolume As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)

'右チャンネル 左チャンネルは最大127~最小0の範囲で設定
Sub PlaySound(FileName As String)
    Call mciSendString("close all", "", 0, 0)
    Call waveOutSetVolume(0, 127 * &H1000000 + 127 * &H100) 
    Call mciSendString("play " & FileName, "", 0, 0)
End Sub

Sub ResumeSound(FileName As String)
    Call waveOutSetVolume(0, 127 * &H1000000 + 127 * &H100) 
    Call mciSendString("resume " & FileName, "", 0, 0)
End Sub

waveOutSetVolume無しの場合は最大値127が設定されるようです。但しこの最大値はデバイスプレーヤーの最大値でスピーカーの最大値ではありません。上記のように音声再生用マクロも変更しておかないと音が出なくなってしまうことがあるので注意が必要です。

フェードイン、フェードアウトでSleep関数を使った理由はmsの設定ができるようにするためです。最初の値はフェード期間をms単位で設定、最後の値はゼロ以上でフェードアウト、それ以外はフェードインになります。

Sub WaveFade(ByVal Time_ms, ByVal InOut)
    Dim AStep As Integer
    For i = 0 To 10
        If InOut > 0 Then
            AStep = Int(127 / 10) * (10 - i)
        Else
            AStep = Int(127 / 10) * i
        End If
        
        Call waveOutSetVolume(0, AStep * &H100 + AStep * &H1000000)
        DoEvents
        Call Sleep(Time_ms / 10)
    Next i

End Sub

これで一通りのwaveの再生操作ができるようになると思います。但し、waveOutSetVolumeは見てわかるようにwaveファイルしか動作しません。