VB.NETでDirectSoundを利用してWAVファイルを再生する
(その2)

WAVファイルの再生を開始する

ダイアログの[再生]ボタンを押されたときに、WAVファイルの再生を開始します。

WAVファイルがオープンされていない場合、WAVファイルをオープンします。

次にオープンしたWAVファイルの情報を元に以下の手順でサウンド出力デバイスに対応したストリームバッファを作成します。

作成したストリームバッファの再生開始位置を初期化します。

最後にDirectSoundの再生を開始します。

サンプルコードを以下に示します。


'****************************************************************************'
'*
'*  @brief  WAVファイルを再生する.
'*
'*  @param  なし.
'*
'*  @retval なし.
'*
Private Sub Play_WaveSound()

On Error Goto error_exit

    ' WAVファイルをオープンしていない場合、オープンする.
    If ( m_File.IsOpen() = False ) Then
        ' -1.ダイアログから再生するWAVファイル名を取得する.
        m_FileName = FileName_TextBox.Text

        ' -2.再生するWAVファイル名をオープンする.
        If ( m_File.Open( m_FileName ) <> True ) Then
            MsgBox( "ファイルをオープンできません", MsgBoxStyle.OKOnly )
            Exit Sub
        End If
    End If

    If ( IsNothing( m_DX ) = True ) Then
        ' WAVファイルからオーディオフォーマットを取得する.
        Dim wf As New WaveFormat
        m_File.GetWaveInfo( wf )

        ' デバイス選択リストからサウンド・デバイスのGUIDを取得する.
        Dim dev_guid As System.Guid
        dev_guid = DeviceList_ComboBox.SelectedValue()

        ' DirectSoundをオープンする
        If ( OpenSoundOutDevice( dev_guid, wf ) = False ) Then
            Exit Sub
        End If

        'WAVファイルの読込み用バッファを確保する.
        m_DataBuf = Nothing
        m_DataBuf = New Byte( (m_BufSize / 2) - 1 ){}

        ' 再生カーソルの位置を初期化する.
        m_DXBuf.SetCurrentPosition( 0 )
        m_WritePos = 0
    End If

    ' サウンド再生を開始する
    If ( IsNothing( m_DXBuf ) = False ) Then
        m_DXBuf.Play( 0, BufferPlayFlags.Looping )
    End If

    ' 再生状態を「再生中」にする.
    m_IsPlay = True

    Play_Button.Enabled         = False
    Stop_Button.Enabled         = True
    Pause_Button.Enabled        = True
    DeviceList_ComboBox.Enabled = False
    FileName_TextBox.Enabled    = False
    FileSel_Button.Enabled      = False

    Exit Sub

error_exit:
    ' エラーメッセージを表示する.
    MsgBox( Err.Description, vbOKOnly, "再生" )
End Sub
    


'****************************************************************************'
'*
'*  @brief  サウンド出力デバイスをオープンする.
'*
'*  @param  [in]    dev_guid    サウンド出力デバイスのGUID.
'*  @param  [in]    wf          WAVEフォーマット構造体.
'*
'*  @retval True = OK. / False = NG.
'*
Private Function OpenSoundOutDevice( ByVal dev_guid As System.Guid, ByVal wf As WaveFormat ) As Boolean

On Error Goto error_exit

    ' DirectSoundの再生オブジェクトを作成する.
    m_DX = new Device( dev_guid )

    ' 再生オブジェクトに対するアプリケーションの協調レベルを設定する.
    m_DX.SetCooperativeLevel( Me, CooperativeLevel.Priority )

    ' ストリームバッファ・オブジェクトを作成する.
    Dim desc As New BufferDescription
    desc.Format      = wf
    desc.BufferBytes = wf.AverageBytesPerSecond / 4
    desc.Flags       = BufferDescriptionFlags.GlobalFocus  _
                     + BufferDescriptionFlags.ControlPositionNotify  _
                     + BufferDescriptionFlags.ControlVolume  _
                     + BufferDescriptionFlags.ControlPan 
    m_DXBuf = New SecondaryBuffer( desc, m_DX )
    desc    = Nothing

    ' 確保されたストリームバッファのサイズを取得する.
    Dim caps As BufferCaps
    caps      = m_DXBuf.Caps()
    m_BufSize = caps.BufferBytes()

    If ( IsNothing( m_Thread ) = True ) Then

        ' イベントタスクを生成する.
        m_Thread = New Thread( New System.Threading.ThreadStart( AddressOf OutputEventTask ) )

        ' 再生イベントのオブジェクトを作成する.
        m_Event = New AutoResetEvent( False )

    End If

    ' 再生イベントを設定する.
    m_DXNotify = New Notify( m_DXBuf )
    Dim psa(1) As BufferPositionNotify
    psa(0).EventNotifyHandle = m_Event.Handle
    psa(0).Offset            = (m_BufSize / 2) - 1
    psa(1).EventNotifyHandle = m_Event.Handle
    psa(1).Offset            = m_BufSize - 1
    m_DXNotify.SetNotificationPositions( psa, psa.Length )

    ' イベントタスクを起動する.
    m_IsDoing = True
    m_Thread.Start()

    Return True
    Exit Function

