1
0
forked from 0ad/0ad

#Added Sound Group Manager, updated Sound Groups.

refs #138.  Added SoundGroupMgr.h and .cpp, revised loading and clean up
in SoundGroup class.

This was SVN commit r4761.
This commit is contained in:
nd3c3nt 2007-01-13 16:00:52 +00:00
parent e0a6c50ce1
commit 0b150ee311
4 changed files with 378 additions and 36 deletions

View File

@ -8,6 +8,19 @@
* Author : Gavin Fowler
* =========================================================================
*/
/*
* Copyright (c) 2005-2006 Gavin Fowler
*
* Redistribution and/or modification are also permitted under the
* terms of the GNU General Public License as published by the
* Free Software Foundation (version 2 or later, at your option).
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "precompiled.h"
#include <algorithm>
@ -28,6 +41,9 @@ CSoundGroup::CSoundGroup()
{
m_index = 0;
m_Flags = 0;
m_Intensity = 0;
m_CurTime = 0.0f;
}
@ -35,6 +51,8 @@ CSoundGroup::CSoundGroup(const char *XMLfile)
{
m_index = 0;
m_Flags = 0;
m_Intensity = 0;
m_CurTime = 0.0f;
LoadSoundGroup(XMLfile);
}
@ -47,59 +65,122 @@ CSoundGroup::~CSoundGroup()
void CSoundGroup::PlayNext()
{
if(m_Intensity >= m_IntensityThreshold)
{
if(!is_playing(m_hReplacement))
{
// load up replacement file
m_hReplacement = snd_open(m_filepath + m_intensity_file);
snd_set_gain(m_hReplacement, m_Gain);
snd_set_pitch(m_hReplacement, m_Pitch);
snd_set_cone(m_hReplacement, m_ConeInnerAngle, m_ConeOuterAngle, m_ConeOuterGain);
//if(this->m_intensity_threshold)
//for(size_t i = 0; i < m_index; i++)
//{
// //H_USER_DATA(snd_group[i], H_Sound);
//}
//check for randomization of pitch and gain
if(TestFlag(eRandPitch))
snd_set_pitch(snd_group[m_index], (float)((rand(m_PitchLower * 100.0f, m_PitchUpper * 100.0f) / 100.0f)));
if(TestFlag(eRandGain))
snd_set_gain(snd_group[m_index], (float)((rand(m_GainLower * 100.0f, m_GainUpper * 100.0f) / 100.0f)));
//check for randomization of pitch and gain
if(TestFlag(eRandPitch))
snd_set_pitch(snd_group[m_index], (float)((rand(m_PitchLower * 100.0f, m_PitchUpper * 100.0f) / 100.0f)));
if(TestFlag(eRandGain))
snd_set_gain(snd_group[m_index], (float)((rand(m_GainLower * 100.0f, m_GainUpper * 100.0f) / 100.0f)));
snd_play(m_hReplacement, m_Priority);
}
}
else
{
// try loading on the fly only when we need the sound to see if that fixes release problems...
if(TestFlag(eRandOrder))
m_index = (size_t)rand(0, filenames.size());
Handle temp;
temp = snd_open(m_filepath + filenames[m_index]);
snd_set_gain(temp, m_Gain);
snd_set_pitch(temp, m_Pitch);
snd_set_cone(temp, m_ConeInnerAngle, m_ConeOuterAngle, m_ConeOuterGain);
//check for randomization of pitch and gain
if(TestFlag(eRandPitch))
snd_set_pitch(temp, (float)((rand(m_PitchLower * 100.0f, m_PitchUpper * 100.0f) / 100.0f)));
//snd_set_pitch(snd_group[m_index], (float)((rand(m_PitchLower * 100.0f, m_PitchUpper * 100.0f) / 100.0f)));
if(TestFlag(eRandGain))
snd_set_gain(temp, (float)((rand(m_GainLower * 100.0f, m_GainUpper * 100.0f) / 100.0f)));
//snd_set_gain(snd_group[m_index], (float)((rand(m_GainLower * 100.0f, m_GainUpper * 100.0f) / 100.0f)));
snd_play(snd_group[m_index], m_Priority);
snd_play(temp, m_Priority);
//snd_play(snd_group[m_index], m_Priority);
}
playtimes[m_index] = 0.0f;
m_index++;
if(m_index >= snd_group.size())
m_Intensity++;
if(m_Intensity > m_IntensityThreshold)
m_Intensity = m_IntensityThreshold;
if(m_index >= filenames.size())
Reload();
}
void CSoundGroup::Reload()
{
m_index = 0; // reset our static index
m_index = 0; // reset our index
// get rid of the used handles
snd_group.clear();
// clear out the old timers
playtimes.clear();
//Reload the sounds
for(size_t i = 0; i < filenames.size(); i++)
/*for(size_t i = 0; i < filenames.size(); i++)
{
string szTemp = m_filepath + filenames[i];
Handle temp = snd_open(m_filepath + filenames[i]);
snd_set_gain(temp, m_Gain);
snd_set_pitch(temp, m_Pitch);
snd_set_cone(temp, m_ConeInnerAngle, m_ConeOuterAngle, m_ConeOuterGain);
snd_group.push_back(temp);
}
if(TestFlag(eRandOrder))
random_shuffle(snd_group.begin(), snd_group.end());
snd_group.push_back(temp);
}*/
while(playtimes.size() < filenames.size())
playtimes.push_back(-1.0f);
//if(TestFlag(eRandOrder))
//random_shuffle(snd_group.begin(), snd_group.end());
}
void CSoundGroup::ReleaseGroup()
{
for(size_t i = m_index; i<snd_group.size(); i++)
snd_free(snd_group[i]);
{
//if(!is_playing(snd_group[i]))
snd_free(snd_group[i]);
}
snd_group.clear();
playtimes.clear();
//if(is_playing(m_hReplacement))
// snd_free(m_hReplacement);
m_index = 0;
}
void CSoundGroup::Update(float TimeSinceLastFrame)
{
for(size_t i = 0; i < playtimes.size(); i++)
{
if(playtimes[i] >= 0.0f)
playtimes[i] += TimeSinceLastFrame;
if(playtimes[i] >= m_Decay)
{
playtimes[i] = -1.0f;
m_Intensity--;
}
}
}
bool CSoundGroup::LoadSoundGroup(const char *XMLfile)
{
@ -132,6 +213,7 @@ bool CSoundGroup::LoadSoundGroup(const char *XMLfile)
EL(pitchlower);
EL(path);
EL(threshold);
EL(decay);
EL(replacement);
#undef AT
#undef EL
@ -239,9 +321,16 @@ bool CSoundGroup::LoadSoundGroup(const char *XMLfile)
}
if(child_name == el_threshold)
{
m_intensity_threshold = CStr(child.getText()).ToFloat();
//m_intensity_threshold = CStr(child.getText()).ToFloat();
m_IntensityThreshold = CStr(child.getText()).ToFloat();
}
if(child_name == el_decay)
{
//m_intensity_threshold = CStr(child.getText()).ToFloat();
m_Decay = CStr(child.getText()).ToFloat();
}
if(child_name == el_replacement)
{
m_intensity_file = child.getText();

View File

@ -8,13 +8,22 @@
* Author : Gavin Fowler
* =========================================================================
*/
/*
Example usage:
CSoundGroup s;
s.LoadSoundGroup("SoundGroup.xml"); // only needs to be called once (or not at all if filename is passed to ctor)
s.PlayNext(); // call each time you want to play another sound from the group.
s.ReleaseGroup(); // If you want to free up the resources early, but this happens in dtor.
/*
* Copyright (c) 2005-2006 Gavin Fowler
*
* Redistribution and/or modification are also permitted under the
* terms of the GNU General Public License as published by the
* Free Software Foundation (version 2 or later, at your option).
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
Example usage: (SEE SOUNDGROUPMGR.H)
Example SoundGroup.xml
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
@ -55,20 +64,26 @@ enum eSndGrpFlags
eLoop = 0x08
};
class CSoundGroup
{
size_t m_index; // index of the next sound to play
Handle m_hReplacement;
vector<Handle> snd_group; // we store the handles so we can load now and play later
vector<CStr> filenames; // we need the filenames so we can reload when necessary.
vector<float> playtimes; // it would be better to store this in with the Handles perhaps?
CStr m_filepath; // the file path for the list of sound file resources
CStr m_intensity_file; // this will be either the name of a new sound file or new sound group
size_t m_intensity_threshold;
CStr m_intensity_file; // the replacement aggregate 'intense' sound
float m_CurTime; // Time elapsed since soundgroup was created
float m_TimeWindow; // The Intensity Threshold Window
size_t m_IntensityThreshold; // the allowable intensity before a sound switch
size_t m_Intensity; // our current intensity(number of sounds played since m_CurTime - m_TimeWindow)
float m_Decay; //
unsigned char m_Flags; // up to eight individual parameters, use with eSndGrpFlags.
float m_Gain;
float m_Pitch;
float m_Priority;
@ -95,6 +110,9 @@ public:
// Release all remaining loaded handles
void ReleaseGroup();
// Update SoundGroup, remove dead sounds from intensity count
void Update(float TimeSinceLastFrame);
// Set a flag using a value from eSndGrpFlags
inline void SetFlag(int flag){ m_Flags |= flag; }

View File

@ -0,0 +1,156 @@
/**
* =========================================================================
* File : SoundGroupMgr.h
* Project : 0 A.D.
* Description : Manages and updates SoundGroups
*
* Author : Gavin Fowler
* =========================================================================
*/
/*
* Copyright (c) 2005-2006 Gavin Fowler
*
* Redistribution and/or modification are also permitted under the
* terms of the GNU General Public License as published by the
* Free Software Foundation (version 2 or later, at your option).
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
// Example usage:
// size_t index;
// CSoundGroupMgr *sgm = CSoundGroupMgr::GetInstance();
// index = sgm->AddGroup("SoundGroup.xml");
// sgm->UpdateSoundGroups(TimeSinceLastFrame); // call in Frame()
// sgm->PlayNext(index); // wash-rinse-repeat
// sgm->RemoveGroup(index); // Remove the group if you like
// sgm->DeleteInstance(); // Delete instance in shutdown
#include "precompiled.h"
#include "SoundGroupMgr.h"
CSoundGroupMgr *CSoundGroupMgr::m_pInstance = 0;
CSoundGroupMgr::CSoundGroupMgr()
{
}
CSoundGroupMgr *CSoundGroupMgr::GetInstance()
{
if(!m_pInstance)
m_pInstance = new CSoundGroupMgr();
return m_pInstance;
}
void CSoundGroupMgr::DeleteInstance()
{
if(m_pInstance)
{
vector<CSoundGroup *>::iterator vIter = m_pInstance->m_Groups.begin();
while(vIter != m_pInstance->m_Groups.end())
vIter = m_pInstance->RemoveGroup(vIter);
delete m_pInstance;
}
m_pInstance = 0;
}
///////////////////////////////////////////
// AddGroup()
// in: const char *XMLFile - the filename of the SoundGroup.xml to open
// out: size_t index into m_Groups
// Loads the given XML file and returns an index for later use
///////////////////////////////////////////
size_t CSoundGroupMgr::AddGroup(const char *XMLFile)
{
CSoundGroup* newGroup = new CSoundGroup(XMLFile);
m_Groups.push_back(newGroup);
return m_Groups.size() - 1;
}
///////////////////////////////////////////
// RemoveGroup()
// in: size_t index into m_Groups
// out: vector<CSoundGroup *>::iterator - one past the index removed (sometimes useful)
// Removes and Releases a given soundgroup
///////////////////////////////////////////
vector<CSoundGroup *>::iterator CSoundGroupMgr::RemoveGroup(size_t index)
{
vector<CSoundGroup *>::iterator vIter = m_Groups.begin();
if(index >= m_Groups.size())
return vIter;
CSoundGroup *temp = (*vIter);
(*vIter)->ReleaseGroup();
vIter = m_Groups.erase(vIter+index);
delete temp;
return vIter;
}
///////////////////////////////////////////
// RemoveGroup()
// in: vector<CSoundGroup *>::iterator - item to remove
// out: vector<CSoundGroup *>::iterator - one past the index removed (sometimes useful)
// Removes and Releases a given soundgroup
///////////////////////////////////////////
vector<CSoundGroup *>::iterator CSoundGroupMgr::RemoveGroup(vector<CSoundGroup *>::iterator iter)
{
(*iter)->ReleaseGroup();
CSoundGroup *temp = (*iter);
iter = m_Groups.erase(iter);
delete temp;
return iter;
}
///////////////////////////////////////////
// UpdateSoundGroups()
// updates all soundgroups, call in Frame()
///////////////////////////////////////////
void CSoundGroupMgr::UpdateSoundGroups(float TimeSinceLastFrame)
{
vector<CSoundGroup *>::iterator vIter = m_Groups.begin();
while(vIter != m_Groups.end())
{
(*vIter)->Update(TimeSinceLastFrame);
vIter++;
}
}
///////////////////////////////////////////
// PlayNext()
// in: size_t index - index into m_Groups
// Plays the next queued sound in an indexed group
///////////////////////////////////////////
void CSoundGroupMgr::PlayNext(size_t index)
{
m_Groups[index]->PlayNext();
}

View File

@ -0,0 +1,79 @@
/**
* =========================================================================
* File : SoundGroupMgr.h
* Project : 0 A.D.
* Description : Manages and updates SoundGroups
*
* Author : Gavin Fowler
* =========================================================================
*/
/*
* Copyright (c) 2005-2006 Gavin Fowler
*
* Redistribution and/or modification are also permitted under the
* terms of the GNU General Public License as published by the
* Free Software Foundation (version 2 or later, at your option).
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "SoundGroup.h"
#include <vector>
using namespace std;
class CSoundGroupMgr
{
public:
vector <CSoundGroup *> m_Groups; // a collection of sound groups
static CSoundGroupMgr *m_pInstance; // our static instance of the manager
static CSoundGroupMgr *GetInstance();
static void DeleteInstance();
///////////////////////////////////////////
// UpdateSoundGroups()
// updates all soundgroups, call in Frame()
///////////////////////////////////////////
void UpdateSoundGroups(float TimeSinceLastFrame);
///////////////////////////////////////////
// PlayNext()
// in: size_t index - index into m_Groups
// Plays the next queued sound in an indexed group
///////////////////////////////////////////
void PlayNext(size_t index);
///////////////////////////////////////////
// AddGroup()
// in: const char *XMLFile - the filename of the SoundGroup.xml to open
// out: size_t index into m_Groups
// Loads the given XML file and returns an index for later use
///////////////////////////////////////////
size_t AddGroup(const char *XMLFile);
///////////////////////////////////////////
// RemoveGroup()
// in: size_t index into m_Groups
// out: vector<CSoundGroup *>::iterator - one past the index removed (sometimes useful)
// Removes and Releases a given soundgroup
///////////////////////////////////////////
vector<CSoundGroup *>::iterator RemoveGroup(size_t index);
///////////////////////////////////////////
// RemoveGroup()
// in: vector<CSoundGroup *>::iterator - item to remove
// out: vector<CSoundGroup *>::iterator - one past the index removed (sometimes useful)
// Removes and Releases a given soundgroup
///////////////////////////////////////////
vector<CSoundGroup *>::iterator RemoveGroup(vector<CSoundGroup *>::iterator iter);
private:
CSoundGroupMgr();
CSoundGroupMgr(const CSoundGroupMgr &ref);
CSoundGroupMgr &operator=(const CSoundGroupMgr &ref);
};