GEN MUTO'S HOMEPAGE  エクセル大事典  エクセルVBAを極める

エクセルExcel大事典 エクセル大事典TOPページへ
 ■ エクセルVBAを極める−VBAスーパーテクニック
  エクセルで音を鳴らそう!1
 
■ エクセルでも音が出せる?

ゲームプログラミングにおいて効果音やBGMの使用はもはや必須ですが、業務アプリケーションにおいてもサウンドの使用は様々な利点があります。

そのもっとも効果的な使用法は、内部処理の進捗やイベントを「音」で知らせることでしょう。
たとえば長時間のバッチ処理の終了を音で知らせたり、タスクバーに常駐するソフトがイベントの発生(メールが届いた、エラーが発生した、等)を音で知らせる場合です。

マルチタスクが当たり前になった現在のWindowOSの様々な局面で「音」の使用はユーザーの利便性を高めます。

エクセルVBAでも音が出せるのでしょうか?
大丈夫です。API関数からDirectXを使用したものまで、さまざまな効果音・BGMの再生方法が可能です。

■ PlaySound関数で音を鳴らしてみよう!

最も簡単にWAVEファイルの再生を行う方法がPlaySoundです。
ところでこのPlaySoundはExcelVBAの機能ではありません。Windowsのもつwinmm.dllというライブラリの中にあるAPI関数の名前です。APIはApplication Programming Interfaceの略で、VBAだけでなく様々な開発言語から呼び出せるOSを制御するためにWindowsが用意した標準のインターフェイスです。

' モジュール宣言部に記述ここから −−−−−−−−−−−−−−−−−−−−−−−−−−
Public Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" ( _
    ByVal pszSound As String, _
    ByVal hmod As Long, _
    ByVal fdwSound As Long _
    ) As Long
Public Const SND_ASYNC = &H1
' モジュール宣言部に記述ここまで −−−−−−−−−−−−−−−−−−−−−−−−−−

Public Sub test()
Dim WrkSndFile As String
  WrkSndFile = ThisWorkbook.Path & "\test.wav"
  PlaySound WrkSndFile, 0, SND_ASYNC
End Sub

これで実行ブックと同一フォルダにあるtest.wavが再生できます。どうやって再生しているのか説明していきましょう。
Declare Function〜 DLL内にある関数を呼び出すことを宣言しています。PlaySound Lib "winmm.dll" は使用するPlaySound関数がwinmm.dllライブラリ内にあることを明示しています。
引数と定数の定義はこちらを参照してください。
http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/jpmltimd/html/_win32_playsound.asp

testプロシージャを実行すると、まずFileName変数に再生するWaveファイルのフルパスが格納されます。次に
PlaySound FileName, 0, SND_ASYNC でWaveファイルを呼び出し非同期再生を行っています。
SND_ASYNC定数が非同期再生の指定になります。
Public Const SND_ASYNC = &H1 の部分を
Public Const SND_SYNC = &H0 とSND_SYNC定数を定義、
PlaySound WrkSndFile, 0, SND_SYNC と指定してやることで同期再生になります。
同期・非同期の違いですが、非同期再生の場合Waveファイルの再生中でも他の操作を受け付けます。同期再生を指定するとWaveファイルの再生が終わるまでマクロ、その他の動作を一切受け付けなくなります。

通常は上記のやり方で十分なんですが、ゲームなどで頻繁に効果音を再生する場合、ファイルからの読み取りでは対応しきれない場合があります。このときプログラムが一時的に停止したり、音再生が出遅れたりします。
少し改良してメモリ上のバッファから再生できるようにしてみましょう。

' モジュール宣言部に記述ここから −−−−−−−−−−−−−−−−−−−−−−−−−−
Public Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" ( _
    ByRef pszSound As Byte, _
    ByVal hmod As Long, _
    ByVal fdwSound As Long _
    ) As Long
