1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Sound patches from Ubuntux #7 - #10:

* Some sound code cleanups
* Renamed soundBase::soundNames into soundBase::soundID
* Add a music handler destructor
* Add Archdevil and vampire pre and post movement sounds

I've applied minor change to fix CMusicHandler - GeniusAI conflict: moved sounds bimap to the .cpp file.

(vcmi_sounds_cleanup.diff
vcmi_sounds_cleanup2.diff
vcmi_sounds_cleanup3.diff
vcmi_add_sounds.diff)
This commit is contained in:
Michał W. Urbańczyk 2009-04-30 10:53:06 +00:00
parent 6ccd9c2701
commit df25dd7efb
14 changed files with 116 additions and 84 deletions

View File

@ -15,7 +15,7 @@ public:
void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID){}; void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID){};
void tileRevealed(int3 pos){}; void tileRevealed(int3 pos){};
void tileHidden(int3 pos){}; void tileHidden(int3 pos){};
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundNames soundID, bool selection, bool cancel){}; void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundID soundID, bool selection, bool cancel){};
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd){}; void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd){};
void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback); void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);
}; };

View File

@ -69,7 +69,7 @@ void GeniusAI::CGeniusAI::showGarrisonDialog( const CArmedInstance *up, const CG
onEnd(); onEnd();
} }
void CGeniusAI::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundNames soundID, bool selection, bool cancel ) void CGeniusAI::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundID soundID, bool selection, bool cancel )
{ {
m_cb->selectionMade(cancel ? 0 : 1, askID); m_cb->selectionMade(cancel ? 0 : 1, askID);
} }

View File

@ -190,7 +190,7 @@ public:
virtual void heroMoved(const HeroMoveDetails &); virtual void heroMoved(const HeroMoveDetails &);
virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val) {}; virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, int val) {};
virtual void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID){}; virtual void showSelDialog(std::string text, std::vector<CSelectableComponent*> & components, int askID){};
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundNames soundID, bool selection, bool cancel); virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundID soundID, bool selection, bool cancel);
virtual void tileRevealed(int3 pos){}; virtual void tileRevealed(int3 pos){};
virtual void tileHidden(int3 pos){}; virtual void tileHidden(int3 pos){};
virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback); virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback);

View File

