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ドライバをDirectSoundEnumerate()を呼び出してリストアップします。
HRESULT WINAPI DirectSoundEnumerate(
LPDSENUMCALLBACK lpDSEnumCallback,
LPVOID lpContext )
引数 | 説明 |
---|---|
lpDSEnumCallback |
オーディオ出力可能なDirectSoundドライバの情報が通知されるコールバック関数のポインタ。 |
lpContext |
アプリケーション定義データ |
DirectSoundEnumerate()からの戻り値がS_OKであれば、DirectSoundの出力デバイスをリストアップは完了です。
オーディオ出力可能なDirectSoundドライバの情報が通知されるコールバックは以下のとおりです。
BOOL CALLBACK DSEnumCallback(
LPGUID lpGuid,
LPCSTR lpcstrDescription,
LPCSTR lpcstrModule,
LPVOID lpContext )
引数 | 説明 |
---|---|
lpGuid |
ドライバのGUIDを示す変数のポインタ。 |
lpcstrDescription | デバイスの説明文を示す文字列のポインタ。 |
lpcstrModule | モジュール名を示す文字列のポインタ。 |
lpContext | アプリケーション定義データ。 |
引き続きデバイスの列挙を行う場合はTRUEを、デバイスの列挙を中断する場合はFALSEを返します。
サンプルコードでは、出力デバイスのGUIDと表示用にデバイスの説明文を示す文字列をテーブルに保存しています。