error_exit:
    ' エラーメッセージを表示する.
    MsgBox( Err.Description, vbOKOnly, "オープン" )

    ' エラーが発生した場合、サウンド出力デバイスをクローズする.
    Call CloseSoundOutDevice()
    Return False
End Function
    

DirectSoundのオブジェクトを作成する

Deviceクラスのオブジェクトを、使用する出力デバイスのGUIDを用いて作成します。

Deviceクラスの主なメソッドとプロパティは以下のとおりです。

クラス名Microsoft.DirectX.DirectSound.Device
基本型

System.MarshalByRefObject

メソッド名説明
SetCooperativeLevel

デバイスに対するアプリケーションの協調レベルを設定します。

プロパティ名説明
Caps

デバイスの性能を取得します。

SpeakerConfig

スピーカ構成の設定と取得を行います。

Certified

ドライバが DirectX で認証されているかどうかを確認します。

アプリケーションの協調レベルを設定する

DirectSoundでは1つの出力デバイスを複数のアプリケーションから同時に利用できる為、DeviceクラスのSetCooperativeLevel()メソッドを呼び出して、使用するサウンド出力デバイスのアプリケーション間の協調レベルを設定します。


    Public Sub SetCooperativeLevel(
                 ByVal owner As System.Windows.Forms.Control, _
                 ByVal level As Microsoft.DirectX.DirectSound.CooperativeLevel )
	

引数説明
owner

DirectSoundを使用するFormのオブジェクト。

level

アプリケーションの協調レベル。
通常はCooperativeLevel.Priority(優先レベル)を指定します。

ストリームバッファを作成する

DirectSoundのストリームバッファはSecondaryBufferクラスのオブジェクトにより管理されます。

SecondaryBufferクラスのオブジェクトをDeviceクラスのオブジェクトを用いて作成します。

SecondaryBufferクラスの主なメソッドとプロパティは以下のとおりです。

クラス名Microsoft.DirectX.DirectSound.SecondaryBuffer
基本型

Microsoft.DirectX.DirectSound.Buffer

メソッド名説明
Play

オーディオの再生を開始します。

Stop

オーディオの再生を停止します。

Write

ストリームバッファにオーディオデータを書き込みます。

Read

ストリームバッファからオーディオデータを読み込みます。

GetCurrentPosition

バッファの再生カーソルおよび読み込みカーソルの位置を取得します。

SetCurrentPosition

バッファの再生カーソルの位置を設定します。

Restore

失われたバッファへのメモリ割り当てを復元します。

プロパティ名説明
Format

オーディオ・フォーマットの取得と設定を行います。

Frequency

サンプルレートの取得と設定を行います。

Caps

バッファの能力を取得します。

Status

バッファのステータスを取得します。

PlayPosition

バッファの再生カーソルの位置を取得します。

WritePosition

バッファの書き込みカーソル位置を取得します。

Volume

ボリュームレベルの取得と設定を行います。

Pan

左右のボリュームバランスの取得と設定を行います。

作成するストリームバッファの設定はBufferDescriptionクラスのオブジェクトで指定します。

BufferDescriptionクラスの主なプロパティは以下のとおりです。

クラス名Microsoft.DirectX.DirectSound.BufferDescription
基本型System.MarshalByRefObject
プロパティ名説明
BufferBytes

作成するバッファのサイズ(バイト数)を設定します。

Flags

サンプルコードで設定しているフラグは以下のとおりです。
 - BufferDescriptionFlags.GlobalFocus
   グローバルなサウンド・バッファを作成します。
 - BufferDescriptionFlags.ControlPositionNotify
   通知イベントを使用します。
 - BufferDescriptionFlags.ControlVolume
   ボリュームレベルの設定を行います。
 - BufferDescriptionFlags.ControlPan
   左右のボリュームバランスの設定を行います。

