2010-09-29 17:29:43 +08:00
|
|
|
#include "SimpleAudioEngine.h"
|
|
|
|
|
|
|
|
#define BREAK_IF(cond) if (cond) break;
|
|
|
|
|
|
|
|
unsigned int BKDRHash(const char *str)
|
|
|
|
{
|
2010-10-09 10:47:09 +08:00
|
|
|
unsigned int seed = 31; // 31 131 1313 13131 131313 etc..
|
2010-09-29 17:29:43 +08:00
|
|
|
unsigned int hash = 0;
|
|
|
|
|
|
|
|
while (*str)
|
|
|
|
{
|
|
|
|
hash = hash * seed + (*str++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (hash & 0x7FFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static SimpleAudioEngine s_SharedAudioEngie;
|
|
|
|
|
|
|
|
SimpleAudioEngine::SimpleAudioEngine()
|
|
|
|
: m_nBackgroundMusicVolume(100)
|
|
|
|
, m_nEffectsVolume(100)
|
|
|
|
, m_bWillPlayBackgroundMusic(false)
|
|
|
|
, m_pEffects(NULL)
|
|
|
|
{
|
2010-10-11 16:21:20 +08:00
|
|
|
m_pEffectPlayers = new PlayerArray();
|
2010-09-29 17:29:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SimpleAudioEngine::~SimpleAudioEngine()
|
|
|
|
{
|
|
|
|
removeAllEffects();
|
|
|
|
removeAllEffectPlayers();
|
|
|
|
}
|
|
|
|
|
|
|
|
SimpleAudioEngine* SimpleAudioEngine::getSharedSimpleAudioEngine()
|
|
|
|
{
|
|
|
|
return &s_SharedAudioEngie;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
|
|
|
|
{
|
|
|
|
if (bLoop)
|
|
|
|
{
|
|
|
|
m_obBackPlayer.PlaySoundFile(pszFilePath, -1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_obBackPlayer.PlaySoundFile(pszFilePath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::stopBackgroundMusic()
|
|
|
|
{
|
|
|
|
m_obBackPlayer.Stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::pauseBackgroundMusic()
|
|
|
|
{
|
|
|
|
m_obBackPlayer.Pause();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::resumeBackgroundMusic()
|
|
|
|
{
|
|
|
|
m_obBackPlayer.Resume();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::rewindBackgroundMusic()
|
|
|
|
{
|
|
|
|
m_obBackPlayer.Rewind();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SimpleAudioEngine::willPlayBackgroundMusic()
|
|
|
|
{
|
|
|
|
return m_bWillPlayBackgroundMusic;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SimpleAudioEngine::isBackgroundMusicPlaying()
|
|
|
|
{
|
|
|
|
return m_obBackPlayer.IsPlaying();
|
|
|
|
}
|
|
|
|
|
|
|
|
// properties
|
|
|
|
int SimpleAudioEngine::GetBackgroundMusicVolume()
|
|
|
|
{
|
|
|
|
return m_nBackgroundMusicVolume;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::SetBackgroundMusicVolume(int volume)
|
|
|
|
{
|
|
|
|
m_obBackPlayer.SetVolumeValue(volume);
|
|
|
|
m_nBackgroundMusicVolume = volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SimpleAudioEngine::GetEffectsVolume()
|
|
|
|
{
|
|
|
|
return m_nEffectsVolume;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::SetEffectsVolume(int volume)
|
|
|
|
{
|
|
|
|
PlayerArrayIterator iter;
|
|
|
|
|
2010-10-11 16:21:20 +08:00
|
|
|
for (iter = m_pEffectPlayers->begin(); iter != m_pEffectPlayers->end(); ++iter)
|
2010-09-29 17:29:43 +08:00
|
|
|
{
|
|
|
|
if (*iter)
|
|
|
|
{
|
|
|
|
(*iter)->SetVolumeValue(volume);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_nEffectsVolume = volume;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// for sound effects
|
|
|
|
int SimpleAudioEngine::playEffect(const char* pszFilePath)
|
|
|
|
{
|
|
|
|
int nSoundID = preloadEffect(pszFilePath);
|
|
|
|
|
|
|
|
if (nSoundID > 0)
|
|
|
|
{
|
|
|
|
playPreloadedEffect(nSoundID);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nSoundID;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::stopEffect(int nSoundId)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// find the data in hash map
|
|
|
|
tHashElement* pElement = NULL;
|
|
|
|
HASH_FIND_INT(m_pEffects, &nSoundId, pElement);
|
|
|
|
BREAK_IF(!pElement);
|
|
|
|
|
|
|
|
// get the pointer of the player
|
|
|
|
SoundPlayer* pPlayer = pElement->pPlayer;
|
|
|
|
BREAK_IF(!pPlayer);
|
|
|
|
|
|
|
|
// stop play add set no player playing nSoundID
|
|
|
|
pPlayer->Stop();
|
|
|
|
pElement->pPlayer = NULL;
|
|
|
|
} while (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int SimpleAudioEngine::preloadEffect(const char* pszFilePath)
|
|
|
|
{
|
|
|
|
SoundPlayer TempPlayer;
|
|
|
|
int nSoundID = 0;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// calculate the hash value of the file name
|
|
|
|
nSoundID = BKDRHash(pszFilePath);
|
|
|
|
|
|
|
|
// if we have loaded the file before,break
|
|
|
|
tHashElement *pElement = NULL;
|
|
|
|
HASH_FIND_INT(m_pEffects, &nSoundID, pElement);
|
|
|
|
BREAK_IF(pElement);
|
|
|
|
|
|
|
|
// calculate the buffer size we needed
|
|
|
|
int nBufferSize = TempPlayer.GetFileBufferSize(pszFilePath);
|
|
|
|
if (nBufferSize < 0)
|
|
|
|
{
|
|
|
|
// can not calculate the size,load failed
|
|
|
|
nSoundID = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// load the file data
|
|
|
|
unsigned char* buffer = NULL;
|
|
|
|
buffer = new unsigned char[nBufferSize];
|
|
|
|
if (!buffer)
|
|
|
|
{
|
|
|
|
nSoundID = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
int nSize = TempPlayer.DecodeFile(buffer, nBufferSize, pszFilePath);
|
|
|
|
if (nSize < 0)
|
|
|
|
{
|
|
|
|
nSoundID = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// add the data to hash map
|
|
|
|
pElement = (tHashElement*)calloc(sizeof(*pElement), 1);
|
|
|
|
pElement->nSoundID = nSoundID;
|
|
|
|
pElement->pDataBuffer = buffer;
|
|
|
|
pElement->pPlayer = NULL;
|
|
|
|
pElement->nDataSize = nBufferSize;
|
|
|
|
HASH_ADD_INT(m_pEffects, nSoundID, pElement);
|
|
|
|
} while (0);
|
|
|
|
|
|
|
|
return nSoundID;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::unloadEffect(int nSoundId)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
tHashElement* pElement = NULL;
|
|
|
|
HASH_FIND_INT(m_pEffects, &nSoundId, pElement);
|
|
|
|
BREAK_IF(!pElement);
|
|
|
|
|
|
|
|
delete [] (pElement->pDataBuffer);
|
|
|
|
HASH_DEL(m_pEffects, pElement);
|
2010-09-30 11:25:15 +08:00
|
|
|
free(pElement);
|
2010-09-29 17:29:43 +08:00
|
|
|
} while (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::playPreloadedEffect(int nSoundId)
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
tHashElement* pElement = NULL;
|
|
|
|
HASH_FIND_INT(m_pEffects, &nSoundId, pElement);
|
|
|
|
BREAK_IF(!pElement);
|
|
|
|
|
|
|
|
SoundPlayer* pPlayer = pElement->pPlayer;
|
2010-10-12 15:55:56 +08:00
|
|
|
if (pPlayer && !pPlayer->IsPlaying())
|
|
|
|
{
|
|
|
|
// there has a player loaded the effect
|
|
|
|
pPlayer->Rewind();
|
|
|
|
}
|
|
|
|
else
|
2010-09-29 17:29:43 +08:00
|
|
|
{
|
2010-10-11 16:21:20 +08:00
|
|
|
// find the not playing player in m_pEffectPlayers
|
2010-09-29 17:29:43 +08:00
|
|
|
PlayerArrayIterator iter;
|
2010-10-11 16:21:20 +08:00
|
|
|
for (iter = m_pEffectPlayers->begin(); iter != m_pEffectPlayers->end(); ++iter)
|
2010-09-29 17:29:43 +08:00
|
|
|
{
|
|
|
|
if ((*iter) && !(*iter)->IsPlaying())
|
|
|
|
{
|
|
|
|
pPlayer = (*iter);
|
2010-10-12 15:55:56 +08:00
|
|
|
|
|
|
|
// Detach from the SoundID before
|
|
|
|
int nCurrentID = pPlayer->GetCurrentSoundID();
|
|
|
|
if (nCurrentID)
|
|
|
|
{
|
|
|
|
tHashElement* pTempElement = NULL;
|
|
|
|
HASH_FIND_INT(m_pEffects, &nCurrentID, pTempElement);
|
|
|
|
|
|
|
|
if (pTempElement)
|
|
|
|
{
|
|
|
|
pTempElement->pPlayer = NULL;
|
|
|
|
}
|
|
|
|
}
|
2010-09-29 17:29:43 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// not find player,new one player
|
|
|
|
if (!pPlayer)
|
|
|
|
{
|
|
|
|
pPlayer = new SoundPlayer();
|
2010-10-11 16:21:20 +08:00
|
|
|
m_pEffectPlayers->push_back(pPlayer);
|
2010-09-30 11:25:15 +08:00
|
|
|
|
|
|
|
// set the player volume
|
|
|
|
pPlayer->SetVolumeValue(m_nEffectsVolume);
|
2010-09-29 17:29:43 +08:00
|
|
|
}
|
|
|
|
|
2010-10-12 15:55:56 +08:00
|
|
|
// play the sound and record the player
|
|
|
|
pPlayer->PlaySoundFromMem(pElement->pDataBuffer, pElement->nDataSize);
|
|
|
|
pElement->pPlayer = pPlayer;
|
|
|
|
pPlayer->SetCurrentSoundID(nSoundId);
|
|
|
|
}
|
2010-09-29 17:29:43 +08:00
|
|
|
} while (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::removeAllEffects()
|
|
|
|
{
|
|
|
|
for (tHashElement *pElement = m_pEffects; pElement != NULL; )
|
|
|
|
{
|
2010-09-30 11:25:15 +08:00
|
|
|
int nSoundID = pElement->nSoundID;
|
2010-09-29 17:29:43 +08:00
|
|
|
pElement = (tHashElement*)pElement->hh.next;
|
2010-09-30 11:25:15 +08:00
|
|
|
unloadEffect(nSoundID);
|
2010-09-29 17:29:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SimpleAudioEngine::removeAllEffectPlayers()
|
|
|
|
{
|
|
|
|
PlayerArrayIterator iter;
|
|
|
|
|
2010-10-11 16:21:20 +08:00
|
|
|
for (iter = m_pEffectPlayers->begin(); iter != m_pEffectPlayers->end(); ++iter)
|
2010-09-29 17:29:43 +08:00
|
|
|
{
|
|
|
|
if (*iter)
|
|
|
|
{
|
|
|
|
delete *iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-11 16:21:20 +08:00
|
|
|
m_pEffectPlayers->clear();
|
|
|
|
delete m_pEffectPlayers;
|
2010-09-29 17:29:43 +08:00
|
|
|
}
|