VB.NETでDirectSoundを利用してWAVファイルを再生する
(その1)
『DirectSoundを利用してサウンド出力を行う方法』で作成したサンプルコードのVisual Basic版です。
Visual Basicから.NET FrameworkのDirectSoundを利用して音声ファイル(WAVファイル)の再生を行います。
C#版は『C#でDirectSoundを利用してWAVファイルを再生する』にあります。
サンプルコードの処理の流れを簡単に説明すると、以下のようになります。
(基本的にC/C++でDirectSoundを利用する場合と一緒です。)
- サウンド出力を行うデバイスのオブジェクトを作成します。
- サウンド出力を行うデバイスのオブジェクトからストリームバッファを作成します。
- ストリームバッファの任意の位置に再生完了イベントを設定します。
- 作成したストリームバッファにサウンド出力するデータを投入します。
- ストリームバッファ上の任意の位置まで再生が完了したときにイベント通知が受けられるので、ストリームバッファで再生が完了した部分に新たにサウンド出力するデータを投入します。
- 出力するデータがなくなった場合、サウンド出力を終了します。
.NET FrameworkでDirectSoundを利用するには、以下のクラスを参照設定で追加します。
追加するクラス | Microsoft.DirectX.DirectSound |
作成するサンプルプログラムは以下の仕様にします。
- ウインドウ・スタイルはダイアログにする。
- サウンドを出力するデバイスが複数ある場合、ユーザーが選択できる。
- 再生するWAVファイルは、ユーザーが選択できる。
- WAVファイルを選択後、[再生]ボタンで再生を開始する。
- WAVファイルの再生中に[一時停止]ボタンを押すと、再生を一時中断し、[再生]ボタンを押すと中断した時点から、再生を再開する。
- [停止]ボタンを押すと再生を終了し、[再生]ボタンを押すとファイルの先頭から再生を開始する。
- 音量調節および左右のバランス調節をダイアログから行えるようにする。
サンプルプログラムの外観は以下のようにします。
ダイアログのLoad()メソッドでダイアログの初期処理を行います。
ダイアログの初期処理では、サウンド出力デバイスのリストを作成します。
実は、本サンプルコードをVisual Studioから実行すると以下の警告メッセージが表示されます。
『マネージ デバッグ アシスタント 'LoaderLock' では 'sample_0005.vshost.exe' に問題を検出しました。
'Microsoft.DirectX.DirectSound.dll' は、OS ローダー ロック内でマネージ実行を試行しています。
DllMain またはイメージ初期化関数内でマネージ コードを実行しないでください。
この動作は、アプリケーションをハングさせる原因になる可能性があります。』
'DirectSound.dll'をロードするタイミングがアプリケーションのFormのロード時では問題があるようです。
(調べてみると'DirectSound.dll'自体の問題かもしれないです。対策しなくても実用上は問題無いとは思うのですが。。。)
DLLをロードするタイミングをFormのロード完了以降にずらせば良いのだろうと思いますが、ちょうど良いイベントが思いつかなかったので、とりあえずこのままにしておきます。
サンプルコードを以下に示します。
'****************************************************************************'
'*
'* @brief ダイアログの初期処理.
'*
'* @param [in] sender イベントの送信元のオブジェクト.
'* @param [in] e イベント情報.
'*
'* @retval なし.
'*
Private Sub Form1_Load( ByVal sender As System.Object, ByVal e As System.EventArgs ) Handles MyBase.Load
' デバイス名コンボボックスにDataTableオブジェクトを作成する.
Dim device_table As New DataTable()
device_table.Columns.Add( "NAME", GetType(String) )
device_table.Columns.Add( "GUID", GetType(Guid) )
Dim DsEnum As New DevicesCollection
Dim info As DeviceInformation
Dim i As Long
' デバイス名コンボボックスにデバイス名と対応するGUIDを登録する.
For i = 0 To DsEnum.Count() - 1
info = DsEnum.Item( i )
' 列挙したデバイス名が"プライマリ・デバイス"の場合、コンボボックスには追加しない.
If (info.DriverGuid() <> System.Guid.Empty _
And info.Description <> "") Then
' DataTableにデバイス名とGIUDを追加する.
Dim row As DataRow = device_table.NewRow()
row("NAME") = info.Description
row("GUID") = info.DriverGuid
device_table.Rows.Add( row )
End If
Next i
DsEnum = Nothing
device_table.AcceptChanges()
'コンボボックスのDataSourceにDataTableを割り当てる.
DeviceList_ComboBox.DataSource = device_table
DeviceList_ComboBox.DisplayMember = "NAME" ' 表示.
DeviceList_ComboBox.ValueMember = "GUID" ' コンボボックスの値.
End Sub
使用するオーディオドライバをユーザーが選択できるように、オーディオ出力可能なDirectSoundドライバをDevicesCollectionクラスから取得してコンボボックスにリストアップします。
DevicesCollectionクラスのプロパティは以下のとおりです。
クラス名 | Microsoft.DirectX.DirectSound.DevicesCollection |
---|---|
基本型 | System.Object |
プロパティ名 | 説明 |
Count | オーディオ出力可能なDirectSoundドライバの個数を取得します。 |
Item | 指定した番号のドライバ情報(DeviceInformation)を取得します。 |
DeviceInformation構造体の主なプロパティは以下のとおりです。
構造体名 | Microsoft.DirectX.DirectSound.DeviceInformation |
---|---|
プロパティ名 | 説明 |
Description | 出力デバイスの説明文を取得します。 |
DriverGuid | 出力デバイスのGUIDを取得します。 |
ModuleName | 出力デバイスのモジュール名を取得します。 |
サンプルコードでは、コンボボックスに出力デバイスのGUIDと表示用にデバイスの説明文を示す文字列をコンボボックスに登録しています。