@ -1095,6 +1095,8 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int d
if(startMoving) //animation of starting move; some units don't have this animation (ie. halberdier) if(startMoving) //animation of starting move; some units don't have this animation (ie. halberdier)
{ {
if (movedStack->creature->sounds.startMoving)
CGI->mush->playSound(movedStack->creature->sounds.startMoving);
handleStartMoving(number); handleStartMoving(number);
} }
if(moveStarted) if(moveStarted)
@ -1194,6 +1196,10 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int d
{ {
if(creAnims[number]->framesInGroup(21)!=0) // some units don't have this animation (ie. halberdier) if(creAnims[number]->framesInGroup(21)!=0) // some units don't have this animation (ie. halberdier)
{ {
if (movedStack->creature->sounds.endMoving) {
CGI->mush->playSound(movedStack->creature->sounds.endMoving);
}
creAnims[number]->setType(21); creAnims[number]->setType(21);
//for(int i=0; i<creAnims[number]->framesInGroup(21)*getAnimSpeedMultiplier()-1; ++i) //for(int i=0; i<creAnims[number]->framesInGroup(21)*getAnimSpeedMultiplier()-1; ++i)

View File

@ -80,10 +80,10 @@ public:
virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){}; virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town){};
virtual void init(ICallback * CB){}; virtual void init(ICallback * CB){};
virtual void receivedResource(int type, int val){}; virtual void receivedResource(int type, int val){};
virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, soundBase::soundNames soundID){}; virtual void showInfoDialog(const std::string &text, const std::vector<Component*> &components, soundBase::soundID soundID){};
//virtual void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){}; //virtual void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){};
//virtual void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){}; //virtual void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID){};
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const soundBase::soundNames soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const soundBase::soundID soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void tileHidden(const std::set<int3> &pos){}; virtual void tileHidden(const std::set<int3> &pos){};
virtual void tileRevealed(const std::set<int3> &pos){}; virtual void tileRevealed(const std::set<int3> &pos){};

View File

@ -2409,7 +2409,7 @@ void CPlayerInterface::showComp(SComponent comp)
adventureInt->infoBar.showComp(&comp,4000); adventureInt->infoBar.showComp(&comp,4000);
} }
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component*> &components, soundBase::soundNames soundID) void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<Component*> &components, soundBase::soundID soundID)
{ {
std::vector<SComponent*> intComps; std::vector<SComponent*> intComps;
for(int i=0;i<components.size();i++) for(int i=0;i<components.size();i++)
@ -2417,7 +2417,7 @@ void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector
showInfoDialog(text,intComps,soundID); showInfoDialog(text,intComps,soundID);
} }
void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, soundBase::soundNames soundID) void CPlayerInterface::showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, soundBase::soundID soundID)
{ {
{ {
boost::unique_lock<boost::mutex> un(showingDialog->mx); boost::unique_lock<boost::mutex> un(showingDialog->mx);
@ -2463,7 +2463,7 @@ void CPlayerInterface::showYesNoDialog(const std::string &text, const std::vecto
LOCPLINT->pushInt(temp); LOCPLINT->pushInt(temp);
} }
void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundNames soundID, bool selection, bool cancel ) void CPlayerInterface::showBlockingDialog( const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundID soundID, bool selection, bool cancel )
{ {
boost::unique_lock<boost::recursive_mutex> un(*pim); boost::unique_lock<boost::recursive_mutex> un(*pim);

View File

@ -592,10 +592,10 @@ public:
void heroMovePointsChanged(const CGHeroInstance * hero); void heroMovePointsChanged(const CGHeroInstance * hero);
void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town); void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town);
void receivedResource(int type, int val); void receivedResource(int type, int val);
void showInfoDialog(const std::string &text, const std::vector<Component*> &components, soundBase::soundNames soundID); void showInfoDialog(const std::string &text, const std::vector<Component*> &components, soundBase::soundID soundID);
//void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID); //void showSelDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID);
//void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID); //void showYesNoDialog(const std::string &text, const std::vector<Component*> &components, ui32 askID);
void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundNames soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, soundBase::soundID soundID, bool selection, bool cancel); //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd); void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, boost::function<void()> &onEnd);
void tileHidden(const std::set<int3> &pos); void tileHidden(const std::set<int3> &pos);
void tileRevealed(const std::set<int3> &pos); void tileRevealed(const std::set<int3> &pos);
@ -636,7 +636,7 @@ public:
void handleMouseMotion(SDL_Event *sEvent); void handleMouseMotion(SDL_Event *sEvent);
void init(ICallback * CB); void init(ICallback * CB);
int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on
void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, soundBase::soundNames soundID); void showInfoDialog(const std::string &text, const std::vector<SComponent*> & components, soundBase::soundID soundID);
void showYesNoDialog(const std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close void showYesNoDialog(const std::string &text, const std::vector<SComponent*> & components, CFunctionList<void()> onYes, CFunctionList<void()> onNo, bool DelComps); //deactivateCur - whether current main interface should be deactivated; delComps - if components will be deleted on window close
bool moveHero(const CGHeroInstance *h, CPath path); bool moveHero(const CGHeroInstance *h, CPath path);

View File

@ -266,7 +266,7 @@ void InfoWindow::applyCl( CClient *cl )
std::string str = toString(text); std::string str = toString(text);
if(vstd::contains(cl->playerint,player)) if(vstd::contains(cl->playerint,player))
cl->playerint[player]->showInfoDialog(str,comps,(soundBase::soundNames)soundID); cl->playerint[player]->showInfoDialog(str,comps,(soundBase::soundID)soundID);
else else
tlog2 << "We received InfoWindow for not our player...\n"; tlog2 << "We received InfoWindow for not our player...\n";
} }
@ -285,7 +285,7 @@ void BlockingDialog::applyCl( CClient *cl )
{ {
std::string str = toString(text); std::string str = toString(text);
if(vstd::contains(cl->playerint,player)) if(vstd::contains(cl->playerint,player))
cl->playerint[player]->showBlockingDialog(str,components,id,(soundBase::soundNames)soundID,selection(),cancel()); cl->playerint[player]->showBlockingDialog(str,components,id,(soundBase::soundID)soundID,selection(),cancel());
else else
tlog2 << "We received YesNoDialog for not our player...\n"; tlog2 << "We received YesNoDialog for not our player...\n";
} }