Public Const SND_ASYNC = &H1
Public Const SND_MEMORY = &H4
Public BufSndTest() As Byte
' モジュール宣言部に記述ここまで −−−−−−−−−−−−−−−−−−−−−−−−−−

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

Public Sub test()
  Call ReadSoundBuffer
  PlaySound BufSndTest(0), 0, SND_ASYNC + SND_MEMORY
End Sub

通常はReadSoundBufferの処理は、ブックもしくはフォームを開いた時点で一度実行しておけばOKです。
BufSndTest 動的配列にtest.wavの中身がバイナリで格納されます。pszSound 第一引数がByte型の参照渡しに変更されていることに注目してください。
第一引数には再生するWaveファイルのバイト列を渡してやる必要があります。値渡しではせっかくメモリに格納したバイナリを別領域に値として格納しなおしてしまいます。
変数(BufSndTest)に格納されたバイト配列の、あくまでポインタを渡すために参照渡しを指定しています。

ReadSoundBufferの処理ですが、test.wavをバイナリとして読み込んだあとLOF関数でサイズを調べ、BufSndTestの配列数を再定義しています。あとは、定義しなおしたByte型配列の中にバイナリを格納していきます。
このBufSndTestはグローバルで定義していますので、プログラムのあらゆるところから呼び出しが可能です。

PlaySound BufSndTest(0), 0, SND_ASYNC + SND_MEMORY BufSndTest配列の先頭ポインタを渡しています。fdwSound(再生フラグ)は非同期(SND_ASYNC)にメモリ再生(SND_MEMORY)のフラグが追加されています。

このPlaySound関数は大変扱いやすく、もっとも簡単にサウンド機能を提供してくれるのですが、いくつか制限もあります。
たとえば、サウンドの停止にはpszSound引数にNullを指定します。(pszSoundがByte型の場合は0)
これは常に再生の停止を意味し、いわゆる一時停止はできません。(次回再生時は常にファイルの先頭からになります)
さらに一度に鳴らすことのできるWaveファイルは一つまでで、同時に複数のWaveファイルを鳴らすことができません。
(再生の途中で他の音を鳴らそうとすると先に鳴っていたWaveは中断されます)

これらの不便を一気に解消してくれるのがDirectXによる再生法です。
しかもPlaySoundでは鳴らせなかったMidiやMP3ファイルの再生も可能です。



DirectXでWaveファイルを再生してみよう!

さあ、DirectXで音を鳴らしてみましょう。DirectXにはバージョンがありますが今回はDirectXの8を使って説明したいと思います。まずVBEのツール>参照設定で
"DirectX 8 for Visual Basic Type Library"にチェックを入れてください。
これで準備OKです。それでは先ほどのコードを早速書き換えてみましょう。



' モジュール宣言部に記述ここから −−−−−−−−−−−−−−−−−−−−−−−−−−
Public Declare Function FindWindow Lib "User32.dll" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String _
    ) As Long
Dim DX8 As New DirectX8
Dim DS8 As DirectSound8
Dim BufSndTest As DirectSoundSecondaryBuffer8
Dim BufDsc As DSBUFFERDESC
Dim MyWindow As Long
Dim WrkSndFile As String
' モジュール宣言部に記述ここまで −−−−−−−−−−−−−−−−−−−−−−−−−−

Public Sub ReadSoundBuffer()
  MyWindow = FindWindow("XLMAIN", Application.Caption)
  WrkSndFile = ThisWorkbook.Path & "\test.wav"
  Set DS8 = DX8.DirectSoundCreate(vbNullString)
    DS8.SetCooperativeLevel Hwnd:=MyWindow, Level:=DSSCL_PRIORITY
  Set BufSndTest = DS8.CreateSoundBufferFromFile( _
    Filename:=WrkSndFile, _
     bufferDesc:=BufDsc _
    )
End Sub

