diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp
index 27fa2ca27c..849f13076d 100644
--- a/apps/launcher/settingspage.cpp
+++ b/apps/launcher/settingspage.cpp
@@ -291,6 +291,7 @@ bool Launcher::SettingsPage::loadSettings()
}
}
loadSettingBool(Settings::sound().mCameraListener, *cameraListenerCheckBox);
+ dopplerSpinBox->setValue(Settings::sound().mDopplerFactor);
}
// Interface Changes
@@ -482,6 +483,8 @@ void Launcher::SettingsPage::saveSettings()
const bool cCameraListener = cameraListenerCheckBox->checkState() != Qt::Unchecked;
Settings::sound().mCameraListener.set(cCameraListener);
+
+ Settings::sound().mDopplerFactor.set(dopplerSpinBox->value());
}
// Interface Changes
diff --git a/apps/launcher/ui/settingspage.ui b/apps/launcher/ui/settingspage.ui
index b96d734605..d7e1a4b3ab 100644
--- a/apps/launcher/ui/settingspage.ui
+++ b/apps/launcher/ui/settingspage.ui
@@ -1224,6 +1224,51 @@
+ -
+
+
-
+
+
+ <html><head/><body><p>Controls the strength of the Doppler effect. Zero means it is completely disabled.</p><p>The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.</p></body></html>
+
+
+ Doppler Factor
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 283
+ 0
+
+
+
+ 2
+
+
+ 0.000000000000000
+
+
+ 1.000000000000000
+
+
+ 0.010000000000000
+
+
+ 0.250000000000000
+
+
+
+
+
-
diff --git a/apps/openmw/mwbase/soundmanager.hpp b/apps/openmw/mwbase/soundmanager.hpp
index 532bc771ba..5591b7205c 100644
--- a/apps/openmw/mwbase/soundmanager.hpp
+++ b/apps/openmw/mwbase/soundmanager.hpp
@@ -234,6 +234,8 @@ namespace MWBase
const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater)
= 0;
+ virtual void setListenerVel(const osg::Vec3f& vel) = 0;
+
virtual void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) = 0;
void setSimulationTimeScale(float scale) { mSimulationTimeScale = scale; }
diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp
index 157c12af23..74bd9f6a5c 100644
--- a/apps/openmw/mwbase/world.hpp
+++ b/apps/openmw/mwbase/world.hpp
@@ -496,6 +496,8 @@ namespace MWBase
virtual float getSunVisibility() const = 0;
virtual float getSunPercentage() const = 0;
+ virtual float getPhysicsFrameRateDt() const = 0;
+
virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp
index f403f97c2f..adc107f7cc 100644
--- a/apps/openmw/mwphysics/physicssystem.cpp
+++ b/apps/openmw/mwphysics/physicssystem.cpp
@@ -93,9 +93,10 @@ namespace
namespace MWPhysics
{
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr parentNode)
- : mShapeManager(
- std::make_unique(resourceSystem->getVFS(), resourceSystem->getSceneManager(),
- resourceSystem->getNifFileManager(), Settings::cells().mCacheExpiryDelay))
+ : mPhysicsDt(1.f / 60.f)
+ , mShapeManager(std::make_unique(resourceSystem->getVFS(),
+ resourceSystem->getSceneManager(), resourceSystem->getNifFileManager(),
+ Settings::cells().mCacheExpiryDelay))
, mResourceSystem(resourceSystem)
, mDebugDrawEnabled(false)
, mTimeAccum(0.0f)
@@ -103,7 +104,6 @@ namespace MWPhysics
, mWaterHeight(0)
, mWaterEnabled(false)
, mParentNode(std::move(parentNode))
- , mPhysicsDt(1.f / 60.f)
{
mResourceSystem->addResourceManager(mShapeManager.get());
diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp
index 8a845b4c41..0ab0cf91a0 100644
--- a/apps/openmw/mwphysics/physicssystem.hpp
+++ b/apps/openmw/mwphysics/physicssystem.hpp
@@ -287,6 +287,8 @@ namespace MWPhysics
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
void reportCollision(const btVector3& position, const btVector3& normal);
+ float mPhysicsDt;
+
private:
void updateWater();
@@ -330,8 +332,6 @@ namespace MWPhysics
osg::ref_ptr mParentNode;
- float mPhysicsDt;
-
std::size_t mSimulationsCounter = 0;
std::array, 2> mSimulations;
std::vector> mActorsPositions;
diff --git a/apps/openmw/mwsound/openaloutput.cpp b/apps/openmw/mwsound/openaloutput.cpp
index 60c9e5f3ea..ecce476685 100644
--- a/apps/openmw/mwsound/openaloutput.cpp
+++ b/apps/openmw/mwsound/openaloutput.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#include "efxpresets.h"
@@ -963,6 +964,7 @@ namespace MWSound
// Speed of sound is in units per second. Take the sound speed in air (assumed
// meters per second), multiply by the units per meter to get the speed in u/s.
alSpeedOfSound(Constants::SoundSpeedInAir * Constants::UnitsPerMeter);
+ alDopplerFactor(Settings::sound().mDopplerFactor);
alGetError();
mInitialized = true;
@@ -1142,8 +1144,8 @@ namespace MWSound
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
}
- void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist,
- ALfloat gain, ALfloat pitch, bool loop, bool useenv)
+ void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat mindist,
+ ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv)
{
alSourcef(source, AL_REFERENCE_DISTANCE, mindist);
alSourcef(source, AL_MAX_DISTANCE, maxdist);
@@ -1179,11 +1181,11 @@ namespace MWSound
alSourcef(source, AL_PITCH, pitch);
alSourcefv(source, AL_POSITION, pos.ptr());
alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
- alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
+ alSourcefv(source, AL_VELOCITY, vel.ptr());
}
- void OpenALOutput::updateCommon(
- ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv)
+ void OpenALOutput::updateCommon(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat maxdist,
+ ALfloat gain, ALfloat pitch, bool useenv)
{
if (useenv && mListenerEnv == Env_Underwater && !mWaterFilter)
{
@@ -1195,7 +1197,7 @@ namespace MWSound
alSourcef(source, AL_PITCH, pitch);
alSourcefv(source, AL_POSITION, pos.ptr());
alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
- alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
+ alSourcefv(source, AL_VELOCITY, vel.ptr());
}
bool OpenALOutput::playSound(Sound* sound, Sound_Handle data, float offset)
@@ -1248,8 +1250,9 @@ namespace MWSound
}
source = mFreeSources.front();
- initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
- sound->getRealVolume(), getTimeScaledPitch(sound), sound->getIsLooping(), sound->getUseEnv());
+ initCommon3D(source, sound->getPosition(), sound->getVelocity(), sound->getMinDistance(),
+ sound->getMaxDistance(), sound->getRealVolume(), getTimeScaledPitch(sound), sound->getIsLooping(),
+ sound->getUseEnv());
alSourcei(source, AL_BUFFER, GET_PTRID(data));
alSourcef(source, AL_SEC_OFFSET, offset);
if (getALError() != AL_NO_ERROR)
@@ -1312,8 +1315,8 @@ namespace MWSound
return;
ALuint source = GET_PTRID(sound->mHandle);
- updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
- getTimeScaledPitch(sound), sound->getUseEnv());
+ updateCommon(source, sound->getPosition(), sound->getVelocity(), sound->getMaxDistance(),
+ sound->getRealVolume(), getTimeScaledPitch(sound), sound->getUseEnv());
getALError();
}
@@ -1360,8 +1363,8 @@ namespace MWSound
if (sound->getIsLooping())
Log(Debug::Warning) << "Warning: cannot loop stream \"" << decoder->getName() << "\"";
- initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
- sound->getRealVolume(), getTimeScaledPitch(sound), false, sound->getUseEnv());
+ initCommon3D(source, sound->getPosition(), sound->getVelocity(), sound->getMinDistance(),
+ sound->getMaxDistance(), sound->getRealVolume(), getTimeScaledPitch(sound), false, sound->getUseEnv());
if (getALError() != AL_NO_ERROR)
return false;
@@ -1443,8 +1446,8 @@ namespace MWSound
OpenAL_SoundStream* stream = reinterpret_cast(sound->mHandle);
ALuint source = stream->mSource;
- updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
- getTimeScaledPitch(sound), sound->getUseEnv());
+ updateCommon(source, sound->getPosition(), sound->getVelocity(), sound->getMaxDistance(),
+ sound->getRealVolume(), getTimeScaledPitch(sound), sound->getUseEnv());
getALError();
}
@@ -1459,12 +1462,13 @@ namespace MWSound
}
void OpenALOutput::updateListener(
- const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env)
+ const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, const osg::Vec3f& vel, Environment env)
{
if (mContext)
{
ALfloat orient[6] = { atdir.x(), atdir.y(), atdir.z(), updir.x(), updir.y(), updir.z() };
alListenerfv(AL_POSITION, pos.ptr());
+ alListenerfv(AL_VELOCITY, vel.ptr());
alListenerfv(AL_ORIENTATION, orient);
if (env != mListenerEnv)
@@ -1497,6 +1501,7 @@ namespace MWSound
}
mListenerPos = pos;
+ mListenerVel = vel;
mListenerEnv = env;
}
@@ -1582,7 +1587,6 @@ namespace MWSound
: SoundOutput(mgr)
, mDevice(nullptr)
, mContext(nullptr)
- , mListenerPos(0.0f, 0.0f, 0.0f)
, mListenerEnv(Env_Normal)
, mWaterFilter(0)
, mWaterEffect(0)
diff --git a/apps/openmw/mwsound/openaloutput.hpp b/apps/openmw/mwsound/openaloutput.hpp
index 4e96dd1627..d689d08546 100644
--- a/apps/openmw/mwsound/openaloutput.hpp
+++ b/apps/openmw/mwsound/openaloutput.hpp
@@ -46,6 +46,7 @@ namespace MWSound
StreamVec mActiveStreams;
osg::Vec3f mListenerPos;
+ osg::Vec3f mListenerVel;
Environment mListenerEnv;
ALuint mWaterFilter;
@@ -64,11 +65,11 @@ namespace MWSound
std::unique_ptr mDefaultDeviceThread;
void initCommon2D(ALuint source, const osg::Vec3f& pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
- void initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist, ALfloat gain,
- ALfloat pitch, bool loop, bool useenv);
+ void initCommon3D(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat mindist, ALfloat maxdist,
+ ALfloat gain, ALfloat pitch, bool loop, bool useenv);
- void updateCommon(
- ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv);
+ void updateCommon(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat maxdist, ALfloat gain,
+ ALfloat pitch, bool useenv);
float getTimeScaledPitch(SoundBase* sound);
@@ -108,8 +109,8 @@ namespace MWSound
void startUpdate() override;
void finishUpdate() override;
- void updateListener(
- const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env) override;
+ void updateListener(const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir,
+ const osg::Vec3f& vel, Environment env) override;
void pauseSounds(int types) override;
void resumeSounds(int types) override;
diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp
index 5160b2934f..7d020c31f9 100644
--- a/apps/openmw/mwsound/sound.hpp
+++ b/apps/openmw/mwsound/sound.hpp
@@ -31,6 +31,8 @@ namespace MWSound
struct SoundParams
{
osg::Vec3f mPos;
+ osg::Vec3f mLastPos;
+ osg::Vec3f mVel;
float mVolume = 1.0f;
float mBaseVolume = 1.0f;
float mPitch = 1.0f;
@@ -57,6 +59,8 @@ namespace MWSound
public:
void setPosition(const osg::Vec3f& pos) { mParams.mPos = pos; }
+ void setLastPosition(const osg::Vec3f& lastpos) { mParams.mLastPos = lastpos; }
+ void setVelocity(const osg::Vec3f& vel) { mParams.mVel = vel; }
void setVolume(float volume) { mParams.mVolume = volume; }
void setBaseVolume(float volume) { mParams.mBaseVolume = volume; }
void setFadeout(float duration) { setFade(duration, 0.0, Play_StopAtFadeEnd); }
@@ -150,6 +154,8 @@ namespace MWSound
}
const osg::Vec3f& getPosition() const { return mParams.mPos; }
+ const osg::Vec3f& getLastPosition() const { return mParams.mLastPos; }
+ const osg::Vec3f& getVelocity() const { return mParams.mVel; }
float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume * mParams.mFadeVolume; }
float getPitch() const { return mParams.mPitch; }
float getMinDistance() const { return mParams.mMinDistance; }
diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp
index 66bdfbdbfa..86631448a9 100644
--- a/apps/openmw/mwsound/soundmanagerimp.cpp
+++ b/apps/openmw/mwsound/soundmanagerimp.cpp
@@ -119,6 +119,7 @@ namespace MWSound
, mListenerPos(0, 0, 0)
, mListenerDir(1, 0, 0)
, mListenerUp(0, 0, 1)
+ , mListenerVel(0, 0, 0)
, mUnderwaterSound(nullptr)
, mNearWaterSound(nullptr)
, mPlaybackPaused(false)
@@ -960,7 +961,7 @@ namespace MWSound
}
mOutput->startUpdate();
- mOutput->updateListener(mListenerPos, mListenerDir, mListenerUp, env);
+ mOutput->updateListener(mListenerPos, mListenerDir, mListenerUp, mListenerVel, env);
updateMusic(duration);
@@ -977,7 +978,13 @@ namespace MWSound
if (sound->getIs3D())
{
if (!ptr.isEmpty())
+ {
+ sound->setLastPosition(sound->getPosition());
sound->setPosition(ptr.getRefData().getPosition().asVec3());
+ MWBase::World* world = MWBase::Environment::get().getWorld();
+ sound->setVelocity(
+ (sound->getPosition() - sound->getLastPosition()) / world->getPhysicsFrameRateDt());
+ }
cull3DSound(sound);
}
@@ -1013,8 +1020,11 @@ namespace MWSound
{
if (!ptr.isEmpty())
{
+ sound->setLastPosition(sound->getPosition());
MWBase::World* world = MWBase::Environment::get().getWorld();
sound->setPosition(world->getActorHeadTransform(ptr).getTrans());
+ sound->setVelocity(
+ (sound->getPosition() - sound->getLastPosition()) / world->getPhysicsFrameRateDt());
}
cull3DSound(sound);
@@ -1153,6 +1163,11 @@ namespace MWSound
mWaterSoundUpdater.setUnderwater(underwater);
}
+ void SoundManager::setListenerVel(const osg::Vec3f& vel)
+ {
+ mListenerVel = vel;
+ }
+
void SoundManager::updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated)
{
SoundMap::iterator snditer = mActiveSounds.find(old.mRef);
diff --git a/apps/openmw/mwsound/soundmanagerimp.hpp b/apps/openmw/mwsound/soundmanagerimp.hpp
index 8fc7e6701f..f1b79557a0 100644
--- a/apps/openmw/mwsound/soundmanagerimp.hpp
+++ b/apps/openmw/mwsound/soundmanagerimp.hpp
@@ -92,6 +92,7 @@ namespace MWSound
osg::Vec3f mListenerPos;
osg::Vec3f mListenerDir;
osg::Vec3f mListenerUp;
+ osg::Vec3f mListenerVel;
int mPausedSoundTypes[BlockerType::MaxCount] = {};
@@ -283,6 +284,8 @@ namespace MWSound
void setListenerPosDir(
const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater) override;
+ void setListenerVel(const osg::Vec3f& vel) override;
+
void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) override;
void clear() override;
diff --git a/apps/openmw/mwsound/soundoutput.hpp b/apps/openmw/mwsound/soundoutput.hpp
index e5c266b204..4b24f159d3 100644
--- a/apps/openmw/mwsound/soundoutput.hpp
+++ b/apps/openmw/mwsound/soundoutput.hpp
@@ -61,8 +61,8 @@ namespace MWSound
virtual void startUpdate() = 0;
virtual void finishUpdate() = 0;
- virtual void updateListener(
- const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env)
+ virtual void updateListener(const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir,
+ const osg::Vec3f& vel, Environment env)
= 0;
virtual void pauseSounds(int types) = 0;
diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp
index 6ea510e1e2..c436f86df5 100644
--- a/apps/openmw/mwworld/projectilemanager.cpp
+++ b/apps/openmw/mwworld/projectilemanager.cpp
@@ -461,6 +461,11 @@ namespace MWWorld
update(magicBoltState, duration);
+ for (const auto& sound : magicBoltState.mSounds)
+ {
+ sound->setVelocity(direction * speed);
+ }
+
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit
// result.
std::vector targetActors;
diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp
index c07f5b9161..d8bc768b39 100644
--- a/apps/openmw/mwworld/worldimp.cpp
+++ b/apps/openmw/mwworld/worldimp.cpp
@@ -1460,6 +1460,8 @@ namespace MWWorld
void World::queueMovement(const Ptr& ptr, const osg::Vec3f& velocity)
{
mPhysics->queueObjectMovement(ptr, velocity);
+ if (ptr == MWMechanics::getPlayer())
+ MWBase::Environment::get().getSoundManager()->setListenerVel(velocity);
}
void World::updateAnimatedCollisionShape(const Ptr& ptr)
@@ -3182,6 +3184,11 @@ namespace MWWorld
return mWeatherManager->getSunPercentage(getTimeStamp().getHour());
}
+ float World::getPhysicsFrameRateDt() const
+ {
+ return mPhysics->mPhysicsDt;
+ }
+
bool World::findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result)
{
if (cell->isExterior())
diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp
index 16f91177a1..dfa0c33ecf 100644
--- a/apps/openmw/mwworld/worldimp.hpp
+++ b/apps/openmw/mwworld/worldimp.hpp
@@ -584,6 +584,8 @@ namespace MWWorld
float getSunVisibility() const override;
float getSunPercentage() const override;
+ float getPhysicsFrameRateDt() const override;
+
bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override;
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
diff --git a/components/settings/categories/sound.hpp b/components/settings/categories/sound.hpp
index 8398a38c55..99e70fcdb2 100644
--- a/components/settings/categories/sound.hpp
+++ b/components/settings/categories/sound.hpp
@@ -24,6 +24,7 @@ namespace Settings
SettingValue mHrtfEnable{ mIndex, "Sound", "hrtf enable" };
SettingValue mHrtf{ mIndex, "Sound", "hrtf" };
SettingValue mCameraListener{ mIndex, "Sound", "camera listener" };
+ SettingValue mDopplerFactor{ mIndex, "Sound", "doppler factor", makeClampSanitizerFloat(0, 1) };
};
}
diff --git a/docs/source/reference/modding/settings/sound.rst b/docs/source/reference/modding/settings/sound.rst
index e38cd9de78..4e73df989c 100644
--- a/docs/source/reference/modding/settings/sound.rst
+++ b/docs/source/reference/modding/settings/sound.rst
@@ -121,3 +121,13 @@ Sound Settings
When true, uses the camera position and direction for audio instead of the player position.
This makes audio in third person sound relative to camera instead of the player.
False is vanilla Morrowind behaviour.
+
+.. omw-setting::
+ :title: doppler factor
+ :type: float32
+ :range: 0.0 (disabled), 1.0 (maximum strength)
+ :default: 0.25
+ :location: :bdg-success:`Launcher > Settings > Audio`
+
+ This setting controls the strength of the Doppler effect. The Doppler effect increases or decreases the pitch of sounds
+ relative to the velocity of the sound source and the listener.
diff --git a/files/lang/launcher_de.ts b/files/lang/launcher_de.ts
index 80e44d7036..83d52c473d 100644
--- a/files/lang/launcher_de.ts
+++ b/files/lang/launcher_de.ts
@@ -1451,5 +1451,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
Run Script After Startup:
+
+ <html><head/><body><p>Controls the strength of the Doppler effect. Zero means it is completely disabled.</p><p>The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.</p></body></html>
+
+
+
+ Doppler Factor
+
+
diff --git a/files/lang/launcher_en.ts b/files/lang/launcher_en.ts
index 5b14aa0ade..4c3bd2819d 100644
--- a/files/lang/launcher_en.ts
+++ b/files/lang/launcher_en.ts
@@ -1451,5 +1451,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
<html><head/><body><p>If enabled - makes transitions between different animations/poses much smoother. Also allows to load animation blending config YAML files that can be bundled with animations in order to customise blending styles.</p></body></html>
+
+ <html><head/><body><p>Controls the strength of the Doppler effect. Zero means it is completely disabled.</p><p>The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.</p></body></html>
+
+
+
+ Doppler Factor
+
+
diff --git a/files/lang/launcher_fr.ts b/files/lang/launcher_fr.ts
index ad779ac896..2f4efe8161 100644
--- a/files/lang/launcher_fr.ts
+++ b/files/lang/launcher_fr.ts
@@ -1454,5 +1454,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
Run Script After Startup:
Script à lancer après démarrage :
+
+ <html><head/><body><p>Controls the strength of the Doppler effect. Zero means it is completely disabled.</p><p>The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.</p></body></html>
+
+
+
+ Doppler Factor
+
+
diff --git a/files/lang/launcher_ru.ts b/files/lang/launcher_ru.ts
index 57789902f7..bd7e05d128 100644
--- a/files/lang/launcher_ru.ts
+++ b/files/lang/launcher_ru.ts
@@ -1466,5 +1466,13 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
Use the Camera as the Sound Listener
Использовать камеру как слушателя
+
+ <html><head/><body><p>Controls the strength of the Doppler effect. Zero means it is completely disabled.</p><p>The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.</p></body></html>
+ <html><head/><body><p>Определяет силу эффекта Доплера. Нулевое значение означает, что эффект отключен полностью.</p><p>Эффект Доплера увеличивает или уменьшает высоту звуков в зависимости от скорости источника звука и слушателя.</p></body></html>
+
+
+ Doppler Factor
+ Множитель эффекта Доплера
+
diff --git a/files/lang/launcher_sv.ts b/files/lang/launcher_sv.ts
index e1903889b7..43bb4ce6e1 100644
--- a/files/lang/launcher_sv.ts
+++ b/files/lang/launcher_sv.ts
@@ -1470,5 +1470,13 @@ de ordinarie fonterna i Morrowind. Bocka denna ruta om du ändå föredrar ordin
<html><head/><body><p>If enabled - makes transitions between different animations/poses much smoother. Also allows to load animation blending config YAML files that can be bundled with animations in order to customise blending styles.</p></body></html>
<html><head/><body><p>Vid aktivering gör denna funktion att övergångarna mellan olika animationer och poser blir mycket mjukare. Funktionen gör det också möjligt att konfigurera animationsövergångarna i YAML-filer. Dessa filer kan buntas ihop tillsammans med nya animationsfiler.</p></body></html>
+
+ <html><head/><body><p>Controls the strength of the Doppler effect. Zero means it is completely disabled.</p><p>The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.</p></body></html>
+ <html><head/><body><p>Kontrollerar styrkan på dopplereffekten. Noll innebär helt inaktiverat.</p><p>Dopplereffekten höjer eller sänker tonhöjden på ljud i förhållande till ljudkällans hastighet och lyssnaren.</p></body></html>
+
+
+ Doppler Factor
+ Dopplerfaktor
+
diff --git a/files/settings-default.cfg b/files/settings-default.cfg
index 76be5bfc6b..c33f02ad35 100644
--- a/files/settings-default.cfg
+++ b/files/settings-default.cfg
@@ -624,6 +624,9 @@ hrtf =
# Specifies whether to use camera as audio listener
camera listener = false
+# Specifies strength of doppler effect
+doppler factor = 0.25
+
[Video]
# Resolution of the OpenMW window or screen.