Format

オーディオ・フォーマットを設定します。


作成したSecondaryBufferクラスのオブジェクトから実際に作成したストリームバッファのサイズを取得します。

ストリームバッファのサイズを取得するには、BufferCaps構造体のプロパティBufferBytesを参照します。

BufferCaps構造体はSecondaryBufferクラスのプロパティCaps()を使用して取得します。

BufferCaps構造体の主なプロパティは以下のとおりです。

構造体名Microsoft.DirectX.DirectSound.BufferCaps
プロパティ名説明
BufferBytes

ストリームバッファのサイズ(バイト数)。

CanGetCurrentPosition

True=正確な再生カーソルを取得できます。

Control3D

True=3Dサウンドを利用できます。

ControlEffects

True=エフェクト処理をサポートしています。

ControlFrequency

True=サンプルレートの設定ができます。

ControlPan

True=左右のボリュームバランスの設定ができます。

ControlPositionNotify

True=通知イベントを利用できます。

ControlVolume

True=ボリュームレベルの設定ができます。

GlobalFocus

True=グローバルなサウンド・バッファを使用しています。

LocateInHardware

True=ハードウェア・ミキシングを行います。

LocateInSoftware

True=ソフトウェア・ミキシングを行います。

LocationDefer

True=再生時にハードウェア/ソフトウェアのリソースにバッファを割り当てます。

Mute3DAtMaximumDistance

True=サウンドは最大距離で無音になります。

PlayCpuOverhead

サウンド・バッファをミキシングするために必要な時間。
CPUサイクルのパーセンテージで表します。

PrimaryBuffer

True=バッファはプライマリ・バッファです。

StaticBuffer

True=オンボード・ハードウェア・メモリを使用しています。

StickyFocus

True=DirectSoundを使用していない他のアプリケーションに切り替えても、継続してオーディオ出力を行います。

UnlockTransferRate

データをバッファ・メモリに転送する速度 (KB/秒)。

再生イベントを設定する

ストリームバッファにWAVEデータを書き込むタイミングを発生させるために、ストリームバッファの任意の再生位置でイベントを発行してもらうように Notify()クラスのオブジェクトを生成して再生イベントの通知位置を設定します。

NotifyクラスノオブジェクトはSecondaryBufferクラスのオブジェクトを用いて作成します。

Notifyクラスの主なメソッドは以下のとおりです。

クラス名Microsoft.DirectX.DirectSound.Notify
基本型

System.MarshalByRefObject

メソッド名説明
SetNotificationPositions

再生イベントを設定します。

再生イベントの通知位置を設定するには、NotifyクラスのSetNotificationPositions()を使用します。
設定したイベントは、再生中に再生カーソルが指定されたオフセットに到達するたびに、イベントが通知されます。


    Public Sub SetNotificationPositions( _
           ByVal notify() As Microsoft.DirectX.DirectSound.BufferPositionNotify, _
           ByVal numNotificationPositions As Integer )
	

引数説明
notify

イベント設定構造体(BufferPositionNotify)の配列。

numNotificationPositions

設定する再生イベントの個数。

BufferPositionNotify構造体の主なプロパティは以下のとおりです。

構造体名Microsoft.DirectX.DirectSound.BufferPositionNotify
プロパティ名説明
EventNotifyHandle

通知されるイベントのハンドル。

Offset

バッファの先頭から通知イベントが発生する場所までのオフセット(バイト単位)。

サンプルコードではストリームバッファの中間点と最後の2点に再生イベントを設定しています。

ストリームバッファの再生開始位置を初期化する

SecondaryBufferクラスのSetCurrentPosition()メソッドを呼び出して再生開始位置を設定します。

サンプルコードでは再生開始位置の初期化なので、引数に0を設定します。


    Public Sub SetCurrentPosition( ByVal newPosition As Integer )
	

引数説明
newPosition

バッファの先頭からの再生カーソルのオフセット(バイト単位)。

再生を開始する

SecondaryBufferクラスのPlay()メソッドを呼び出して再生を開始します。


    Public Sub Play( ByVal priority As Integer, _
                     ByVal flags As Microsoft.DirectX.DirectSound.BufferPlayFlags )
	

引数説明
priority

サウンドの優先度。通常は0を指定します。

flags

ストリームバッファをリングバッファとして動作させますのでBufferPlayFlags.Loopingを指定します。



Windows、DirectXおよびDirectSoundは米国Microsoft Corporationの登録商標です。