Skip to content

Commit

Permalink
Refactor|Sector|Client: Moved sector audio environment calculations i…
Browse files Browse the repository at this point in the history
…nto Sector
  • Loading branch information
danij-deng committed Aug 16, 2013
1 parent 76eacd9 commit c62f7d1
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 107 deletions.
4 changes: 1 addition & 3 deletions doomsday/client/include/audio/s_environ.h
Expand Up @@ -55,15 +55,13 @@ struct AudioEnvironment
*
* Call S_UpdateReverbForSector() to do the actual calculation.
*
* @pre BspLeaf attributors must have been determined first.
*
* @param sec Sector to calculate reverb properties of.
*/
void S_MarkSectorReverbDirty(Sector *sec);

/**
* Recalculates reverb properties for a sector. One must first mark the sector
* eligible for update using S_MarkSectorReverbDirty() or this function will do
* as needing an update using S_MarkSectorReverbDirty() or this function will do
* nothing.
*
* @param sec Sector in which to update reverb properties.
Expand Down
23 changes: 7 additions & 16 deletions doomsday/client/include/world/sector.h
Expand Up @@ -22,7 +22,6 @@
#define DENG_WORLD_SECTOR_H

#include <QList>
#include <QSet>

#include <de/aabox.h>

Expand Down Expand Up @@ -77,9 +76,6 @@ class Sector : public de::MapElement
typedef QList<BspLeaf *> BspLeafs;
typedef QList<Plane *> Planes;
typedef QList<Line::Side *> Sides;
#ifdef __CLIENT__
typedef QSet<BspLeaf *> ReverbBspLeafs;
#endif

// Plane identifiers:
enum { Floor, Ceiling };
Expand Down Expand Up @@ -107,11 +103,6 @@ class Sector : public de::MapElement
/// Head of the linked list of mobjs "in" the sector (not owned).
struct mobj_s *_mobjList;

#ifdef __CLIENT__
/// Final environmental audio characteristics.
AudioEnvironmentFactors _reverb;
#endif

public:
Sector(float lightLevel = 1,
de::Vector3f const &lightColor = de::Vector3f(1, 1, 1));
Expand Down Expand Up @@ -436,24 +427,24 @@ class Sector : public de::MapElement
LightGridData &lightGridData();

/**
* Update the set of BSP leafs which contribute to the environmental audio
* Perform initialization for environmental audio (reverb). Duties include
* determining the set of BSP leafs which will contribute to the final audio
* characteristics (reverb) of the sector. To be called when initializing
* the map after load.
*
* The BspLeaf Blockmap for the owning map must be prepared before calling.
*/
void findReverbBspLeafs();
void initReverb();

/**
* Provides access to the set of BSP leafs which contribute to the environmental
* audio characteristics (reverb) of the sector, for efficient traversal.
* Recalculate environmental audio (reverb) for the sector.
*/
ReverbBspLeafs const &reverbBspLeafs() const;
void updateReverb();

/**
* Returns the final environmental audio characteristics of the sector.
* Returns the final environmental audio characteristics (reverb) of the sector.
*/
AudioEnvironmentFactors const &audioEnvironmentFactors() const;
AudioEnvironmentFactors const &reverb() const;

