1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-10-08 15:21:12 +00:00

Implemenet proper positional audio, one issue still.

With this patch, entities can serve as a sound source whose position
updates relative to the listener. This implements the last missing
feature of my previous positional audio patch, which is moving sound sources.
Previously, all sounds were relative to the listener with the listener
centered at (0, 0, 0), and once a sound started playing, the position could
not be changed. Volume was set as an estimation of the distance to the listener.

These restrictions are now gone; OpenAL will handle the volume & panning
based on the distance.

The remaining problem is that stereo sounds are not attenuated, at all.

Lua additions:
- playSfx() takes an additional parameter now.
- entity_setStopSoundsOnDeath()
This commit is contained in:
fgenesis 2013-07-22 03:29:57 +02:00
commit e6680da428
12 changed files with 435 additions and 174 deletions

View file

@ -3466,7 +3466,7 @@ void Avatar::lockToWallCommon()
dsq->spawnParticleEffect("LockToWall", position);
stopBurst();
stopRoll();
core->sound->playSfx("LockToWall", 1.0, 0);//, (1000+rand()%100)/1000.0f);
core->sound->playSfx("LockToWall", 1.0);
//bursting = false;
this->burst = 1;
//lastLockToWallPos = position;

View file

@ -2293,58 +2293,22 @@ void DSQ::playMenuSelectSfx()
core->sound->playSfx("MenuSelect");
}
PlaySfx DSQ::calcPositionalSfx(const Vector &position, float maxdist)
void DSQ::playPositionalSfx(const std::string &name, const Vector &position, float f, float fadeOut, SoundHolder *holder)
{
PlaySfx sfx;
sfx.vol = 0;
if (dsq->game && dsq->game->avatar)
{
Vector diff = position - dsq->game->avatar->position;
// Aspect-ratio-adjustment:
// Just multiplying the cut-off distance with aspect increases it too much on widescreen,
// so only a part of it is aspect-corrected to make it sound better.
// Aspect is most likely >= 5/4 here, which results in a higher value than
// the default of 1024; this is intended. -- FG
if (maxdist <= 0)
maxdist = 724 + (300 * aspect);
float dist = diff.getLength2D();
if (dist < maxdist)
{
sfx.vol = 1.0f - (dist / maxdist);
sfx.pan = (diff.x / maxdist) * 2.0f;
if (sfx.pan < -1)
sfx.pan = -1;
if (sfx.pan > 1)
sfx.pan = 1;
}
}
return sfx;
}
void DSQ::playPositionalSfx(const std::string &name, const Vector &position, float f, float fadeOut)
{
PlaySfx sfx = calcPositionalSfx(position);
// FIXME: Right now, positional sound effects never update their relative position to the
// listener, which means that if they are spawned too far away to be audible, it is not possible
// that they ever get audible at all. Additionally, the current scripting API only provides
// functions to fade sounds OUT, not to set their volume arbitrarily.
// Because audio thread creation is costly, drop sounds that can not be heard.
// This needs to be removed once proper audio source/listener positioning is implemented,
// or the scripting interface gets additional functions to mess with sound. -- FG
if (sfx.vol <= 0)
return;
sfx.freq = f;
sfx.name = name;
sfx.relative = false;
sfx.x = position.x;
sfx.y = position.y;
void *c = sound->playSfx(sfx);
if (fadeOut != 0)
{
sound->fadeSfx(c, SFT_OUT, fadeOut);
}
if (holder)
holder->linkSound(c);
}
void DSQ::shutdown()

View file

@ -1426,8 +1426,7 @@ public:
bool voiceOversEnabled;
int recentSaveSlot;
PlaySfx calcPositionalSfx(const Vector &position, float maxdist = 0);
void playPositionalSfx(const std::string &name, const Vector &position, float freq=1.0f, float fadeOut=0);
void playPositionalSfx(const std::string &name, const Vector &position, float freq=1.0f, float fadeOut=0, SoundHolder *holder = 0);
void playMenuSelectSfx();

View file

