C#でDirectSoundを利用してWAVファイルを再生する
(その2)
ダイアログの[再生]ボタンを押されたときに、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;
}
}
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 |
アプリケーションの協調レベル。 |
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 |
サンプルコードで設定しているフラグは以下のとおりです。 |
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 | サウンド・バッファをミキシングするために必要な時間。 |
PrimaryBuffer | True=バッファはプライマリ・バッファです。 |
StaticBuffer | True=オンボード・ハードウェア・メモリを使用しています。 |
StickyFocus | True=DirectSoundを使用していない他のアプリケーションに切り替えても、継続してオーディオ出力を行います。 |
UnlockTransferRate | データをバッファ・メモリに転送する速度 (KB/秒)。 |
ストリームバッファにWAVEデータを書き込むタイミングを発生させるために、ストリームバッファの任意の再生位置でイベントを発行してもらうように Notify()クラスのオブジェクトを生成して再生イベントの通知位置を設定します。
NotifyクラスノオブジェクトはSecondaryBufferクラスのオブジェクトを用いて作成します。
クラス名 | 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を指定します。 |