VBAで音声を再生する

ラボ

はじめに

 ExcelVBAで音声ファイルを再生させるには、いくつか方法がありますが、ここではWindowsAPIの mciSendString 関数を用いた方法を紹介します。

 今回紹介するのは上記のようなツールです。B2セル(結合していますが)にパス付のファイル名を保持して、各ボタンで音声ファイルの操作を行えるようにしています。

WindowsAPIの準備

 WindowsAPIの関数を使う場合は、最初に宣言が必要です。64bitと32bitでは、定義の仕方が違うので、どちらでも使えるように以下のように記述します。
 必ず標準モジュールの最上部に書くようにしてください。

'windowsAPI 宣言(Sleep,mciSendString)
#If VBA7 Then ' 64ビット
    Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
    Private Declare PtrSafe 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

#Else ' 32ビット
    Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Private Declare Function mciSendString Lib "winmm" Alias "mciSendStringA" _
    (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _
     ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long

#End If

 今回はサンプルコードで使用する Sleep関数の定義もしています。

音声ファイルを取得するコード

 今回は、B2セルに再生する音声ファイルを記述しておくようにします。再生・一時停止などを行うような場合は、ファイル名(もしくは別名)を保持するようにした方が良いでしょう。
 セルではなく、グローバル変数に保持しても良いでしょう。グローバル変数は、どのプロシージャよりも上部に書くようにします。

Sub 音声ファイルをセルにセット()
    Dim vfilename As Variant
    ChDir ThisWorkbook.Path      '開くフォルダを指定したい時
    vfilename = Application.GetOpenFilename("音声ファイル (*.wav;*.mid;*.mp3;*.wma)," & vbLf & "*.wav;*.mid;*.mp3;*.wma")
    If vfilename = False Then
        Range("B2") = ""
    Else
        Range("B2") = vfilename
    End If
    
End Sub

 ここではファイルダイアログを出してB2セルに音声ファイルを指定できるようにしています。
「開く」ボタンで呼ぶことにします。

テストコード

Sub testPlay()
    
    Dim file As String
    file = Range("B2").Value

    Call mciSendString("play " & file, "", 0, 0)    '再生(最後まで再生してしまう)
    
    Sleep 5000     '5秒待機
    
    Call mciSendString("pause " & file, "", 0, 0)     '一時停止
    
    Sleep 5000
    
    Call mciSendString("resume " & file, "", 0, 0)    '一時停止から再開
    
    Sleep 5000
    
    Call mciSendString("stop " & file, "", 0, 0)    '停止
    Call mciSendString("Close All", "", 0, 0)       '閉じる
End Sub

 mciSendStringの引数は、(”コマンド ファイル名”, “”, 0, 0)という書式になっています。第2引数から第4引数は、特殊な事をしないのであれば、決まった書き方で大丈夫です。

コマンドに関しては、OpenからCloseまでメモリーに常駐します。ちなみに上記コードでは、Openしていませんが、いきなり play としても音声再生できます。

 上記のコードを実行すると、再生して5秒後に一時停止し、5秒後に再開、5秒間再生して、停止して閉じます。
Open(play)した後は、メモリーに常駐するので、プロシージャを分けて操作する事ができます。

サンプルコード

'開く
Sub myOpenSoundFile()

    Call 音声ファイルをセルにセット
    
    Dim result As Long
    Dim file As String
    
    If Range("B2").Value = "" Then Exit Sub
    
    file = Range("B2").Value
    
    result = mciSendString("Open " & file, "", 0, 0)
    
    If result = 0 Then
        MsgBox "音声ファイルをメモリに読み込みました。"
    Else
        MsgBox "音声ファイルの読み込めませんでした。"
    End If
End Sub

'再生
Sub mySoundPlay()
    Dim file As String
    file = Range("B2").Value
    
    If file = "" Then Exit Sub

    Call mciSendString("Play " & file, "", 0, 0)
End Sub

'停止
Sub mySounStop()
    Dim file As String
    file = Range("B2").Value
    
    If file = "" Then Exit Sub
    
    Call mciSendString("stop " & file, "", 0, 0)
End Sub

'一時停止
Sub mySoundPause()
    Dim file As String
    file = Range("B2").Value
    
    If file = "" Then Exit Sub
    
    Call mciSendString("pause " & file, "", 0, 0)
End Sub

'再生再開
Sub mySoundResume()
    Dim file As String
    file = Range("B2").Value
    
    If file = "" Then Exit Sub
    Call mciSendString("resume " & file, "", 0, 0)
End Sub

'閉じる
Sub mySoundClose()
    Call mciSendString("Close All", "", 0, 0)
End Sub

 Open から Close までを1つずつのプロシージャにしています。Close 以外は file (ファイル名)が必要になっているのがわかると思います。

 色々実行してみるとわかると思いますが、Open しなくても Play で再生できますし、一時停止(pause)の後で、再開(resume)でなくても Play で再開する事ができるようです。

 実際にプログラムする時は、音声ファイルをいくつも開くとメモリーに常駐するので、必要なくなったら Close するようにした方が良いでしょう。

 もし効果音として音声ファイルを使用する場合は、Play ,Stop を繰り返し、Excelを閉じる際に Close すれば良いでしょう。

mp3再生の時に音が途切れる現象について

 このプログラムを作成する際、一部のmp3ファイルの再生で、音が途切れたり遅れたりする現象が起こりました。
原因を色々と探したのですが、一向に改善しませんでした。

 結局、「Bluetoothヘッドフォンを使っていたから」という何とも情けない原因でした!
(半日潰れました、、、)
 メディアプレイヤーなどではちゃんと再生されるのですが、mciSendStringを使ったプログラムなどではこういった現象が起こるようです。メディアプレイヤーとかはちゃんとしたデータにしてからスピーカーやヘッドフォンに送っているということでしょうか?詳細は不明です。

 Bluetoothヘッドフォンをやめて、有線のヘッドフォンやスピーカーなら問題なく再生されました。
(こういう情報がネットに上がっていないので不思議だと思ったんですよね、、、)

 同じような現象が起こったらBluetoothを疑ってみてくださいませ。

コメント

タイトルとURLをコピーしました