View File

@ -96,7 +96,7 @@ Monk MONKATTK.wav MONKDFND.wav MONKKILL.wav MONKMOVE.wav MONKSHOT.wav MONKWNCE.w
Mummy MUMYATTK.wav MUMYDFND.wav MUMYKILL.wav MUMYMOVE.wav invalid MUMYWNCE.wav Mummy MUMYATTK.wav MUMYDFND.wav MUMYKILL.wav MUMYMOVE.wav invalid MUMYWNCE.wav
NagaGuardian NGRDATTK.wav NGRDDFND.wav NGRDKILL.wav NGRDMOVE.wav invalid NGRDWNCE.wav NagaGuardian NGRDATTK.wav NGRDDFND.wav NGRDKILL.wav NGRDMOVE.wav invalid NGRDWNCE.wav
NagaSentinel NSENATTK.wav NSENDFND.wav NSENKILL.wav NSENMOVE.wav invalid NSENWNCE.wav NagaSentinel NSENATTK.wav NSENDFND.wav NSENKILL.wav NSENMOVE.wav invalid NSENWNCE.wav
Nosferatu NOSFATTK.wav NOSFDFND.wav NOSFEXT1.wav NOSFEXT2.wav NOSFKILL.wav NOSFMOVE.wav NOSFSHOT.wav NOSFWNCE.wav Nosferatu NOSFATTK.wav NOSFDFND.wav NOSFKILL.wav NOSFMOVE.wav NOSFSHOT.wav NOSFWNCE.wav NOSFEXT1.wav NOSFEXT2.wav
ObsidianGargoyle OGRGATTK.wav OGRGDFND.wav OGRGKILL.wav OGRGMOVE.wav invalid OGRGWNCE.wav ObsidianGargoyle OGRGATTK.wav OGRGDFND.wav OGRGKILL.wav OGRGMOVE.wav invalid OGRGWNCE.wav
Ogre OGREATTK.wav OGREDFND.wav OGREKILL.wav OGREMOVE.wav invalid OGREWNCE.wav Ogre OGREATTK.wav OGREDFND.wav OGREKILL.wav OGREMOVE.wav invalid OGREWNCE.wav
OgreMage OGRMATTK.wav OGRMDFND.wav OGRMKILL.wav OGRMMOVE.wav OGRMSHOT.wav OGRMWNCE.wav OgreMage OGRMATTK.wav OGRMDFND.wav OGRMKILL.wav OGRMMOVE.wav OGRMSHOT.wav OGRMWNCE.wav

View File

@ -107,6 +107,8 @@ void CCreatureHandler::loadCreatures()
ncre.sounds.wince = soundBase::invalid; ncre.sounds.wince = soundBase::invalid;
ncre.sounds.ext1 = soundBase::invalid; ncre.sounds.ext1 = soundBase::invalid;
ncre.sounds.ext2 = soundBase::invalid; ncre.sounds.ext2 = soundBase::invalid;
ncre.sounds.startMoving = soundBase::invalid;
ncre.sounds.endMoving = soundBase::invalid;
int befi=i; int befi=i;
for(i; i<andame; ++i) for(i; i<andame; ++i)

