Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

EFX spawnarg for location entities #2

Draft
wants to merge 10 commits into
base: trunk
Choose a base branch
from
Draft
4 changes: 4 additions & 0 deletions MayaImport.vcxproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should not be added to VCS I suppose.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed from PR

5 changes: 4 additions & 1 deletion game/PlayerView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,10 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view, b
// place the sound origin for the player
// TODO: Support overriding the location area so that reverb settings can be applied for listening thru doors?
idVec3 p = player->GetPrimaryListenerLoc(); // grayman #4882
gameSoundWorld->PlaceListener( p, view->viewaxis, player->entityNumber + 1, gameLocal.time, hud ? hud->State().GetString( "location" ) : "Undefined" ); // grayman #4882
idLocationEntity* currentLocation = player->GetLocation();
idStr efxPreset = currentLocation->spawnArgs.GetString("efx_preset");

gameSoundWorld->PlaceListener( p, view->viewaxis, player->entityNumber + 1, gameLocal.time, hud ? hud->State().GetString( "location" ) : "Undefined", efxPreset ); // grayman #4882
// gameSoundWorld->PlaceListener(player->GetListenerLoc(), view->viewaxis, player->entityNumber + 1, gameLocal.time, hud ? hud->State().GetString("location") : "Undefined");

// hack the shake in at the very last moment, so it can't cause any consistency problems
Expand Down
4 changes: 4 additions & 0 deletions sound/efxlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ class idEFXFile {
bool Reload();
bool IsAfterReload();

bool AddOrUpdatePreset(idStr areaName, idStr efxPreset, ALuint* effect);

private:
bool ReadEffectLegacy(idLexer &lexer, idSoundEffect *effect);
bool AddPreset(idStr token, idSoundEffect *effect, ALenum err);
bool GetEffect(idStr& name, idSoundEffect * soundEffect);
bool ReadEffectOpenAL(idLexer &lexer, idSoundEffect *effect);

//filename initially passed to LoadFile (or empty if LoadFile never called)
Expand Down
151 changes: 109 additions & 42 deletions sound/snd_efxfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static inline ALfloat _mB_to_gain(ALfloat millibels, ALfloat min, ALfloat max) {
}

idSoundEffect::idSoundEffect() :
effect(0) {
effect(0) {
}

idSoundEffect::~idSoundEffect() {
Expand Down Expand Up @@ -104,6 +104,19 @@ bool idEFXFile::FindEffect(idStr &name, ALuint *effect) {
return false;
}

bool idEFXFile::GetEffect(idStr& name, idSoundEffect *soundEffect) {
int i;

for (i = 0; i < effects.Num(); i++) {
if (effects[i]->name.Icmp(name) == 0) {
*soundEffect = *effects[i];
return true;
}
}

return false;
}

#define efxi(param, value) \
do { \
ALint _v = value; \
Expand Down Expand Up @@ -252,6 +265,96 @@ bool idEFXFile::ReadEffectLegacy(idLexer &src, idSoundEffect *effect) {
return true;
}

bool idEFXFile::AddOrUpdatePreset(idStr areaName, idStr efxPreset, ALuint* effect) {

idSoundEffect* soundEffect = new idSoundEffect;

//ALuint effect = AL_EFFECTSLOT_NULL;
const bool found = GetEffect(areaName, soundEffect);
ALenum err{};
bool ok;

if (!found) {

// we need to add this preset

if (!soundEffect->alloc()) {
delete soundEffect;
Clear();
return false;
}

soundEffect->name = areaName;

//ALenum err{};
bool ok;
ok = AddPreset(efxPreset, soundEffect, err);

if (!ok) {
return false;
}

effects.Append(soundEffect);
}
else {
ok = AddPreset(efxPreset, soundEffect, err);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why both cases call AddPreset.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presets can be used by either the EFX file or the spawnarg, so instead of duplicating the code I refactored it into a new function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry ignore my last comment - I understand what you mean now. I've gone back and refactored it, it should look better now.


if (!ok) {
return false;
}
}

*effect = soundEffect->effect;
return true;
}

bool idEFXFile::AddPreset(idStr preset, idSoundEffect* effect, ALenum err) {

const EFXEAXREVERBPROPERTIES* props = NULL;
int k = 0;
for (k = 0; efxPresets[k].name[0]; k++)
if (efxPresets[k].name == preset) {
props = &efxPresets[k].props;
break;
}

// Reference the preset by index instead of name.
if (!props && idStr::IsNumeric(preset)) {
int idx = atoi(preset);
if (idx >= 0 && idx < k)
props = &efxPresets[idx].props;
}
if (!props) {
//src.Error("idEFXFile::ReadEffect: Unknown preset name %s", token.c_str());
return false;
}

efxf(AL_EAXREVERB_DENSITY, props->flDensity);
efxf(AL_EAXREVERB_DIFFUSION, props->flDiffusion);
efxf(AL_EAXREVERB_GAIN, props->flGain);
efxf(AL_EAXREVERB_GAINHF, props->flGainHF);
efxf(AL_EAXREVERB_GAINLF, props->flGainLF);
efxf(AL_EAXREVERB_DECAY_TIME, props->flDecayTime);
efxf(AL_EAXREVERB_DECAY_HFRATIO, props->flDecayHFRatio);
efxf(AL_EAXREVERB_DECAY_LFRATIO, props->flDecayLFRatio);
efxf(AL_EAXREVERB_REFLECTIONS_GAIN, props->flReflectionsGain);
efxf(AL_EAXREVERB_REFLECTIONS_DELAY, props->flReflectionsDelay);
efxfv(AL_EAXREVERB_REFLECTIONS_PAN, props->flReflectionsPan[0], props->flReflectionsPan[1], props->flReflectionsPan[2]);
efxf(AL_EAXREVERB_LATE_REVERB_GAIN, props->flLateReverbGain);
efxf(AL_EAXREVERB_LATE_REVERB_DELAY, props->flLateReverbDelay);
efxfv(AL_EAXREVERB_LATE_REVERB_PAN, props->flLateReverbPan[0], props->flLateReverbPan[1], props->flLateReverbPan[2]);
efxf(AL_EAXREVERB_ECHO_TIME, props->flEchoTime);
efxf(AL_EAXREVERB_ECHO_DEPTH, props->flEchoDepth);
efxf(AL_EAXREVERB_MODULATION_TIME, props->flModulationTime);
efxf(AL_EAXREVERB_MODULATION_DEPTH, props->flModulationDepth);
efxf(AL_EAXREVERB_AIR_ABSORPTION_GAINHF, props->flAirAbsorptionGainHF);
efxf(AL_EAXREVERB_HFREFERENCE, props->flHFReference);
efxf(AL_EAXREVERB_LFREFERENCE, props->flLFReference);
efxf(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, props->flRoomRolloffFactor);
efxi(AL_EAXREVERB_DECAY_HFLIMIT, props->iDecayHFLimit);

}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like missing return.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


bool idEFXFile::ReadEffectOpenAL(idLexer &src, idSoundEffect *effect) {
idToken token;

Expand All @@ -267,7 +370,7 @@ bool idEFXFile::ReadEffectOpenAL(idLexer &src, idSoundEffect *effect) {
if (!src.ExpectTokenString("{"))
return false;

ALenum err;
ALenum err{};
alGetError();
common->Printf("Loading EFX effect for location '%s' (#%u)\n", name.c_str(), effect->effect);

Expand All @@ -288,47 +391,9 @@ bool idEFXFile::ReadEffectOpenAL(idLexer &src, idSoundEffect *effect) {
return false;
token.ToUpper();

const EFXEAXREVERBPROPERTIES *props = NULL;
int k = 0;
for (k = 0; efxPresets[k].name[0]; k++)
if (efxPresets[k].name == token) {
props = &efxPresets[k].props;
break;
}
if (!props && (token.type == TT_NUMBER)) {
int idx = token.GetIntValue();
if (idx >= 0 && idx < k)
props = &efxPresets[idx].props;
}
if (!props) {
src.Error("idEFXFile::ReadEffect: Unknown preset name %s", token.c_str());
if (!AddPreset(token, effect, err)) {
return false;
}

efxf(AL_EAXREVERB_DENSITY, props->flDensity);
efxf(AL_EAXREVERB_DIFFUSION, props->flDiffusion);
efxf(AL_EAXREVERB_GAIN, props->flGain);
efxf(AL_EAXREVERB_GAINHF, props->flGainHF);
efxf(AL_EAXREVERB_GAINLF, props->flGainLF);
efxf(AL_EAXREVERB_DECAY_TIME, props->flDecayTime);
efxf(AL_EAXREVERB_DECAY_HFRATIO, props->flDecayHFRatio);
efxf(AL_EAXREVERB_DECAY_LFRATIO, props->flDecayLFRatio);
efxf(AL_EAXREVERB_REFLECTIONS_GAIN, props->flReflectionsGain);
efxf(AL_EAXREVERB_REFLECTIONS_DELAY, props->flReflectionsDelay);
efxfv(AL_EAXREVERB_REFLECTIONS_PAN, props->flReflectionsPan[0], props->flReflectionsPan[1], props->flReflectionsPan[2]);
efxf(AL_EAXREVERB_LATE_REVERB_GAIN, props->flLateReverbGain);
efxf(AL_EAXREVERB_LATE_REVERB_DELAY, props->flLateReverbDelay);
efxfv(AL_EAXREVERB_LATE_REVERB_PAN, props->flLateReverbPan[0], props->flLateReverbPan[1], props->flLateReverbPan[2]);
efxf(AL_EAXREVERB_ECHO_TIME, props->flEchoTime);
efxf(AL_EAXREVERB_ECHO_DEPTH, props->flEchoDepth);
efxf(AL_EAXREVERB_MODULATION_TIME, props->flModulationTime);
efxf(AL_EAXREVERB_MODULATION_DEPTH, props->flModulationDepth);
efxf(AL_EAXREVERB_AIR_ABSORPTION_GAINHF, props->flAirAbsorptionGainHF);
efxf(AL_EAXREVERB_HFREFERENCE, props->flHFReference);
efxf(AL_EAXREVERB_LFREFERENCE, props->flLFReference);
efxf(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, props->flRoomRolloffFactor);
efxi(AL_EAXREVERB_DECAY_HFLIMIT, props->iDecayHFLimit);

} else if ( token == "DENSITY" ) {
efxf(AL_EAXREVERB_DENSITY, src.ParseFloat());
} else if ( token == "DIFFUSION" ) {
Expand Down Expand Up @@ -398,7 +463,9 @@ bool idEFXFile::LoadFile( const char *filename/*, bool OSPath*/ ) {
efxFilename = filename;
src.LoadFile( filename/*, OSPath*/ );
if ( !src.IsLoaded() ) {
return false;

// Just return true if file doesn't exist, as EFX can now be specified on location entities
return true;
}

if ( !src.ExpectTokenString( "Version" ) ) {
Expand Down
3 changes: 2 additions & 1 deletion sound/snd_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ class idSoundWorldLocal : public idSoundWorld {

// where is the camera/microphone
// listenerId allows listener-private sounds to be added
virtual void PlaceListener( const idVec3 &origin, const idMat3 &axis, const int listenerId, const int gameTime, const idStr& areaName ) override;
virtual void PlaceListener( const idVec3 &origin, const idMat3 &axis, const int listenerId, const int gameTime, const idStr& areaName, const idStr& efxPreset) override;

// fade all sounds in the world with a given shader soundClass
// to is in Db (sigh), over is in seconds
Expand Down Expand Up @@ -618,6 +618,7 @@ class idSoundWorldLocal : public idSoundWorld {
idVec3 listenerQU; // position in "quake units"
int listenerArea;
idStr listenerAreaName;
idStr listenerAreaEfxPreset;
ALuint listenerEffect;
ALuint listenerSlot;
ALuint listenerFilter;
Expand Down
21 changes: 17 additions & 4 deletions sound/snd_world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ void idSoundWorldLocal::ProcessDemoCommand( idDemoFile *readDemo ) {
readDemo->ReadInt( listenerId );
readDemo->ReadInt( gameTime );

PlaceListener( origin, axis, listenerId, gameTime, "" );
PlaceListener( origin, axis, listenerId, gameTime, "", "");
};
break;
case SCMD_ALLOC_EMITTER:
Expand Down Expand Up @@ -515,17 +515,29 @@ void idSoundWorldLocal::MixLoopInternal( int current44kHz, int numSpeakers, floa
soundSystemLocal.alAuxiliaryEffectSlotf(listenerSlot, AL_EFFECTSLOT_GAIN, gain);
}

// Look for effect based on area index (1, 2, etc.). Does anyone actually do this?
bool found = soundSystemLocal.EFXDatabase.FindEffect(s, &effect);

// Look for effect based on area (location) name
if (!found) {
s = listenerAreaName;
found = soundSystemLocal.EFXDatabase.FindEffect(s, &effect);

if (!listenerAreaEfxPreset.IsEmpty()) {
ALenum err;
found = soundSystemLocal.EFXDatabase.AddOrUpdatePreset(s, listenerAreaEfxPreset, &effect);
}
else {
found = soundSystemLocal.EFXDatabase.FindEffect(s, &effect);
}

}
if (!found) {
s = "default";
found = soundSystemLocal.EFXDatabase.FindEffect(s, &effect);
}

bool justReloaded = soundSystemLocal.EFXDatabase.IsAfterReload();

// only update if change in settings
if (listenerEffect != effect || justReloaded) {
common->Printf("Switching to EFX '%s' (#%u)\n", s.c_str(), effect);
Expand Down Expand Up @@ -1152,7 +1164,7 @@ idSoundWorldLocal::PlaceListener
===================
*/
void idSoundWorldLocal::PlaceListener( const idVec3& origin, const idMat3& axis,
const int listenerId, const int gameTime, const idStr& areaName ) {
const int listenerId, const int gameTime, const idStr& areaName, const idStr& efxPreset) {

int current44kHzTime;

Expand Down Expand Up @@ -1199,6 +1211,7 @@ void idSoundWorldLocal::PlaceListener( const idVec3& origin, const idMat3& axis,
listenerPos = origin * DOOM_TO_METERS; // meters
listenerAxis = axis;
listenerAreaName = areaName;
listenerAreaEfxPreset = efxPreset;

if ( rw ) {
listenerArea = rw->GetAreaAtPoint( listenerQU ); // where are we?
Expand Down Expand Up @@ -1573,7 +1586,7 @@ void idSoundWorldLocal::ReadFromSaveGame( idFile *savefile ) {
pause44kHz = currentSoundTime;

// place listener
PlaceListener( origin, axis, listenerId, gameTime, "Undefined" );
PlaceListener( origin, axis, listenerId, gameTime, "Undefined", "");

// make sure there are enough
// slots to read the saveGame in. We don't shrink the list
Expand Down
2 changes: 1 addition & 1 deletion sound/sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ class idSoundWorld {
// listenerId allows listener-private and antiPrivate sounds to be filtered
// gameTime is in msec, and is used to time sound queries and removals so that they are independent
// of any race conditions with the async update
virtual void PlaceListener( const idVec3 &origin, const idMat3 &axis, const int listenerId, const int gameTime, const idStr& areaName ) = 0;
virtual void PlaceListener( const idVec3 &origin, const idMat3 &axis, const int listenerId, const int gameTime, const idStr& areaName, const idStr& efxPreset ) = 0;

// fade all sounds in the world with a given shader soundClass
// to is in Db (sigh), over is in seconds
Expand Down
2 changes: 1 addition & 1 deletion tools/radiant/CamWnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ void CCamWnd::Cam_Draw() {
// set the sound origin for both simple draw and rendered mode
// the editor uses opposite pitch convention
idMat3 axis = idAngles( -m_Camera.angles.pitch, m_Camera.angles.yaw, m_Camera.angles.roll ).ToMat3();
g_qeglobals.sw->PlaceListener( m_Camera.origin, axis, 0, Sys_Milliseconds(), "Undefined" );
g_qeglobals.sw->PlaceListener( m_Camera.origin, axis, 0, Sys_Milliseconds(), "Undefined", "");

if (renderMode) {
Cam_Render();
Expand Down