📄 audiomanager.cpp
字号:
// AudioManager.cpp: implementation of the CAudioManager class.
//
//////////////////////////////////////////////////////////////////////
#include "AudioManager.h"
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
#include "MikMod.h"
namespace AudioEngine {
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAudioManager::CAudioManager() : m_Listener()
{
m_InitGood = false;
m_Performance = NULL;
m_Loader = NULL;
m_NotificationHandler = NULL;
}
CAudioManager::~CAudioManager()
{
}
void CAudioManager::Init(HWND hwnd, bool stereo, int perfchannels)
{
HRESULT hr;
// initialize COM
hr = CoInitialize(NULL);
ThrowIfFailed(hr, "CAudioManager::Init: CoInitialize failed.");
// Create the loader
hr = CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC,
IID_IDirectMusicLoader8, (void**)&m_Loader);
ThrowIfFailed(hr, "CAudioManager::Init: CoCreateInstance for loader failed.");
// Create performance object
hr = CoCreateInstance( CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC,
IID_IDirectMusicPerformance8, (void**)&m_Performance);
ThrowIfFailed(hr, "CAudioManager::Init: CoCreateInstance for performance failed.");
hr = m_Performance->InitAudio(NULL, NULL, hwnd, stereo ? DMUS_APATH_DYNAMIC_STEREO : DMUS_APATH_DYNAMIC_MONO,
perfchannels, DMUS_AUDIOF_ALL, NULL);
if (hr == DSERR_NODRIVER) {
// output a warning message, then continue as usual
MessageBox(hwnd, "The program could not locate your audio hardware. Make sure your driver supports DirectX 8.", "Audio Engine", MB_ICONSTOP);
return; // notice we didn't set m_InitGood true
}
else ThrowIfFailed(hr, "CAudioManager::Init: m_Performance->InitAudio failed.");
// initialize mixer
m_Mixer.Init();
// add ALL notification messages (even though we may not do anything with some of them)
GUID guid;
/*
guid = GUID_NOTIFICATION_CHORD;
ThrowIfFailed(m_Performance->AddNotificationType(guid), "CAudioManager::Init: couldn't add CHORD notification type!");
guid = GUID_NOTIFICATION_COMMAND;
ThrowIfFailed(m_Performance->AddNotificationType(guid), "CAudioManager::Init: couldn't add COMMAND notification type!");
*/
guid = GUID_NOTIFICATION_MEASUREANDBEAT;
ThrowIfFailed(m_Performance->AddNotificationType(guid), "CAudioManager::Init: couldn't add MEASUREANDBEAT notification type!");
/*
guid = GUID_NOTIFICATION_PERFORMANCE;
ThrowIfFailed(m_Performance->AddNotificationType(guid), "CAudioManager::Init: couldn't add PERFORMANCE notification type!");
guid = GUID_NOTIFICATION_RECOMPOSE;
ThrowIfFailed(m_Performance->AddNotificationType(guid), "CAudioManager::Init: couldn't add RECOMPOSE notification type!");
guid = GUID_NOTIFICATION_SEGMENT;
ThrowIfFailed(m_Performance->AddNotificationType(guid), "CAudioManager::Init: couldn't add SEGMENT notification type!");
*/
// create event and tell DirectMusic about it
m_NotificationEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_Performance->SetNotificationHandle(m_NotificationEvent, 0); // hold messages for default of 2 seconds
// register MikMod drivers and init MikMod library
MikMod_RegisterAllDrivers();
MikMod_RegisterAllLoaders();
MikMod_Init("");
// get the listener buffer
IDirectMusicAudioPath8 *defaudiopath = NULL;
IDirectSound3DListener8 *listener;
hr = GetPerformance()->GetDefaultAudioPath(&defaudiopath);
ThrowIfFailed(hr, "CAudioManager::Init: can't get default audio path!");
hr = defaudiopath->GetObjectInPath(0, DMUS_PATH_PRIMARY_BUFFER, 0, GUID_NULL, 0,
IID_IDirectSound3DListener8, (LPVOID*) &listener);
ThrowIfFailed(hr, "CAudioManager::Init: can't get listener on default audio path!");
// tell our listener object to use this listener interface
GetListener().m_Listener = listener;
GetListener().RefreshProps();
Commit3DSoundParameters();
SAFE_RELEASE(defaudiopath);
m_InitGood = true;
}
void CAudioManager::UnInit()
{
// close notification handle and tell DirectMusic it's closed
CloseHandle(m_NotificationEvent);
m_Performance->SetNotificationHandle(NULL, 0);
// release performance
if(m_Performance != NULL) {
m_Performance->Stop( NULL, NULL, 0, 0 );
m_Performance->CloseDown();
SAFE_RELEASE( m_Performance );
}
SAFE_RELEASE( m_Loader );
// uninitialize mixer
m_Mixer.UnInit();
// UnInit MikMod
CTrackedMusic::FreeAllModules();
Player_Stop();
MikMod_Exit();
m_InitGood = false;
}
CSoundPtr CAudioManager::LoadSound(const CWAVFile &wavfile)
{
unsigned char *savedata = wavfile.Save();
// when you load a wave from memory, DirectMusic owns the memory pointer...
// do NOT delete!
return(LoadSound(savedata, wavfile.GetTotalSize()));
}
CSoundPtr CAudioManager::LoadSound(unsigned char *data, int datalen)
{
CSoundEffect *snd = new CSoundEffect(this);
LoadSegmentFromMemory(snd, data, datalen);
return(CSoundPtr(snd));
}
CSoundPtr CAudioManager::LoadSound(HMODULE hmod, char *type, WORD resID)
{
CSoundEffect *snd = new CSoundEffect(this);
LoadSegmentFromResource(snd, hmod, type, resID);
return(CSoundPtr(snd));
}
CSoundPtr CAudioManager::LoadSound(std::string filename)
{
CSoundEffect *snd = new CSoundEffect(this);
LoadSegmentFromDisk(snd, filename);
return(CSoundPtr(snd));
}
CSoundPtr CAudioManager::LoadMIDI(std::string filename)
{
CMIDIMusic *music = new CMIDIMusic(this);
LoadSegmentFromDisk(music, filename);
return(CSoundPtr(music));
}
CSoundPtr CAudioManager::LoadMIDI(unsigned char *data, int datalen)
{
CMIDIMusic *music = new CMIDIMusic(this);
LoadSegmentFromMemory(music, data, datalen);
return(CSoundPtr(music));
}
CSoundPtr CAudioManager::LoadMIDI(HMODULE hmod, char *type, WORD resID)
{
CMIDIMusic *music = new CMIDIMusic(this);
LoadSegmentFromResource(music, hmod, type, resID);
return(CSoundPtr(music));
}
CSoundPtr CAudioManager::LoadDynamicMusic(std::string filename)
{
CDynamicMusic *music = new CDynamicMusic(this);
LoadSegmentFromDisk(music, filename);
music->LoadMotifs();
return(CSoundPtr(music));
}
CSoundPtr CAudioManager::LoadDynamicMusic(unsigned char *data, int datalen)
{
CDynamicMusic *music = new CDynamicMusic(this);
LoadSegmentFromMemory(music, data, datalen);
music->LoadMotifs();
return(CSoundPtr(music));
}
CSoundPtr CAudioManager::LoadDynamicMusic(HMODULE hmod, char *type, WORD resID)
{
CDynamicMusic *music = new CDynamicMusic(this);
LoadSegmentFromResource(music, hmod, type, resID);
music->LoadMotifs();
return(CSoundPtr(music));
}
void CAudioManager::SetPerformanceGrooveLevelModifier(int value)
{
if (value > 100) value=100;
if (value < 0) value=0;
char v = value;
if (NULL == m_Performance) return;
ThrowIfFailed(m_Performance->SetGlobalParam(GUID_PerfMasterGrooveLevel, &v, sizeof(v)),
"CAudioManager::SetMasterGrooveLEvel: SetGlobalParam failed.");
}
int CAudioManager::GetPerformanceGrooveLevelModifier()
{
if (NULL == m_Performance) return(0);
char groove=0;
m_Performance->GetGlobalParam(GUID_PerfMasterGrooveLevel, &groove, sizeof(groove));
return(groove);
}
CSoundPtr CAudioManager::LoadMP3(std::string filename)
{
CMP3 *mp3 = new CMP3(this);
mp3->m_Tag = GetMP3AudioTag(filename);
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&mp3->m_GraphBuilder);
mp3->m_GraphBuilder->QueryInterface(IID_IMediaControl, (void **)&mp3->m_MediaControl);
mp3->m_GraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&mp3->m_MediaEventEx);
WCHAR widefilename[MAX_PATH];
DXUtil_ConvertGenericStringToWide( widefilename, filename.c_str());
mp3->m_GraphBuilder->RenderFile(widefilename, NULL);
return(CSoundPtr(mp3));
}
CMP3AudioTag CAudioManager::GetMP3AudioTag(std::string filename)
{
CMP3AudioTag tag;
tag.Read(filename);
return(tag);
}
CSoundPtr CAudioManager::LoadOggVorbis(std::string filename)
{
std::vector<unsigned char> pcmdata;
// this code is based on vorbisfile_example.c, included in the ogg distribution.
char pcmout[4096]; // ogg decoding buffer
OggVorbis_File vf;
int eof=0;
int current_section=0;
FILE *f = fopen(filename.c_str(), "rb");
if (f == NULL) { Throw("CAudioManager::LoadOggVorbis: could not open file."); }
if(ov_open(f, &vf, NULL, 0) < 0) {
Throw("CAudioManager::LoadOggVorbis: Input does not appear to be an Ogg bitstream.");
}
/* Throw the comments plus a few lines about the bitstream we're
decoding */
vorbis_info *vi=ov_info(&vf,-1);
// resize the pcmdata vector to the size of the ogg file
// two bytes per channel per sample
int samples = ov_pcm_total(&vf,-1);
int channels = vi->channels;
int samplerate = vi->rate;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -