前にXACT3でWaveを再生する処理を書きましたが、いちいち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);
}