⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asl_audio.cpp

📁 泡泡堂单机版(含ASL游戏引擎源码 泡泡堂单机版(含ASL游戏引擎源码
💻 CPP
字号:
//-----------------------------------------------------------------------------
//
//    ____ Azure Star Game Engine 蓝星游戏引擎 ____
//
//    Copyright (c) 2006, 蓝星工作室
//    All rights reserved.
//
//    文件名称: asl_audio.cpp
//    摘    要: 音频处理类实现
//
//    当前版本: 1.0
//    作    者: 汤  祺
//    创建日期: 2006-8-30
//
//-----------------------------------------------------------------------------

#include "asl_audio.h"

namespace ASL
{

//-----------------------------------------------------------------------------
//
// ASLAudio类实现部分
//
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::Instance()
// 功  能: 取全局唯一实例
// 参  数: [void] - 无
// 返回值: [ASLAudio&] - 全局唯一实例
//-----------------------------------------------------------------------------
	ASLAudio& ASLAudio::Instance(void)
{
	static ASLAudio instance;
	return instance;
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::ASLAudio()
// 功  能: 构造函数
// 参  数: [void] - 无
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
ASLAudio::ASLAudio(void)
: m_pLoader(NULL)
, m_pPerformance(NULL)
{
	HRESULT hr = CoInitialize(NULL);
    m_bCleanupCOM = SUCCEEDED(hr);
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::~ASLAudio()
// 功  能: 析构函数
// 参  数: [void] - 无
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
ASLAudio::~ASLAudio(void)
{
	// 释放所有声音
	std::list<ASLSound*>::iterator it;
	for (it = m_lstEffect.begin(); it != m_lstEffect.end(); ++it)
	{
		SAFE_DELETE(*it);
	}
	for (it = m_lstMusic.begin(); it != m_lstMusic.end(); ++it)
	{
		SAFE_DELETE(*it);
	}

	// 释放Loader和Performance
	SAFE_RELEASE(m_pLoader); 

    if (m_pPerformance != NULL)
    {
        m_pPerformance->Stop( NULL, NULL, 0, 0 );
        m_pPerformance->CloseDown();

        SAFE_RELEASE(m_pPerformance);
    }

	// 结束COM
    if (m_bCleanupCOM)
	{
        CoUninitialize();
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::Init()
// 功  能: 初始化
// 参  数: [hWnd] - 主窗口句柄
// 返回值: [void] - 无
//         失败则抛出ASLDirectMusicException异常
//-----------------------------------------------------------------------------
void ASLAudio::Init(HWND hWnd) throw(ASLDirectMusicException)
{
	HRESULT hr;
 
    // 创建Loader对象
	hr = CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, 
		IID_IDirectMusicLoader8, (void**)&m_pLoader);
	if (FAILED(hr))
	{
		throw ASLDirectMusicException("创建Loader对象失败", hr);
	}

    // 创建Performance对象
	hr = CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC,
		IID_IDirectMusicPerformance8, (void**)&m_pPerformance);
	if (FAILED(hr))
	{
		throw ASLDirectMusicException("创建Performance对象失败", hr);
	}

    // 初始化Performance
	hr = m_pPerformance->InitAudio(NULL, NULL, hWnd, DMUS_APATH_DYNAMIC_STEREO,
		128, DMUS_AUDIOF_ALL, NULL);
	if (FAILED(hr))
	{
		throw ASLDirectMusicException("初始化Performance失败", hr);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::DestroySound()
// 功  能: 释放声音
// 参  数: [*pSound] - 待释放的声音
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLAudio::DestroySound(ASLSound *pSound)
{
	std::list<ASLSound*>::iterator it;
	for (it = m_lstEffect.begin(); it != m_lstEffect.end(); ++it)
	{
		if (pSound == (*it))
		{
			m_lstEffect.erase(it);
			return;
		}
	}
	for (it = m_lstMusic.begin(); it != m_lstMusic.end(); ++it)
	{
		if (pSound == (*it))
		{
			m_lstMusic.erase(it);
			return;
		}
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::SetDirCur()
// 功  能: 设置文件目录(相对于当前目录)
// 参  数: [szDir] - 音频目录
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLAudio::SetDirCur(LPCSTR szDir)
{
	WCHAR wszAudioPath[MAX_PATH];

	// 取音频文件夹的绝对路径并转为宽字符
	MultiByteToWideChar(CP_ACP, 0, szDir, -1, wszAudioPath, MAX_PATH);

	// 设置搜索目录
	m_pLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wszAudioPath, FALSE);
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::SetDirApp()
// 功  能: 设置文件目录(相对于当前目录)
// 参  数: [szDir] - 音频目录
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLAudio::SetDirApp(LPCSTR szDir)
{
	WCHAR wszAudioPath[MAX_PATH];

	// 取音频文件夹的绝对路径并转为宽字符
	MultiByteToWideChar(CP_ACP, 0, GetAbsPath(szDir), -1, wszAudioPath, MAX_PATH);

	// 设置搜索目录
	m_pLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wszAudioPath, FALSE);
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::StopAll()
// 功  能: 停止所有声音
// 参  数: [void] - 无
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLAudio::StopAll(void)
{
	if(m_pPerformance != NULL)
	{
        m_pPerformance->Stop(NULL, NULL, 0, 0);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::LoadSound()
// 功  能: 加载声音
// 参  数: [szFileName] - 声音文件名
//         [st] - 声音类型
//         [group] - 加载到何组
// 返回值: [ASLSound*] - 已加载的声音指针
//         失败则抛出ASLDirectMusicException异常
//-----------------------------------------------------------------------------
ASLSound* ASLAudio::LoadSound(LPCSTR szFileName, SoundType st, 
							  std::list<ASLSound*> &group)
							  throw(ASLDirectMusicException)
{
	HRESULT hr;
    IDirectMusicSegment8* pSegment = NULL;
	WCHAR wszFileName[MAX_PATH];
	ASLSound *pSound;

	ASSERT(st == stWave || st == stMidi);

	// 将文件名转为宽字符
	MultiByteToWideChar(CP_ACP, 0, szFileName, -1, wszFileName, MAX_PATH);

	// 加载音频文件到Segment
	hr = m_pLoader->LoadObjectFromFile(CLSID_DirectMusicSegment, 
		IID_IDirectMusicSegment8, wszFileName, (LPVOID*)&pSegment);
	if (FAILED(hr))
	{
		char szDesc[128];
		sprintf(szDesc, "加载文件 %s 时失败", szFileName);
		throw ASLDirectMusicException(szDesc, hr);
	}

	// 创建ASLSound对象
	pSound = new ASLSound(m_pPerformance, m_pLoader, pSegment);

	// 对MIDI文件做特殊处理
	if (st == stMidi)
	{
		pSegment->SetParam(GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, NULL);
	}

	group.push_back(pSound);

	return pSound;
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::SetGroupVolume()
// 功  能: 设置一组声音的音量
// 参  数: [fVolume] - 音量值, 0.0f ~ 1.0f
//         [group] - 待设置的组
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLAudio::SetGroupVolume(float fVolume, std::list<ASLSound*> &group)
{
	std::list<ASLSound*>::iterator it;
	for (it = group.begin(); it != group.end(); ++it)
	{
		(*it)->SetVolume(fVolume);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::EnableGroup()
// 功  能: 使一组声音有效
// 参  数: [&group] - 待设置的组
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLAudio::EnableGroup(std::list<ASLSound*> &group)
{
	std::list<ASLSound*>::iterator it;
	for (it = group.begin(); it != group.end(); ++it)
	{
		(*it)->Enable();
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLAudio::DisableGroup()
// 功  能: 使一组声音无效
// 参  数: [&group] - 待设置的组
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLAudio::DisableGroup(std::list<ASLSound*> &group)
{
	std::list<ASLSound*>::iterator it;
	for (it = group.begin(); it != group.end(); ++it)
	{
		(*it)->Disable();
	}
}



/******************************************************************************
 * ASLSound类实现部分
 ******************************************************************************/

//-----------------------------------------------------------------------------
// 函数名: ASLSound::ASLSound()
// 功  能: 构造函数
// 参  数: [pPerformance] - Performance对象指针
//         [pLoader] - Loader对象指针
//         [pSegment] - Segment对象指针
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
ASLSound::ASLSound(IDirectMusicPerformance8* pPerformance,
				   IDirectMusicLoader8* pLoader,
				   IDirectMusicSegment8* pSegment)
: m_pPerformance(pPerformance)
, m_pLoader(pLoader)
, m_pSegment(pSegment)
, m_pAudioPath(NULL)
, m_pSoundBuffer(NULL)
, m_bDownloaded(false)
{
	m_pPerformance->CreateStandardAudioPath(DMUS_APATH_DYNAMIC_STEREO, 
		128, TRUE, &m_pAudioPath);

	if (m_pAudioPath != NULL)
	{
		m_pAudioPath->GetObjectInPath(DMUS_PCHANNEL_ALL, DMUS_PATH_BUFFER, 0,
			GUID_NULL, 0, IID_IDirectSoundBuffer8, (LPVOID*)&m_pSoundBuffer);
	}
	if (m_pSoundBuffer != NULL)
	{
		m_pSoundBuffer->GetFrequency(&m_dwFrequency);
	}

	HRESULT hr;
	if (m_pAudioPath != NULL)
	{
		hr = m_pSegment->Download(m_pAudioPath);
	}
	else
	{
		hr = m_pSegment->Download(m_pPerformance);
	}

	if (SUCCEEDED(hr))
	{
		m_bDownloaded = true;
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::ASLSound()
// 功  能: 析构函数
// 参  数: [void] - 无
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
ASLSound::~ASLSound(void)
{
	if (m_pSegment != NULL)
    {
        if (m_pLoader != NULL)
		{
            m_pLoader->ReleaseObjectByUnknown(m_pSegment);
		}

		if (m_bDownloaded)
		{
			if (m_pAudioPath != NULL)
			{
				m_pSegment->Unload(m_pAudioPath);
			}
			else
			{
				m_pSegment->Unload(m_pPerformance);
			}
		}

        SAFE_RELEASE(m_pAudioPath); 
        SAFE_RELEASE(m_pSegment); 
		m_pSoundBuffer = NULL;
    }

    m_pPerformance = NULL;
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::Play()
// 功  能: 播放声音
// 参  数: [void] - 无
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLSound::Play(void)
{
	if (m_bEnabled && m_pPerformance != NULL && m_bDownloaded)
	{
		// m_pAudioPath为空时该函数会自动调用默认的AudioPath
		m_pPerformance->PlaySegmentEx(m_pSegment, 0, NULL, 
			DMUS_SEGF_SECONDARY, 0, 0, NULL, m_pAudioPath);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::Stop()
// 功  能: 停止播放
// 参  数: [void] - 无
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLSound::Stop(void)
{
	if (m_pSegment != NULL && m_pPerformance != NULL)
	{
		m_pPerformance->Stop(m_pSegment, NULL, 0, 0);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::IsPlaying()
// 功  能: 判断是否在播放
// 参  数: [void] - 无
// 返回值: [bool] - 是否在播放
//-----------------------------------------------------------------------------
bool ASLSound::IsPlaying(void)
{
	if (m_pSegment != NULL && m_pPerformance != NULL)
	{
		return m_pPerformance->IsPlaying(m_pSegment, NULL) == S_OK;
	}
	else
	{
		return false;
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::SetRepeats()
// 功  能: 设置重复播放次数
// 参  数: [dwRepeats] - 重复播放次数
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLSound::SetRepeats(DWORD dwRepeats)
{
	if (m_pSegment != NULL)
	{
		m_pSegment->SetRepeats(dwRepeats);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::SetVolume()
// 功  能: 设置音量
// 参  数: [fVolumn] - 音量值, 0.0f ~ 1.0f
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLSound::SetVolume(float fVolumn)
{
	if (m_pSoundBuffer != NULL)
	{
		fVolumn = max(0.0f, min(1.0f, fVolumn));
		LONG lVolumn = LONG((1 - fVolumn) * DSBVOLUME_MIN) / 2;
		m_pSoundBuffer->SetVolume(lVolumn);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::SetPan()
// 功  能: 设置声道均衡
// 参  数: [fPan] - 声道均衡值, -1.0f ~ 1.0f (左声道最强 ~ 右声道最强)
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLSound::SetPan(float fPan)
{
	if (m_pSoundBuffer != NULL)
	{
		fPan = max(-1.0f, min(1.0f, fPan));
		LONG lPan = LONG(fPan * DSBPAN_RIGHT);
		m_pSoundBuffer->SetPan(lPan);
	}
}

//-----------------------------------------------------------------------------
// 函数名: ASLSound::SetPitch()
// 功  能: 设置音调
// 参  数: [fPitch] - 音调倍数, 必须大于0, 值为1时以原音调播放
// 返回值: [void] - 无
//-----------------------------------------------------------------------------
void ASLSound::SetPitch(float fPitch)
{
	if (m_pSoundBuffer != NULL)
	{
		fPitch = max(0.0f, fPitch);
		DWORD dwFreq = DWORD(m_dwFrequency * fPitch);
		m_pSoundBuffer->SetFrequency(dwFreq);
	}
}

} // namespace ASL

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -