ホーム < ゲームつくろー! < Ogg Vorbis入門編
Ogg Vorbis入門編
その6 OggDecoderオブジェクトを複製して同時に鳴らす:サンプルプログラム
Ogg Vorbis入門編その6「OggDecoderオブジェクトを複製して同時に鳴らす」で説明した内容を踏まえたサンプルプログラムです。実行するとコンソール画面が現れて、指定のOggファイルが20個ちょっとずつズレながら同時にストリーム再生されます。
サンプルスクリーンショット。味も素っ気も無い画面ですいません。
このサンプルは1つのOggファイルをメモリに展開し、その複製を20個作成してちょっとずつ遅延させながら(ついでに音量も小さくして)同時に鳴らしています。こういうのを「擬似リバーブ」と言います(昔MIDIをやっていた時に多用していました)。
複製は同じメモリを参照しているため、実質のメモリ消費はほぼ複製元1つ分です。Playerにデコーダオブジェクトを渡す時に元ではなくてクローン側を渡すのがポイントです。
// 元を作成
Dix::sp< Dix::OggDecoderInMemory > spOggDecoder( new Dix::OggDecoderInMemory( "test.ogg" ) );
for ( int i = 0; i < cloneNum_g; ++i ) {
playerAry[ i ].setDevice( cpDS8 );
playerAry[ i ].setDecoder( spOggDecoder->clone() );
}
○ サンプルの動かし方
サンプルを動かすために必要なファイルはこちらからダウンロードできます(OggSmp_No6.lzh)。空のコンソールアプリケーションを作成し、アーカイブに入っているクラスをすべて追加し、Ogg Vorbisライブラリを環境に設定するとビルドできます。実行して音楽を聴くにはプロジェクトフォルダ下に「Test.Ogg」というOggファイルが必要です。お手元の音楽をOggファイルに変換して試してみてください。
PCMDecoderオブジェクトはスマートポインタに包む必要があります。またIDirectSound8インターフェイスはCOMポインタに包みます。これはポインタ先のアクセスを保障するためです。使用の際はご注意下さい。
○ Ogg Vorbisライブラリについて
このサンプルを動かすには別途Ogg Vorbisライブラリを組み込む必要があります。組み込み方についてはOgg Vorbis入門編その1「Ogg Vorbisライブラリのインストール」に詳しく記載しておりますのでご参照ください。うまくいかない場合は掲示板にご報告下さい。
// Ogg Vorbisストリーム再生クラステストプログラム // // 製作者 : IKD // HP : http://marupeke296.com // #pragma comment ( lib, "dxguid.lib" ) #pragma comment ( lib, "dsound.lib" ) #include <dsound.h> #include <tchar.h> #include "OggDecoderInMemory.h" #include "PCMPlayer.h" #include "DixSmartPtr.h" #include "DixComPtr.h" // コンソールのウィンドウハンドル取得 HWND GetConsoleHwnd(void) { TCHAR pszWindowTitle[ 1024 ]; GetConsoleTitle( pszWindowTitle, 1024 ); return FindWindow( NULL, pszWindowTitle ); } // 一時停止関数 void StopProc() { while ( 1 ) { Sleep( 200 ); // Escapeキーを押したら抜ける if ( GetAsyncKeyState( VK_ESCAPE ) ) break; } } int _tmain(int argc, _TCHAR* argv[]) { // DirectSoundの作成 IDirectSound8 *pDS8; DirectSoundCreate8( NULL, &pDS8, NULL ); Dix::Com_ptr< IDirectSound8 > cpDS8( pDS8 ); pDS8->SetCooperativeLevel( GetConsoleHwnd(), DSSCL_PRIORITY ); // Oggオブジェクト作成 Dix::sp< Dix::OggDecoderInMemory > spOggDecoder( new Dix::OggDecoderInMemory( "test.ogg" ) ); // Dix::sp< Dix::OggDecoder > spOggDecoder( new Dix::OggDecoderInMemory( "test.ogg" ) ); const int cloneNum_g = 20; Dix::PCMPlayer playerAry[ cloneNum_g ]; for ( int i = 0; i < cloneNum_g; ++i ) { playerAry[ i ].setDevice( cpDS8 ); playerAry[ i ].setDecoder( spOggDecoder->clone() ); } bool isLoop = true; for ( int i = 0; i < cloneNum_g; ++i ) { Sleep( 100 ); if( playerAry[ i ].play( isLoop ) == false ) { printf( "ファイル準備に失敗しています" ); return 0; } playerAry[ i ].setVolume( -500 * i ); } // 再生 printf( "ただ今再生中\n" ); StopProc(); // 停止 for ( int i = 0; i < cloneNum_g; ++i ) { playerAry[ i ].stop(); } printf( "\n停止しました\n" ); return 0; }