View File

@ -46,14 +46,16 @@ public:
// Sound infos // Sound infos
struct { struct {
soundBase::soundNames attack; soundBase::soundID attack;
soundBase::soundNames defend; soundBase::soundID defend;
soundBase::soundNames killed; // was killed died soundBase::soundID killed; // was killed died
soundBase::soundNames move; soundBase::soundID move;
soundBase::soundNames shoot; // range attack soundBase::soundID shoot; // range attack
soundBase::soundNames wince; // attacked but did not die soundBase::soundID wince; // attacked but did not die
soundBase::soundNames ext1; // creature specific extension soundBase::soundID ext1; // creature specific extension
soundBase::soundNames ext2; // creature specific extension soundBase::soundID ext2; // creature specific extension
soundBase::soundID startMoving; // usually same as ext1
soundBase::soundID endMoving; // usually same as ext2
} sounds; } sounds;
bool isDoubleWide() const; //returns true if unit is double wide on battlefield bool isDoubleWide() const; //returns true if unit is double wide on battlefield

View File

@ -3,6 +3,7 @@
#include <sstream> #include <sstream>
#include <boost/assign/std/vector.hpp> #include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp> #include <boost/assign/list_of.hpp>
#include <boost/bimap.hpp>
#include <SDL_mixer.h> #include <SDL_mixer.h>
@ -23,19 +24,44 @@
using namespace boost::assign; using namespace boost::assign;
boost::bimap<soundBase::soundID, std::string> sounds;
CMusicHandler::~CMusicHandler()
{
if (!audioInit)
return;
if (sndh) {
Mix_HaltChannel(-1);
delete sndh;
}
std::map<soundBase::soundID, Mix_Chunk *>::iterator it;
for (it=soundChunks.begin(); it != soundChunks.end(); it++) {
if (it->second)
Mix_FreeChunk(it->second);
}
Mix_CloseAudio();
}
void CMusicHandler::initMusics() void CMusicHandler::initMusics()
{ {
if (audioInit)
return;
if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)==-1) if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)==-1)
{ {
printf("Mix_OpenAudio error: %s!!!\n", Mix_GetError()); printf("Mix_OpenAudio error: %s!!!\n", Mix_GetError());
return; return;
} }
atexit(Mix_CloseAudio);
audioInit = true;
// Map sound names // Map sound names
#define VCMI_SOUND_NAME(x) ( soundBase::x, #define VCMI_SOUND_NAME(x) ( soundBase::x,
#define VCMI_SOUND_FILE(y) cachedSounds(#y, 0) ) #define VCMI_SOUND_FILE(y) #y )
sounds = boost::assign::map_list_of sounds = boost::assign::list_of<boost::bimap<soundBase::soundID, std::string>::relation>
VCMI_SOUND_LIST; VCMI_SOUND_LIST;
#undef VCMI_SOUND_NAME #undef VCMI_SOUND_NAME
#undef VCMI_SOUND_FILE #undef VCMI_SOUND_FILE
@ -49,11 +75,6 @@ void CMusicHandler::initMusics()
soundBase::horseSubterranean, soundBase::horseLava, soundBase::horseSubterranean, soundBase::horseLava,
soundBase::horseWater, soundBase::horseRock; soundBase::horseWater, soundBase::horseRock;
// Create reverse map. It's used during game init to map names to internal IDs
std::map<soundBase::soundNames, cachedSounds>::iterator it;
for ( it=sounds.begin() ; it != sounds.end(); it++ )
reverse_sounds[(*it).second.filename] = (*it).first;
//AITheme0 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITheme0.mp3"); //AITheme0 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITheme0.mp3");
//AITheme1 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITHEME1.mp3"); //AITheme1 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITHEME1.mp3");
//AITheme2 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITHEME2.mp3"); //AITheme2 = Mix_LoadMUS(DATA_DIR "MP3" PATHSEPARATOR "AITHEME2.mp3");
@ -101,33 +122,42 @@ void CMusicHandler::initMusics()
sndh = new CSndHandler(std::string(DATA_DIR "Data" PATHSEPARATOR "Heroes3.snd")); sndh = new CSndHandler(std::string(DATA_DIR "Data" PATHSEPARATOR "Heroes3.snd"));
} }
// Return an SDL chunk. Allocate if it is not cached yet. // Allocate an SDL chunk and cache it.
Mix_Chunk *CMusicHandler::GetSoundChunk(std::string srcName) Mix_Chunk *CMusicHandler::GetSoundChunk(soundBase::soundID soundID)
{ {
int size; // Find its name
const char *data = sndh->extract(srcName, size); boost::bimap<soundBase::soundID, std::string>::left_iterator it;
SDL_RWops *ops; it = sounds.left.find(soundID);
Mix_Chunk *chunk; if (it == sounds.left.end())
return NULL;
// Load and insert
int size;
const char *data = sndh->extract(it->second, size);
if (!data) if (!data)
return NULL; return NULL;
ops = SDL_RWFromConstMem(data, size); SDL_RWops *ops = SDL_RWFromConstMem(data, size);
Mix_Chunk *chunk;
chunk = Mix_LoadWAV_RW(ops, 1); // will free ops chunk = Mix_LoadWAV_RW(ops, 1); // will free ops
if (!chunk) if (!chunk) {
fprintf(stderr, "Unable to mix: %s\n", tlog1 << "Unable to mix sound" << it->second << "(" << Mix_GetError() << ")" << std::endl;
Mix_GetError()); return NULL;
}
soundChunks.insert(std::pair<soundBase::soundID, Mix_Chunk *>(soundID, chunk));
return chunk; return chunk;
} }
soundBase::soundNames CMusicHandler::getSoundID(std::string &fileName) // Get a soundID given a filename
soundBase::soundID CMusicHandler::getSoundID(std::string &fileName)
{ {
std::map<std::string, soundBase::soundNames>::iterator it; boost::bimap<soundBase::soundID, std::string>::right_iterator it;
it = reverse_sounds.find(fileName); it = sounds.right.find(fileName);
if (it == reverse_sounds.end()) if (it == sounds.right.end())
return soundBase::invalid; return soundBase::invalid;
else else
return it->second; return it->second;
@ -167,6 +197,15 @@ void CMusicHandler::initCreaturesSounds(std::vector<CCreature> &creatures)
c.sounds.wince = getSoundID(wince); c.sounds.wince = getSoundID(wince);
c.sounds.ext1 = getSoundID(ext1); c.sounds.ext1 = getSoundID(ext1);
c.sounds.ext2 = getSoundID(ext2); c.sounds.ext2 = getSoundID(ext2);
// Special creatures
if (c.idNumber == 55 || // Archdevil
c.idNumber == 62 || // Vampire
c.idNumber == 62) // Vampire Lord
{
c.sounds.startMoving = c.sounds.ext1;
c.sounds.endMoving = c.sounds.ext2;
}
} }
} }
ifs.close(); ifs.close();
@ -187,40 +226,32 @@ void CMusicHandler::initCreaturesSounds(std::vector<CCreature> &creatures)
} }
// Plays a sound, and return its channel so we can fade it out later // Plays a sound, and return its channel so we can fade it out later
int CMusicHandler::playSound(soundBase::soundNames soundID, int repeats) int CMusicHandler::playSound(soundBase::soundID soundID, int repeats)
{ {
int channel; int channel;
Mix_Chunk *chunk;
std::map<soundBase::soundID, Mix_Chunk *>::iterator it;
if (!sndh) if (!sndh)
return -1; return -1;
std::map<soundBase::soundNames, cachedSounds>::iterator it; chunk = GetSoundChunk(soundID);
it = sounds.find(soundID); if (chunk)
if (it == sounds.end())
return -1;
class cachedSounds sound = it->second;
if (!sound.chunk) {
sound.chunk = GetSoundChunk(sound.filename);
}
if (sound.chunk)
{ {
channel = Mix_PlayChannel(-1, sound.chunk, repeats); channel = Mix_PlayChannel(-1, chunk, repeats);
if(channel == -1) if (channel == -1)
{ tlog1 << "Unable to play sound file " << soundID << std::endl;
fprintf(stderr, "Unable to play WAV file("DATA_DIR "Data" PATHSEPARATOR "Heroes3.wav::%s): %s\n",
sound.filename.c_str(),Mix_GetError()); } else {
} channel = -1;
} }
return channel; return channel;
} }
// Helper. Randomly select a sound from an array and play it // Helper. Randomly select a sound from an array and play it
int CMusicHandler::playSoundFromSet(std::vector<soundBase::soundNames> &sound_vec) int CMusicHandler::playSoundFromSet(std::vector<soundBase::soundID> &sound_vec)
{ {
return playSound(sound_vec[rand() % sound_vec.size()]); return playSound(sound_vec[rand() % sound_vec.size()]);
} }

