bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

xact3でwave再生

サウンドでも再生してみた。
微妙に設計に失敗してるけど気にしない。

使い方

// ゲームループのどこか
g_sound_mgr.doWork();

// アプリケーションのどこか
cSound* sound = g_sound_mgr.createSound("Sound/Sounds.xwb");
sound->play();
g_sound_mgr.destroySound(sound);

SoundData

#ifndef __SoundData_h__
#define __SoundData_h__

#include <xact3.h>

struct sSoundData
{
	IXACT3WaveBank*		pWaveBank;
	IXACT3SoundBank*	pSoundBank;
	XACTINDEX			XACTIndex;

	VOID*				pbWaveBank;
	VOID*				pbSoundBank;
};

#endif	// __SoundData_h__

iSound.h

#ifndef __iSound_h__
#define __iSound_h__

#include <xact3.h>

class cSoundManager;

class iSound
{
	friend class cSoundManager;
protected:
	virtual ~iSound() {}

public:
	virtual void play() = 0;
	virtual void stop() = 0;
};

#endif	// __iSound_h__

cSound.h

#ifndef __cSound_h__
#define __cSound_h__

#include "iSound.h"
#include "SoundData.h"

class cSound : public iSound
{
	friend class cSoundManager;

protected:
	cSound();
	virtual ~cSound();

public:
	void play();
	void stop();

	void setSoundData(sSoundData* data) { m_pData = data; }

protected:
	sSoundData* m_pData;
};

#endif	// __cSound_h__

cSound.cpp

#include "cSound.h"

cSound::cSound()
: m_pData( NULL )
{
}

cSound::~cSound()
{
	if(m_pData) {
		if(m_pData->pSoundBank) {
			m_pData->pSoundBank->Destroy();
			m_pData->pSoundBank = NULL;
		}
		if(m_pData->pWaveBank) {
			m_pData->pWaveBank->Destroy();
			m_pData->pWaveBank = NULL;
		}
		if(m_pData->pbSoundBank) {
			delete [] m_pData->pbSoundBank;
		}
		if(m_pData->pbWaveBank) {
			UnmapViewOfFile( m_pData->pbWaveBank );
		}

		HeapFree(GetProcessHeap(), 0, m_pData);
	}
}

void cSound::play()
{
#if 1
	if(m_pData->pWaveBank) {
		m_pData->pWaveBank->Play(0, 0, 0, 0, NULL);
	}
#else
	if(m_pData->pSoundBank) {
		m_pData->pSoundBank->Play(m_pData->XACTIndex, 0, 0, NULL);
	}
#endif
}

void cSound::stop()
{
	if(m_pData->pSoundBank) {
		m_pData->pSoundBank->Stop(m_pData->XACTIndex, 0);
	}
}

cSoundManager.h

#ifndef __cSoundManager_h__
#define __cSoundManager_h__

#include <xact3.h>
#include <tchar.h>

#include "SoundData.h"
#include "cSound.h"

class cSoundManager
{
public:
	static cSoundManager& GetInstance()
	{
		static cSoundManager s_Instance;
		return s_Instance;
	}

public:
	HRESULT init();
	void exit();

	void doWork();
	cSound* createSound(TCHAR* filename);
	void destroySound(iSound* sound);

protected:
	HRESULT loadWaveBank(TCHAR* filename, sSoundData* data);
	HRESULT loadSoundBank(TCHAR* filename, sSoundData* data);

private:
	cSoundManager();
	cSoundManager(const cSoundManager& rhs);
	cSoundManager& operator=(const cSoundManager& rhs);

private:
	IXACT3Engine*		m_pEngine;
};

#define g_sound_mgr cSoundManager::GetInstance()

#endif	// __cSoundManager_h__

cSoundManager

#include "cSoundManager.h"
#include "cSound.h"

#include <windows.h>

static bool DoesCommandLineContainAuditioinSwitch();

cSoundManager::cSoundManager()
: m_pEngine( NULL )
{
}

HRESULT cSoundManager::init()
{
	HRESULT hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
	if( SUCCEEDED( hr ) )
	{
		DWORD creationFlag = 0;
		hr = XACT3CreateEngine( creationFlag, &m_pEngine );
	}
	if( FAILED(hr) || m_pEngine == NULL )
	{
		return E_FAIL;
	}

	// Init
	XACT_RUNTIME_PARAMETERS xact_runtime_params = {0};
	xact_runtime_params.lookAheadTime = XACT_ENGINE_LOOKAHEAD_DEFAULT;
	hr = m_pEngine->Initialize( &xact_runtime_params );
	if( FAILED(hr) ) {
		return hr;
	}

	return hr;
}

void cSoundManager::exit()
{
	if( m_pEngine) {
		m_pEngine->ShutDown();
		m_pEngine->Release();
	}

	CoUninitialize();
}


void cSoundManager::doWork()
{
	if( m_pEngine) {
		m_pEngine->DoWork();
	}
}

cSound* cSoundManager::createSound(TCHAR* filename)
{
	sSoundData* data = static_cast<sSoundData*>(HeapAlloc(GetProcessHeap(), 0, sizeof(sSoundData)));
	if(NULL == data) {
		return NULL;
	}
	ZeroMemory(data, sizeof(sSoundData));

	// xwb
	HRESULT hr = loadWaveBank(filename, data);
	if(FAILED(hr)) {
		HeapFree(GetProcessHeap(), 0, data);
		return NULL;
	}
#if 0
	// xsb
	hr = loadSoundBank(filename, data);
	if(FAILED(hr)) {
		HeapFree(GetProcessHeap(), 0, data);
		return NULL;
	}
#endif

	cSound* sound = new cSound();
	if(sound) {
		sound->setSoundData(data);
	} else {
		HeapFree(GetProcessHeap(), 0, data);
	}

	return sound;
}

void cSoundManager::destroySound(iSound* sound)
{
	if(sound) {
		delete sound;
	}
}

HRESULT cSoundManager::loadWaveBank(TCHAR* filename, sSoundData* data)
{
	HRESULT hr = E_FAIL;
	if(NULL == data) {
		return hr;
	}

	HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if(hFile != INVALID_HANDLE_VALUE)
	{
		DWORD fileSize = GetFileSize(hFile, NULL);
		if(fileSize != -1)
		{
			HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, fileSize, NULL);
			if(hMapFile)
			{
				data->pbWaveBank = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
				if(data->pbWaveBank) {
					hr = m_pEngine->CreateInMemoryWaveBank( data->pbWaveBank, fileSize, 0, 0, &data->pWaveBank );
				}
				CloseHandle(hMapFile);
			}
		}
		CloseHandle(hFile);
	}
	else
	{
		DWORD error = 0;
		error = GetLastError();
		error = 0;
	}

	return hr;
}

HRESULT cSoundManager::loadSoundBank(TCHAR* filename, sSoundData* data)
{
	HRESULT hr = E_FAIL;
	if(NULL == data) {
		return hr;
	}

	HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if(hFile != INVALID_HANDLE_VALUE)
	{
		DWORD fileSize = GetFileSize(hFile, NULL);
		if(fileSize != -1)
		{
			data->pbSoundBank = new BYTE[fileSize];
			if(data->pbSoundBank)
			{
				DWORD bytesRead;
				if(0 != ReadFile(hFile, data->pbSoundBank, fileSize, &bytesRead, NULL))
				{
					hr = m_pEngine->CreateSoundBank(data->pbSoundBank, fileSize, 0, 0, &data->pSoundBank);
				}
			}
		}
		CloseHandle(hFile);
	}

	return hr;
}