前回に引き続きサウンド処理です。古い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);
}