ゲーム開発31:XAudio2でWaveを再生する1

前にXACT3Waveを再生する処理を書きましたが、いちいちWaveファイルを固めるのはメンドくさい。

てな訳で、改めてXAudio2でWaveを再生することにしました。まぁサンプルにそのものずばりな物があるので(XAudio2BasicSound)、それを元にゲームで使える様な物に作り替えます。

基本的な処理の流れは、COMを初期化してXAudio2を使えるようにする。マスターボイスを作ってその中にWaveから取り出したソースボイスを入れる。再生。といった感じです。

今回はXAudio2の部分CAudioBaseクラスだけ記述しました。Waveファイルからデータを取り出す処理は次回。

//--------------------------------------------------------------------------------------
// 生成
CAudioBase::CAudioBase()
{
 for (int i=0; i<MAX_SOUND; i++) {
  pSourceVoice[i]=NULL;
  pXAudioBuffer[i]=NULL;
  pbWaveData[i]=NULL;
 }

 pXAudio2=NULL;
 pMasteringVoice=NULL;
}
//-----------------------------------------------------------------------------
// 解放
CAudioBase::~CAudioBase()
{
 Release();

 // マスターボイス解放
 if (pMasteringVoice!=NULL) {
  pMasteringVoice->DestroyVoice();
  pMasteringVoice=NULL;
 }

 // XAudio解放
 SAFE_RELEASE(pXAudio2);

 // COM解放
 CoUninitialize();
}
//--------------------------------------------------------------------------------------
// 初期化
BOOL CAudioBase::Init()
{
 // COM初期化
 CoInitializeEx(NULL, COINIT_MULTITHREADED);

 // デバッグモードの場合
 UINT32 flags=0;
#ifdef _DEBUG
 flags|=XAUDIO2_DEBUG_ENGINE;
#endif

 // XAudio2生成
 if (FAILED(XAudio2Create(&pXAudio2, flags))) {
  CoUninitialize();
  return E_FAIL;
 }

 // マスターボイス生成
 if (FAILED(pXAudio2->CreateMasteringVoice(&pMasteringVoice))) {
  SAFE_RELEASE(pXAudio2);
  CoUninitialize();
  return E_FAIL;
 }

 return S_OK;
}
//-----------------------------------------------------------------------------
// 解放
void CAudioBase::Release()
{
 // ソースボイス解放
 for (int i=0; i<MAX_SOUND; i++) {
  ReleaseSound(i);
 }
}
//-----------------------------------------------------------------------------
// サウンド解放
void CAudioBase::ReleaseSound(int no)
{
 if (pbWaveData[no]!=NULL) {
  SAFE_DELETE(pbWaveData[no]);
 }
 if (pXAudioBuffer[no]!=NULL) {
  SAFE_DELETE(pXAudioBuffer[no]);
 }
 if (pSourceVoice[no]!=NULL) {
  pSourceVoice[no]->DestroyVoice();
  pSourceVoice[no]=NULL;
 }
}
//--------------------------------------------------------------------------------------
// ファイル読み込み
int CAudioBase::LoadSound(LPSTR szFilename, int loop_flag)
{
 int  i;

 // 空いているWaveがあるか検索
 for (i=0; i<MAX_SOUND; i++) {
  if (pSourceVoice[i]==NULL) {
   break;
  }
 }
 if (i>=MAX_SOUND) {
  return -1;
 }

 // Waveファイル読み込み
 CAudioWave wav;
 if (FAILED(wav.Open(szFilename, NULL))) {
  return -1;
 }

 // Waveファイルのフォーマット取得
 WAVEFORMATEX* pwfx=wav.GetFormat();

 // サイズ計算
 DWORD cbWaveSize=wav.GetSize();

 // メモリにデータを乗せる
 pbWaveData[i]=new BYTE[cbWaveSize];
 if (FAILED(wav.Read(pbWaveData[i], cbWaveSize, &cbWaveSize))) {
  SAFE_DELETE_ARRAY(pbWaveData[i]);
  return -1;
 }

 // ソースボイス生成
 if (FAILED(pXAudio2->CreateSourceVoice(&pSourceVoice[i], pwfx))) {
  SAFE_DELETE_ARRAY(pbWaveData[i]);
  return -1;
 }

 if (loop_flag!=0) {
  loop_flag=XAUDIO2_LOOP_INFINITE;
 }

 // オーディオバッファ設定
 pXAudioBuffer[i]=new XAUDIO2_BUFFER;
 pXAudioBuffer[i]->Flags=XAUDIO2_END_OF_STREAM;
 pXAudioBuffer[i]->AudioBytes=cbWaveSize;
 pXAudioBuffer[i]->pAudioData=pbWaveData[i];
 pXAudioBuffer[i]->PlayBegin=0;
 pXAudioBuffer[i]->PlayLength=0;
 pXAudioBuffer[i]->LoopBegin=0;
 pXAudioBuffer[i]->LoopLength=0;
 pXAudioBuffer[i]->LoopCount=loop_flag;
 if (FAILED(pSourceVoice[i]->SubmitSourceBuffer(pXAudioBuffer[i]))) {
  pSourceVoice[i]->DestroyVoice();
  SAFE_DELETE_ARRAY(pbWaveData[i]);
  return -1;
 }

 return i;
}
//--------------------------------------------------------------------------------------
// サウンド再生
void CAudioBase::PlaySound(int no)
{
 if (no==-1 || pSourceVoice[no]==NULL) {
  return;
 }
 StopSound(no);
 pSourceVoice[no]->FlushSourceBuffers();
 pSourceVoice[no]->SubmitSourceBuffer(pXAudioBuffer[no]);
 HRESULT hr=pSourceVoice[no]->Start(0);
}
//--------------------------------------------------------------------------------------
// サウンド停止
void CAudioBase::StopSound(int no)
{
 if (no==-1 || pSourceVoice[no]==NULL) {
  return;
 }

 pSourceVoice[no]->Stop(0);
}

コメントを残す

メールアドレスが公開されることはありません。