Public Sub test()
  Call ReadSoundBuffer
  BufSndTest.Play DSBPLAY_DEFAULT
  Do
    DoEvents
  Loop Until BufSndTest.GetStatus = 0
End Sub

こんな感じになります。まず最初のAPI関数、FindWindowですがExcelのウィンドウハンドルを取得するために必要です。DirectX(正確にはDirectSound8オブジェクト)は再生する前に必ずアプリケーション協調レベルを設定しなければなりません。このとき、Excelのハンドルを渡す必要があるのでFindWindowが必要になるわけです。
Dim DX8 As New DirectX8 まずDirectX8の新しいオブジェクトを宣言します。
次にDirectXの主要なコンポーネントオブジェクトであるDirectSound8のオブジェクトを作成します。
このときは DirectX8.DirectSoundCreate の戻り値を代入します。
Dim DS8 As DirectSound8
Set DS8 = DX8.DirectSoundCreate(vbNullString)

さて、作成したDS8オブジェクトを初期化します。このときExcelのハンドルと協調レベルDSSCL_PRIORITY(優先的に使用する)を設定します。
Set BufSndTest = ここでサウンドバッファにWaveファイルを読み込みます。CreateSoundBufferFromFileというメソッドがDirectSound8には用意されています。ここで指定したファイルWrkSndFileを作成されたバッファにロードしています。bufferDescに指定されているBufDscはDSBUFFERDESC構造体でWaveフォーマットやエフェクトなどの指定を行うことが可能です。
こうしてBufSndTest内にサウンドバッファがセットされました。

音の再生はtestプロシージャからおこなっている、
BufSndTest.Play DSBPLAY_DEFAULT の部分です。DSBPLAY_DEFAULT はバッファの再生方法の指定で、再生カーソルの位置からバッファの最後までを再生する指定になっています。

Do〜LoopでBufSndTest.GetStatus = 0 の間ループさせているのはプロシージャが終了してしまうと再生が終了してしまうからです。GetStatusが0 のとき再生が終了していますので、それまで待ってプロシージャを終了させるようにしています。

次回は、DirectXを使用したMIDIサウンドの再生とWAVE、MIDIを組み合わせた多重再生についてご紹介したいと思います。

 

>> 次の話にすすむ


サイト内検索ができます

Microsoft Most Valuable Professional

Microsoft MVP Excel
武藤 玄 プロフィール
 

■■■ 執筆した書籍 ■■■
 

EXCEL VBA 業務自動化
 

Excel VBA を5日でマスターする本
 

仕事を速くする Excel VBA 入門
 

Excel VBAと業務改善のポイントがわかる本
 

Access VBA ベーシック スタンダード
 

Excel VBA アクションゲーム作成入門
 

■■■ 連載中の記事 ■■■
 

Excel VBAで業務改善!
 

実務で使うExcel VBA
 


TOPページ


■ エクセルVBA超入門

 ・9ステップで"Hello World!"
  からオブジェクト指向まで!
  1."Hello World!"を表示しよう
  2.基本はデータの入出力
  3.繰り返し処理
  4.シートで簡易データベース
  5.名前をつけよう
  6.構造化プログラムに挑戦
  7.構造体を使ってみよう
  8.フォームを使ってみよう
  9.オブジェクト指向に挑戦