/**
* Returns a rough approximation of the total combined area of the geometry
Expand Down
75 changes: 1 addition & 74 deletions doomsday/client/src/audio/s_environ.cpp
Expand Up @@ -84,79 +84,6 @@ AudioEnvironmentId S_AudioEnvironmentId(uri_s const *uri)
return AE_NONE;
}

static void calculateSectorReverb(Sector *sec)
{
if(!sec || !sec->sideCount()) return;

uint spaceVolume = int((sec->ceiling().height() - sec->floor().height()) * sec->roughArea());

sec->_reverb[SRD_SPACE] = sec->_reverb[SRD_VOLUME] =
sec->_reverb[SRD_DECAY] = sec->_reverb[SRD_DAMPING] = 0;

foreach(BspLeaf *bspLeaf, sec->reverbBspLeafs())
{
if(bspLeaf->updateReverb())
{
BspLeaf::AudioEnvironmentFactors const &leafReverb = bspLeaf->reverb();

sec->_reverb[SRD_SPACE] += leafReverb[SRD_SPACE];

sec->_reverb[SRD_VOLUME] += leafReverb[SRD_VOLUME] / 255.0f * leafReverb[SRD_SPACE];
sec->_reverb[SRD_DECAY] += leafReverb[SRD_DECAY] / 255.0f * leafReverb[SRD_SPACE];
sec->_reverb[SRD_DAMPING] += leafReverb[SRD_DAMPING] / 255.0f * leafReverb[SRD_SPACE];
}
}

float spaceScatter;
if(sec->_reverb[SRD_SPACE])
{
spaceScatter = spaceVolume / sec->_reverb[SRD_SPACE];
// These three are weighted by the space.
sec->_reverb[SRD_VOLUME] /= sec->_reverb[SRD_SPACE];
sec->_reverb[SRD_DECAY] /= sec->_reverb[SRD_SPACE];
sec->_reverb[SRD_DAMPING] /= sec->_reverb[SRD_SPACE];
}
else
{
spaceScatter = 0;
sec->_reverb[SRD_VOLUME] = .2f;
sec->_reverb[SRD_DECAY] = .4f;
sec->_reverb[SRD_DAMPING] = 1;
}

// If the space is scattered, the reverb effect lessens.
sec->_reverb[SRD_SPACE] /= (spaceScatter > .8 ? 10 : spaceScatter > .6 ? 4 : 1);

// Normalize the reverb space [0..1]
// 0= very small
// .99= very large
// 1.0= only for open areas (special case).
sec->_reverb[SRD_SPACE] /= 120e6;
if(sec->_reverb[SRD_SPACE] > .99)
sec->_reverb[SRD_SPACE] = .99f;

if(sec->ceilingSurface().hasSkyMaskedMaterial() || sec->floorSurface().hasSkyMaskedMaterial())
{
// An "open" sector.
// It can still be small, in which case; reverb is diminished a bit.
if(sec->_reverb[SRD_SPACE] > .5)
sec->_reverb[SRD_VOLUME] = 1; // Full volume.
else
sec->_reverb[SRD_VOLUME] = .5f; // Small, but still open.

sec->_reverb[SRD_SPACE] = 1;
}
else
{
// A "closed" sector.
// Large spaces have automatically a bit more audible reverb.
sec->_reverb[SRD_VOLUME] += sec->_reverb[SRD_SPACE] / 4;
}

if(sec->_reverb[SRD_VOLUME] > 1)
sec->_reverb[SRD_VOLUME] = 1;
}

void S_ResetReverb()
{
reverbUpdateRequested.clear();
Expand All @@ -169,7 +96,7 @@ void S_UpdateReverbForSector(Sector *sec)
// If update has been requested for this sector, calculate it now.
if(reverbUpdateRequested.find(sec) != reverbUpdateRequested.end())
{
calculateSectorReverb(sec);
sec->updateReverb();
reverbUpdateRequested.erase(sec);
}
}
Expand Down
2 changes: 1 addition & 1 deletion doomsday/client/src/audio/s_sfx.cpp
Expand Up @@ -565,7 +565,7 @@ void Sfx_ListenerUpdate()
// It may be necessary to recalculate the reverb properties.
S_UpdateReverbForSector(listenerSector);

AudioEnvironmentFactors const &envFactors = listenerSector->audioEnvironmentFactors();
AudioEnvironmentFactors const &envFactors = listenerSector->reverb();

for(int i = 0; i < NUM_REVERB_DATA; ++i)
{
Expand Down
7 changes: 2 additions & 5 deletions doomsday/client/src/world/map.cpp
Expand Up @@ -3623,13 +3623,10 @@ bool Map::endEditing()
d->initBspLeafBlockmap();

#ifdef __CLIENT__
// Determine the BSP leafs which contribute to each sector's environmental
// audio characteristics (reverb). Given that BSP leafs do not change shape
// (on the XY plane, that is), they do not move and are not created/destroyed
// once the map has been loaded; this step can be pre-processed.
// Perform pre-processing for environmental audio.
foreach(Sector *sector, d->sectors)
{
sector->findReverbBspLeafs();
sector->initReverb();
}
#endif

Expand Down
98 changes: 90 additions & 8 deletions doomsday/client/src/world/sector.cpp
Expand Up @@ -18,6 +18,7 @@
* 02110-1301 USA</small>
*/

#include <QSet>
#include <QtAlgorithms>

#include <de/Log>
Expand All @@ -42,6 +43,10 @@

using namespace de;

#ifdef __CLIENT__
typedef QSet<BspLeaf *> ReverbBspLeafs;
#endif

DENG2_PIMPL(Sector),
DENG2_OBSERVES(Plane, HeightChange)
{
Expand Down Expand Up @@ -77,6 +82,9 @@ DENG2_OBSERVES(Plane, HeightChange)
/// characteristics.
ReverbBspLeafs reverbBspLeafs;

/// Final environmental audio characteristics.
AudioEnvironmentFactors reverb;

bool visible; ///< @c true= marked as visible for the current frame.
#endif

Expand All @@ -96,6 +104,7 @@ DENG2_OBSERVES(Plane, HeightChange)
zap(soundEmitter);
#ifdef __CLIENT__
zap(lightGridData);
zap(reverb);
#endif
}

