DirectSoundを利用してWAVファイルを再生する
(その1)

概要

Windowsにて、DirectSoundを利用して音声ファイル(WAVファイル)を再生する簡単なサンプルプログラムです。

DirectSoundでは5.1チャンネルのようなマルチチャンネルがサポートされていたり、データビット長も16ビット以上がサポートされていたりして、高音質の多チャンネル対応がされています。
また、レイテンシーもMMEに比べると小さいようです。(私の作ったサンプルプログラムでは比較してもよく判りませんが。。。)

但し、DirectSoundの開発には『DirectX SDK』が別途必要になります。

DirectSoundを利用したサウンド出力の処理の流れを簡単に説明すると、以下のようになります。

  • サウンド出力を行うデバイスのオブジェクトを作成します。
  • サウンド出力を行うデバイスのオブジェクトからストリームバッファを作成します。
  • ストリームバッファの任意の位置に再生完了イベントを設定します。
  • 作成したストリームバッファにサウンド出力するデータを投入します。
  • ストリームバッファ上の任意の位置まで再生が完了したときにイベント通知が受けられるので、ストリームバッファで再生が完了した部分に新たにサウンド出力するデータを投入します。
  • 出力するデータがなくなった場合、サウンド出力を終了します。

DirectSoundを利用するには、以下のインクルードファイルとライブラリが必要になります。

追加するインクルード

dsound.h

追加するライブラリ

dsound.lib, dxguid.lib

サンプルプログラムの仕様

作成するサンプルプログラムは以下の仕様にします。

  • ウインドウ・スタイルはダイアログにする。
  • サウンドを出力するデバイスが複数ある場合、ユーザーが選択できる。
  • 再生するWAVファイルは、ユーザーが選択できる。
  • WAVファイルを選択後、[再生]ボタンで再生を開始する。
  • WAVファイルの再生中に[一時停止]ボタンを押すと、再生を一時中断し、[再生]ボタンを押すと中断した時点から、再生を再開する。
  • [停止]ボタンを押すと再生を終了し、[再生]ボタンを押すとファイルの先頭から再生を開始する。
  • 音量調節および左右のバランス調節をダイアログから行えるようにする。

サンプルプログラムの外観は以下のようにします。

ダイアログの初期処理

WM_INITDIALOGメッセージを受けたときに、ダイアログの初期処理を行います。

ダイアログの初期処理では、サウンド出力デバイスのリストの作成と、音量ボリュームおよび左右バランスのトラックバーの初期化を行います。

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


/****************************************************************************/
/*!
 *  @brief  ダイアログの初期処理.
 *
 *  @param  [in]    hDlg    ダイアログのウインドウ・ハンドル.
 *
 *  @retval なし.
 */
static void     OnInitDialog( HWND hDlg )
{
    //! DirectSoundの出力デバイスをリストアップする.
    DevCnt = 0;
    DirectSoundEnumerate( DSEnumCallback, (void*)0 );

    //! 出力デバイスリストを作成する.
    if( DevCnt != 0 ){
        HWND hlist = GetDlgItem( hDlg, IDC_OUTPUT_DEVICE );
        ComboBox_ResetContent( hlist );
        for( DWORD i = 0; i < DevCnt; i++ ){
            ComboBox_AddString( hlist, DevName[i] );
        }
        ComboBox_SetCurSel( hlist, 0 );
    }
    //! 音量ボリュームのトラックバーを設定する.
    HWND hbar = GetDlgItem( hDlg, IDC_VOLUME );
    SendMessage( hbar, TBM_SETRANGE, TRUE, MAKELONG( 0, 100 ) );
    SendMessage( hbar, TBM_SETPOS  , TRUE, 50 );

    //! 音量バランスのトラックバーを設定する.
    hbar = GetDlgItem( hDlg, IDC_BALANCE );
    SendMessage( hbar, TBM_SETRANGE, TRUE, MAKELONG( 0, 100 ) );
    SendMessage( hbar, TBM_SETPOS  , TRUE, 50 );
}
	


/****************************************************************************/
/*!
 *  @brief  入出力デバイス列挙時のコールバック関数.
 *
 *  @param  [in]    guid    デバイスを識別するGIUD.
 *  @param  [in]    desc    DirectSoundデバイスの説明文.
 *  @param  [in]    module  DirectSoundドライバのモジュール名.
 *  @param  [in]    user    ユーザー定義変数 (今回は使用しない).
 *
 *  @retval TRUE = 次のデバイスを取得 / FALSE = デバイスの列挙を終了する.
 */
static BOOL CALLBACK    DSEnumCallback( LPGUID guid, LPCTSTR desc,
                                               LPCTSTR module, LPVOID user )
{
    //! 確保しているリストサイズを超えてしまう場合、デバイスの列挙を終了する.
    if( DevCnt >= 10 ){
        return FALSE;
    }
    //! "プライマリ デバイス"はリストに入れない.
    if( !guid || !desc ){
        return TRUE;
    }
    //! 出力デバイスのGUIDを保存する.
    DevGuid[DevCnt] = *guid;

    //! 出力デバイス名を保存する.
    _tcsncpy_s( DevName[DevCnt], desc, 63 );

    //! 出力デバイスの個数を+1する.
    DevCnt++;
    return TRUE;
}
	

DirectSoundの出力デバイスをリストアップする

使用するオーディオドライバをユーザーが選択できるように、オーディオ出力可能なDirectSoundドライバをDirectSoundEnumerate()を呼び出してリストアップします。


    HRESULT WINAPI DirectSoundEnumerate(
                              LPDSENUMCALLBACK lpDSEnumCallback,
                              LPVOID lpContext )
	

引数説明
lpDSEnumCallback

オーディオ出力可能なDirectSoundドライバの情報が通知されるコールバック関数のポインタ。

lpContext

アプリケーション定義データ
コールバック関数の引数lpContextに使われます。

DirectSoundEnumerate()からの戻り値がS_OKであれば、DirectSoundの出力デバイスをリストアップは完了です。

オーディオ出力可能なDirectSoundドライバの情報が通知されるコールバックは以下のとおりです。


    BOOL CALLBACK DSEnumCallback(
                         LPGUID lpGuid,
                         LPCSTR lpcstrDescription,
                         LPCSTR lpcstrModule,
                         LPVOID lpContext )
	

引数説明
lpGuid

ドライバのGUIDを示す変数のポインタ。
コントロールパネルで指定されているデバイスの場合、NULLとGIUDの2回呼び出されます。

lpcstrDescription

デバイスの説明文を示す文字列のポインタ。

lpcstrModule

モジュール名を示す文字列のポインタ。

lpContext

アプリケーション定義データ。

引き続きデバイスの列挙を行う場合はTRUEを、デバイスの列挙を中断する場合はFALSEを返します。

サンプルコードでは、出力デバイスのGUIDと表示用にデバイスの説明文を示す文字列をテーブルに保存しています。



商標に関する表示