📄 asl_audio.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 + -