前回に引き続きサウンド処理です。古いDirectSoundを使うか、新しいXAudio2を使うか迷ったのですが、やっぱり新しい方でやる事にしました。
しかしネットで検索してもあまり情報が無いね。新しいと言っても数年前のものなのに。リファレンスとサンプルプログラムで調べたのですが、物凄く面倒です。サウンドファイルを自前で解析してライブラリに投げる方式のようで、サンプルではCWaveFileという独自クラスで解析してました。なのでCWaveFileをいじってたんだけど、いまいち良くわからず。
さらに調べてたらXACT3というライブラリがXAudio2のラッパーであると知る。ラッパー使った方が楽じゃんという訳で、XACT3をいじってたのですが、こっちも資料が少なくて難航する。
さらにさらに調べたらXACT3は元々XBOX用のなので、素材もゲーム機に特化したデータ形式に変換して使うのだとわかりました。つまり複数の音楽ファイルを1つに結合して(Waveバンク)、属性なんかを埋め込んだファイル(Soundバンク)にしないとダメだったのです。
以前のとは全然違うな…
だいぶ回り道をしたけど、ようやく音楽を鳴らすことが出来ました。以下はオーディオ基底クラスCAudioBaseです。1シーンにつき1ファイルって考えて設計したんだけど、もしかしたら変更になるかも。
//-----------------------------------------------------------------------------
// 生成
CAudioBase::CAudioBase()
{
 // いちおう
 pXACT3Engine=NULL;
 pbWaveBank=NULL;
 pbSoundBank=NULL;
}
//-----------------------------------------------------------------------------
// 解放
CAudioBase::~CAudioBase()
{
 Release();
}
//-----------------------------------------------------------------------------
// 初期化
BOOL CAudioBase::Init()
{
 XACT_RUNTIME_PARAMETERS  EngineParameters={0};
 if (pXACT3Engine!=NULL) {
  Release();
 }
 // COM初期化
 CoInitializeEx(NULL, COINIT_MULTITHREADED);
 // XACT3生成
 XACT3CreateEngine(0, &pXACT3Engine);
 // XACT3パラメータ
 pXACT3Engine->Initialize(&EngineParameters);
 return S_OK;
}
//-----------------------------------------------------------------------------
// 解放
void CAudioBase::Release()
{
 // XACT3解放
 if (pXACT3Engine!=NULL) {
  pXACT3Engine->ShutDown();
  pXACT3Engine->Release();
 }
 pXACT3Engine=NULL;
 // Soundバンク解放
 if (pbSoundBank!=NULL) {
  delete[] pbSoundBank;
 }
 pbSoundBank=NULL;
 // Waveバンク解放
 if (pbWaveBank!=NULL) {
  UnmapViewOfFile(pbWaveBank);
 }
 pbWaveBank=NULL;
 // COM解放
 CoUninitialize();
}
//-----------------------------------------------------------------------------
// ファイル読み込み
BOOL CAudioBase::LoadSound(PCSTR filename)
{
 HRESULT hr;
 HANDLE hFile;
 DWORD dwFileSize;
 HANDLE hMapFile;
 DWORD dwBytesRead;
 char pathfile[512];
 // Waveバンク生成
 hr=E_FAIL;
 sprintf_s(pathfile, 512, "data\%s.xwb", filename);
 hFile=CreateFile(pathfile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
 if (hFile!=INVALID_HANDLE_VALUE) {
  dwFileSize=GetFileSize(hFile, NULL);
  if (dwFileSize!=-1) {
   hMapFile=CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSize, NULL);
   if (hMapFile) {
    pbWaveBank=MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
    if (pbWaveBank) {
     hr=pXACT3Engine->CreateInMemoryWaveBank(pbWaveBank, dwFileSize, 0, 0, &pWaveBank);
    }
    CloseHandle(hMapFile);
   }
  }
  CloseHandle(hFile);
 }
 if (FAILED(hr)) {
  return E_FAIL;
 }
 // Soundバンク生成
 hr=E_FAIL;
 sprintf_s(pathfile, 512, "data\%s.xsb", filename);
 hFile=CreateFile(pathfile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
 if (hFile!=INVALID_HANDLE_VALUE) {
  dwFileSize=GetFileSize(hFile, NULL);
  if (dwFileSize!=-1) {
   pbSoundBank= new BYTE[dwFileSize];
   if (pbWaveBank) {
    if (0!=ReadFile(hFile, pbSoundBank, dwFileSize, &dwBytesRead, NULL)) {
     hr=pXACT3Engine->CreateSoundBank(pbSoundBank, dwFileSize, 0, 0, &pSoundBank);
    }
   }
  }
  CloseHandle(hFile);
 }
 if (FAILED(hr)) {
  return E_FAIL;
 }
 return S_OK;
}
//-----------------------------------------------------------------------------
// サウンド再生
void CAudioBase::PlaySound(PCSTR zap)
{
 XACTINDEX iIndex;
 iIndex=pSoundBank->GetCueIndex(zap);
 pSoundBank->Play(iIndex, 0, 0, NULL);
}
//-----------------------------------------------------------------------------
// サウンド停止
void CAudioBase::StopSound(PCSTR zap)
{
 XACTINDEX iIndex;
 iIndex=pSoundBank->GetCueIndex(zap);
 pSoundBank->Stop(iIndex, XACT_FLAG_SOUNDBANK_STOP_IMMEDIATE);
}