■ エクセルVBA中級編

 ・VBAでいろんなテクニック
  変数・関数のスコープ
  引数の参照方法を明示
  配列の中身を一気に複写
  識別子がよいコードを作る
  データ定義型をもっと知ろう
  定数と列挙型を活用しよう
  エラー処理の重要性1
  エラー処理の重要性2
  いろいろな条件分岐
  いろいろな繰り返し処理
  演算子について知ろう
  文字列操作 連結 変換 置換
  文字列操作 検索 比較 書式
  日付操作関数を知ろう
  数値操作・評価・その他関数
  並び替えソートをマスター
  いろいろな検索をマスター
  VBEditorを使いこなそう
  マクロの記録を活用しよう1
  マクロの記録を活用しよう2
  VBAからVBEを操作しよう1
  VBAからVBEを操作しよう2
  VBAからVBEを操作しよう3
 ・ワークシートを使いこなす
  セルの参照をマスターしよう
  セルの選択をマスターしよう
  セルの操作をマスターしよう
  セルの書式設定をマスターしよう
  行・列の操作をマスターしよう
  シートの参照をマスターしよう
  シートの操作をマスターしよう
  ブックの操作をマスターしよう
  ウィンドウの操作をマスターしよう
  イベントプロシージャを活用しよう
  ワークシートを印刷しよう1
  ワークシートを印刷しよう2
  音声(読み上げ)機能を操作しよう
  グラフを操作しよう
 ・ユーザーフォームを使いこなす
  ユーザーフォームを使おう
  UserFormsオブジェクト
  Labelコントロール
  TextBoxコントロール
  ComboBoxコントロール
  ListBoxコントロール
  CheckBoxコントロール
  OptionButtonコントロール
  ToggleButtonコントロール
  CommandButtonコントロール
  ScrollBarコントロール
  SpinButtonコントロール
 ・VBA関数の一覧
  Aから始まる関数の一覧
  Cから始まる関数の一覧
  Dから始まる関数の一覧
  Eから始まる関数の一覧
  Fから始まる関数の一覧
  Gから始まる関数の一覧
 
■ エクセルVBAを極める
 VBAスーパーテクニック
 
 ・データベースへ接続してみよう!
  CSVファイルへの接続
  ワークシートへの接続
  mdbファイルへの接続
  SQL Serverへの接続
  ADOレコードセットの操作1
  ADOレコードセットの操作2
 ・ファイルを操作してみよう!
  FileSystemObjectの操作
  Drive File Folderの操作
  TextStream ダイアログ
  ステートメントでファイル操作1
  ステートメントでファイル操作2
 ・他アプリと連携してみよう!
  ActiveXオートメーションの操作
 ・ゲーム技でマクロを超える
  エクセルで音を鳴らす1
  エクセルで音を鳴らす2  
  スクリーン座標を取得
  様々なイベント取得
  リボンUIを制御しよう1
  リボンUIを制御しよう2
  シート上でアニメを動かそう
 
■ 一歩上行くエクセル
 基本操作の完全マスター!

 
 ・あなたはいったい
  エクセルで何をしたいのか?
  エクセルで業務効率化
  エクセル関数を使いこなす
  エクセルの便利技
  エクセルは最高の帳票ツール
 ・エクセル基本操作上級編!
  セル選択、コメント、シリアル値
  オート機能を使いこなそう!
  参照、条件付書式、入力規則
  関数をもっと理解しよう!
  配列数式を有効利用しよう!
  データの正規化をしよう!
  ショートカットキーを利用しよう1
  ショートカットキーを利用しよう2
  Office用アプリを作成しよう!
  PowerPivotとExcelで簡単BI!
 ・世間の誤ったエクセルの
  べからず集
  エクセルで文章を書くべからず
  エクセルで図形を描くべからず
  エクセルでシステムをつくるな
 
■ エクセル関連その他

 ・エクセルコミニュティにあなたも
  参加しませんか?
  Excel関連リンク・コミニュティ
 ・VBの理解がVBAをマスターする
  最短距離!
  VB関連の老舗・大家サイト
 ・エクセルExcel大事典掲示板
 ・プライバシーポリシー

2000アイテムを超えるラベルを販売
送料無料、即納対応の優良ショップ
今買っているラベルより確実に安い!
OAラベルの販売専科グラフトラベル




エクセルExcel大事典ははリンクフリーです エクセル大事典Excel大事典
お問い合わせはこちら gengengen@yahoo.co.jp

Copyright© Gen Muto 武藤 玄 All Rights Reserved,