View File

@ -20,38 +20,29 @@ class CMusicHandler
{ {
private: private:
CSndHandler *sndh; CSndHandler *sndh;
soundBase::soundNames getSoundID(std::string &fileName); soundBase::soundID getSoundID(std::string &fileName);
class cachedSounds { std::map<soundBase::soundID, Mix_Chunk *> soundChunks;
public:
std::string filename;
Mix_Chunk *chunk;
// This is some horrible C++ abuse. Isn't there any way to do Mix_Chunk *GetSoundChunk(soundBase::soundID soundID);
// something simplier to init sounds?
cachedSounds(std::string filename_in, Mix_Chunk *chunk_in):
filename(filename_in), chunk(chunk_in) {};
};
std::map<soundBase::soundNames, cachedSounds> sounds; bool audioInit;
std::map<std::string, soundBase::soundNames> reverse_sounds;
Mix_Chunk *GetSoundChunk(std::string srcName);
public: public:
CMusicHandler(): sndh(NULL) {}; CMusicHandler(): sndh(NULL), audioInit(false) {};
~CMusicHandler();
void initMusics(); void initMusics();
void initCreaturesSounds(std::vector<CCreature> &creatures); void initCreaturesSounds(std::vector<CCreature> &creatures);
// Sounds // Sounds
int playSound(soundBase::soundNames soundID, int repeats=0); int playSound(soundBase::soundID soundID, int repeats=0);
int playSoundFromSet(std::vector<soundBase::soundNames> &sound_vec); int playSoundFromSet(std::vector<soundBase::soundID> &sound_vec);
void stopSound(int handler); void stopSound(int handler);
// Sets // Sets
std::vector<soundBase::soundNames> pickup_sounds; std::vector<soundBase::soundID> pickup_sounds;
std::vector<soundBase::soundNames> horseSounds; std::vector<soundBase::soundID> horseSounds;
}; };
#endif // __CMUSICHANDLER_H__ #endif // __CMUSICHANDLER_H__

View File

@ -1026,7 +1026,7 @@ public:
// We must keep an entry 0 for an invalid or no sound. // We must keep an entry 0 for an invalid or no sound.
#define VCMI_SOUND_NAME(x) x, #define VCMI_SOUND_NAME(x) x,
#define VCMI_SOUND_FILE(y) #define VCMI_SOUND_FILE(y)
enum soundNames { enum soundID {
invalid=0, invalid=0,
sound_todo=1, // temp entry until code is fixed sound_todo=1, // temp entry until code is fixed
VCMI_SOUND_LIST VCMI_SOUND_LIST