@ -284,6 +284,8 @@ Entity::Entity()
setDamageTarget(DT_AVATAR_BUBBLE, false);
setDamageTarget(DT_AVATAR_SEED, false);
stopSoundsOnDeath = false;
//debugLog("End Entity::Entity()");
}
@ -573,6 +575,10 @@ void Entity::watchEntity(Entity *e)
void Entity::destroy()
{
if (stopSoundsOnDeath)
this->stopAllSounds();
this->unlinkAllSounds();
/*
if (hair)
{
@ -1231,6 +1237,8 @@ void Entity::update(float dt)
position = backupPos;
if (vel.isNan())
vel = backupVel;
updateSoundPosition();
}
void Entity::postUpdate(float dt)
@ -2239,7 +2247,8 @@ void Entity::songNoteDone(int note, float len)
void Entity::sound(const std::string &sound, float freq, float fadeOut)
{
dsq->playPositionalSfx(sound, position, freq, fadeOut);
dsq->playPositionalSfx(sound, position, freq, fadeOut, this);
updateSoundPosition();
}
Vector Entity::getEnergyShotTargetPosition()
@ -3139,3 +3148,8 @@ bool Entity::isEntityInside()
}
return false;
}
void Entity::updateSoundPosition()
{
SoundHolder::updateSoundPosition(position.x + offset.x, position.y + offset.y);
}

View file

@ -196,7 +196,7 @@ enum BounceType
BOUNCE_REAL = 1
};
class Entity : public Quad, public StateMachine
class Entity : public Quad, public StateMachine, public SoundHolder
{
public:
Entity();
@ -276,6 +276,7 @@ public:
void popBubble();
void sound(const std::string &sound, float freq=1, float fadeOut=0);
void setStopSoundsOnDeath(bool stop) { stopSoundsOnDeath = stop; }
void freeze(float time);
@ -492,6 +493,8 @@ public:
bool isEntityInside();
void updateSoundPosition();
protected:
bool calledEntityDied;
Path *waterBubble;
@ -602,6 +605,8 @@ private:
int maxSpeed;
int oldMaxSpeed;
bool stopSoundsOnDeath;
};
#endif

View file

@ -8134,13 +8134,13 @@ void Game::playBurstSound(bool wallJump)
int freqBase = 950;
if (wallJump)
freqBase += 100;
sound->playSfx("Burst", 1, 0);//, (freqBase+rand()%25)/1000.0f);
sound->playSfx("Burst", 1);
if (chance(50))
{
switch (dsq->continuity.form)
{
case FORM_BEAST:
sound->playSfx("BeastBurst", (128+rand()%64)/256.0f, 0);//, (freqBase+rand()%25)/1000.0f);
sound->playSfx("BeastBurst", (128+rand()%64)/256.0f);
break;
}
}

View file

@ -2763,28 +2763,36 @@ luaFunc(entity_playSfx)
void *h = NULL;
if (e && !dsq->isSkippingCutscene())
{
PlaySfx sfx = dsq->calcPositionalSfx(e->position, lua_tonumber(L, 7));
PlaySfx sfx;
sfx.name = getString(L, 2);
sfx.freq = lua_tonumber(L, 3);
float vol = lua_tonumber(L, 4);
sfx.vol = lua_tonumber(L, 4);
sfx.loops = lua_tonumber(L, 5);
float fadeOut = lua_tonumber(L, 6);
if(vol > 0)
sfx.vol *= vol;
// FIXME: See comment in DSQ::playPositionalSfx() -- FG
if (sfx.vol <= 0)
luaReturnPtr(NULL);
sfx.maxdist = lua_tonumber(L, 7);
sfx.relative = false;
h = core->sound->playSfx(sfx);
if (fadeOut != 0)
{
sound->fadeSfx(h, SFT_OUT, fadeOut);
}
e->linkSound(h);
e->updateSoundPosition();
}
luaReturnPtr(h);
}
luaFunc(entity_setStopSoundsOnDeath)
{
Entity *e = entity(L);
if (e)
e->setStopSoundsOnDeath(getBool(L, 2));
luaReturnNil();
}
luaFunc(entity_setSpiritFreeze)
{
Entity *e = entity(L);
@ -5927,32 +5935,20 @@ luaFunc(emote)
luaFunc(playSfx)
{
float freq = lua_tonumber(L, 2);
float vol = lua_tonumber(L, 3);
int loops = lua_tointeger(L, 4);
if (vol <= 0)
vol = 1;
PlaySfx sfx;
if (lua_isnumber(L, 5) && lua_isnumber(L, 6))
{
const Vector pos(lua_tonumber(L, 5), lua_tonumber(L, 6));
sfx = dsq->calcPositionalSfx(pos, lua_tonumber(L, 7));
sfx.vol *= vol;
}
else
{
sfx.vol = vol;
}
// FIXME: See comment in DSQ::playPositionalSfx() -- FG
if (sfx.vol <= 0)
luaReturnPtr(NULL);
sfx.name = getString(L, 1);
sfx.freq = freq;
sfx.loops = loops;
sfx.freq = lua_tonumber(L, 2);
sfx.vol = lua_tonumber(L, 3);
if (sfx.vol <= 0)
sfx.vol = 1;
sfx.loops = lua_tointeger(L, 4);
sfx.x = lua_tonumber(L, 5);
sfx.y = lua_tonumber(L, 6);
sfx.maxdist = lua_tonumber(L, 7);
if(lua_isnoneornil(L, 8))
sfx.relative = (sfx.x == 0 && sfx.y == 0);
else
sfx.relative = getBool(L, 8);
void *handle = NULL;