ホーム < ゲームつくろー! < Ogg Vorbis入門編

Ogg Vorbis入門編
その8 音が終わった事を通知する:サンプルプログラム


 Ogg Vorbis入門編その8「音が終わった事を通知する」で説明した内容を踏まえたサンプルプログラムです。実行するとコンソール画面が現れて、指定のOggファイルがストリーム再生されます。


サンプルスクリーンショット。見た目はもう気にしない事にしました(T_T)

 このサンプルは1つのOggファイルをオープンし、デコーダがそこから音声情報をデコードし、さらに再生機がそれを再生します。曲が最後まで到達したら自動的に停止状態になりストリーム再生が停止します。裏ではストリームスレッドは回っていますが、停止中はSleepが100ミリ秒入った空スレッドになっているためCPU負荷はとても低くなっています。


○ サンプルの動かし方

 サンプルを動かすために必要なファイルはこちらからダウンロードできます(OGGSmp_No8(v103).zip)。空のコンソールアプリケーションを作成し、アーカイブに入っているクラスをすべて追加し、Ogg Vorbisライブラリを環境に設定するとビルドできます。実行して音楽を聴くにはプロジェクトフォルダ下に「Test.Ogg」というOggファイルが必要です。お手元の音楽をOggファイルに変換して試してみてください。

 PCMDecoderオブジェクトはスマートポインタに包む必要があります。またIDirectSound8インターフェイスはCOMポインタに包みます。これはポインタ先のアクセスを保障するためです。使用の際はご注意下さい。

○ Ogg Vorbisライブラリについて

 このサンプルを動かすには別途Ogg Vorbisライブラリを組み込む必要があります。組み込み方についてはOgg Vorbis入門編その1「Ogg Vorbisライブラリのインストール」に詳しく記載しておりますのでご参照ください。うまくいかない場合は掲示板にご報告下さい。

○ バージョン情報

・ v1.00
 非ループ時の自動停止処理追加

・ v1.01
 終了時にOggVorbis_Fileを解放していなかったバグを修正

・ v1.02
 確保時間とほぼ同じ長さのサウンドを再生したときに終了しないバグを修正

・ v1.03
 OggVorbisMemory::createBufferメソッド内でfclose抜けの為ファイルバッファがリークしているバグを修正

// Ogg Vorbisストリーム再生クラステストプログラム
//
//  製作者 : IKD
//  HP     : http://marupeke296.com
//


#pragma comment ( lib, "dxguid.lib" )
#pragma comment ( lib, "dsound.lib" )

#include <dsound.h>
#include <tchar.h>
#include "OggDecoder.h"
#include "OggVorbisMemory.h"
#include "OggVorbisFile.h"
#include "PCMPlayer.h"
#include "DixSmartPtr.h"
#include "DixComPtr.h"


// コンソールのウィンドウハンドル取得
HWND GetConsoleHwnd(void)
{
   TCHAR pszWindowTitle[ 1024 ];
   GetConsoleTitle( pszWindowTitle, 1024 );
   return FindWindow( NULL, pszWindowTitle );
}

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::OggVorbisMemory > spOggResource( new Dix::OggVorbisMemory( "test.ogg" ) );
// Dix::sp< Dix::OggVorbisFile > spOggResource( new Dix::OggVorbisFile( "test.ogg" ) );
   Dix::sp< Dix::OggDecoder > spOggDecoder( new Dix::OggDecoder( spOggResource ) );
   Dix::PCMPlayer player;

   player.setDevice( cpDS8 );
   player.setDecoder( spOggDecoder );
   bool isLoop = false;
   if ( player.play( isLoop ) == false ) {
      printf( "ファイル準備に失敗しています" );
      return 0;
   }

   // 状態チェック
   bool isFinish = false;
   while( !isFinish ) {
      switch( player.getState() ) {
      case Dix::PCMPlayer::STATE_PLAY:
         printf( "再生中です\n" );
         break;

      case Dix::PCMPlayer::STATE_STOP:
         printf( "停止しました" );
         isFinish = true;
         break;
      }

      Sleep( 1000 );
   }

   return 0;
}