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

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

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

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

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

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

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

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


/****************************************************************************/
/*!
 *  @brief  WAVファイルを再生する.
 *
 *  @param  なし.
 *
 *  @retval なし.
 */
private void Play_WaveSound()
{
    //! WAVファイルをオープンしていない場合、オープンする.
    if( m_File.IsOpen() == false ){
        //! -1.ダイアログから再生するWAVファイル名を取得する.
        m_FileName = FileName_TextBox.Text;

        //! -2.再生するWAVファイル名をオープンする.
        if( m_File.Open( m_FileName ) != true ){
            MessageBox.Show( "ファイルをオープンできません", "オープン", MessageBoxButtons.OK );
            return;
        }
    }
    if( m_DX == null ){
        //! WAVファイルからオーディオフォーマットを取得する.
        WaveFormat wf = new WaveFormat();
        m_File.GetWaveInfo( ref wf );

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

        //! DirectSoundをオープンする
        if( OpenSoundOutDevice( dev_guid, wf ) == false ) {
            return;
        }

        //! WAVファイルの読込み用バッファを確保する.
        m_DataBuf = null;
        m_DataBuf = new Byte[m_BufSize / 2];

        //! 再生カーソルの位置を初期化する.
        m_DXBuf.SetCurrentPosition( 0 );
        m_WritePos = 0;
    }

    //! サウンド再生を開始する.
    if( m_DXBuf !=  null ){
        m_DXBuf.Play( 0, BufferPlayFlags.Looping );
    }

    //! 再生状態を「再生中」にする.
    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;
}
    


/****************************************************************************/
/*!
 *  @brief  サウンド出力デバイスをオープンする.
 *
 *  @param  [in]    dev_guid    サウンド出力デバイスのGUID.
 *  @param  [in]    wf          WAVEフォーマット構造体.
 *
 *  @retval true = OK. / false = NG.
 */
private bool OpenSoundOutDevice( System.Guid dev_guid, WaveFormat wf )
{
    try {
        //! DirectSoundの再生オブジェクトを作成する.
        m_DX = new Device( dev_guid );

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

        //! ストリームバッファ・オブジェクトを作成する.
        BufferDescription desc = 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    = null;

        //! 確保されたストリームバッファのサイズを取得する.
        BufferCaps caps;
        caps      = m_DXBuf.Caps;
        m_BufSize = caps.BufferBytes;

        if( m_Thread == null ){
            //! イベントタスクを生成する.
            m_Thread = new Thread( new System.Threading.ThreadStart( OutputEventTask ) );

            //! 再生イベントのオブジェクトを作成する.
            m_Event = new AutoResetEvent( false );
        }

        //! 再生イベントを設定する.
        m_DXNotify = new Notify( m_DXBuf );
        BufferPositionNotify[] psa = new BufferPositionNotify[2];
        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;
    }
    catch( Exception ex ){
        //! エラーメッセージを表示する.
        MessageBox.Show( ex.Message, "オープン", MessageBoxButtons.OK );

        //! エラーが発生した場合、サウンド出力デバイスをクローズする.
        CloseSoundOutDevice();
        return false;
    }
}
    

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

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

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

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

System.MarshalByRefObject

メソッド名説明
SetCooperativeLevel

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

プロパティ名説明
Caps

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

SpeakerConfig

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

Certified

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

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

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


    public void SetCooperativeLevel( Control owner, CooperativeLevel level )
	

引数説明
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 void SetNotificationPositions(
                            BufferPositionNotify[] notify,
                            int numNotificationPositions )
	

引数説明
notify

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

numNotificationPositions

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

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

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

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

Offset

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

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

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

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

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


    public void SetCurrentPosition( int newPosition )
	

引数説明
newPosition

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

再生を開始する

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


    public void Play( int priority, BufferPlayFlags flags )
	

引数説明
priority

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

flags

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



商標に関する表示