Expand Down Expand Up @@ -211,9 +220,6 @@ Sector::Sector(float lightLevel, Vector3f const &lightColor)
: MapElement(DMU_SECTOR), d(new Instance(this, lightLevel, lightColor))
{
_mobjList = 0;
#ifdef __CLIENT__
zap(_reverb);
#endif
}

float Sector::lightLevel() const
Expand Down Expand Up @@ -292,7 +298,13 @@ Sector::LightGridData &Sector::lightGridData()
return d->lightGridData;
}

void Sector::findReverbBspLeafs()
/**
* Determine the BSP leafs which contribute to each sector's environmental
* audio characteristics (reverb). Given that BSP leafs do not change shape
* (on the XY plane, that is), they do not move and are not created/destroyed
* once the map has been loaded; this step can be pre-processed.
*/
void Sector::initReverb()
{
d->reverbBspLeafs.clear();

Expand All @@ -315,14 +327,84 @@ void Sector::findReverbBspLeafs()
map().bspLeafsBoxIterator(affectionBounds, 0, Instance::addReverbBspLeafWorker, d);
}

Sector::ReverbBspLeafs const &Sector::reverbBspLeafs() const
void Sector::updateReverb()
{
return d->reverbBspLeafs;
// Sectors which no referencing line need no reverb.
if(!sideCount())
return;

uint spaceVolume = int((ceiling().height() - floor().height()) * roughArea());

d->reverb[SRD_SPACE] = d->reverb[SRD_VOLUME] =
d->reverb[SRD_DECAY] = d->reverb[SRD_DAMPING] = 0;

foreach(BspLeaf *bspLeaf, d->reverbBspLeafs)
{
if(bspLeaf->updateReverb())
{
BspLeaf::AudioEnvironmentFactors const &leafReverb = bspLeaf->reverb();

d->reverb[SRD_SPACE] += leafReverb[SRD_SPACE];

d->reverb[SRD_VOLUME] += leafReverb[SRD_VOLUME] / 255.0f * leafReverb[SRD_SPACE];
d->reverb[SRD_DECAY] += leafReverb[SRD_DECAY] / 255.0f * leafReverb[SRD_SPACE];
d->reverb[SRD_DAMPING] += leafReverb[SRD_DAMPING] / 255.0f * leafReverb[SRD_SPACE];
}
}

float spaceScatter;
if(d->reverb[SRD_SPACE])
{
spaceScatter = spaceVolume / d->reverb[SRD_SPACE];
// These three are weighted by the space.
d->reverb[SRD_VOLUME] /= d->reverb[SRD_SPACE];
d->reverb[SRD_DECAY] /= d->reverb[SRD_SPACE];
d->reverb[SRD_DAMPING] /= d->reverb[SRD_SPACE];
}
else
{
spaceScatter = 0;
d->reverb[SRD_VOLUME] = .2f;
d->reverb[SRD_DECAY] = .4f;
d->reverb[SRD_DAMPING] = 1;
}

// If the space is scattered, the reverb effect lessens.
d->reverb[SRD_SPACE] /= (spaceScatter > .8 ? 10 : spaceScatter > .6 ? 4 : 1);

// Normalize the reverb space [0..1]
// 0= very small
// .99= very large
// 1.0= only for open areas (special case).
d->reverb[SRD_SPACE] /= 120e6;
if(d->reverb[SRD_SPACE] > .99)
d->reverb[SRD_SPACE] = .99f;

if(ceilingSurface().hasSkyMaskedMaterial() || floorSurface().hasSkyMaskedMaterial())
{
// An "open" sector.
// It can still be small, in which case; reverb is diminished a bit.
if(d->reverb[SRD_SPACE] > .5)
d->reverb[SRD_VOLUME] = 1; // Full volume.
else
d->reverb[SRD_VOLUME] = .5f; // Small, but still open.

d->reverb[SRD_SPACE] = 1;
}
else
{
// A "closed" sector.
// Large spaces have automatically a bit more audible reverb.
d->reverb[SRD_VOLUME] += d->reverb[SRD_SPACE] / 4;
}

if(d->reverb[SRD_VOLUME] > 1)
d->reverb[SRD_VOLUME] = 1;
}

AudioEnvironmentFactors const &Sector::audioEnvironmentFactors() const
AudioEnvironmentFactors const &Sector::reverb() const
{
return _reverb;
return d->reverb;
}

coord_t Sector::roughArea() const
Expand Down

0 comments on commit c62f7d1

Please sign in to comment.