forked from mirror/openmw-tes3mp
Merge pull request #843 from kcat/master
Add HRTF options and fix an incorrect SoundID
This commit is contained in:
commit
3890afd6f5
6 changed files with 173 additions and 20 deletions
|
@ -1103,7 +1103,7 @@ namespace MWClass
|
|||
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
|
||||
return "DefaultLandWater";
|
||||
if(world->isOnGround(ptr))
|
||||
return "Body Fall Medium";
|
||||
return "DefaultLand";
|
||||
return "";
|
||||
}
|
||||
if(name == "swimleft")
|
||||
|
|
|
@ -19,6 +19,28 @@
|
|||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
#endif
|
||||
|
||||
#ifndef ALC_SOFT_HRTF
|
||||
#define ALC_SOFT_HRTF 1
|
||||
#define ALC_HRTF_SOFT 0x1992
|
||||
#define ALC_DONT_CARE_SOFT 0x0002
|
||||
#define ALC_HRTF_STATUS_SOFT 0x1993
|
||||
#define ALC_HRTF_DISABLED_SOFT 0x0000
|
||||
#define ALC_HRTF_ENABLED_SOFT 0x0001
|
||||
#define ALC_HRTF_DENIED_SOFT 0x0002
|
||||
#define ALC_HRTF_REQUIRED_SOFT 0x0003
|
||||
#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004
|
||||
#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005
|
||||
#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994
|
||||
#define ALC_HRTF_SPECIFIER_SOFT 0x1995
|
||||
#define ALC_HRTF_ID_SOFT 0x1996
|
||||
typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index);
|
||||
typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index);
|
||||
ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define MAKE_PTRID(id) ((void*)(uintptr_t)id)
|
||||
#define GET_PTRID(ptr) ((ALuint)(uintptr_t)ptr)
|
||||
|
@ -571,6 +593,113 @@ void OpenAL_Output::deinit()
|
|||
}
|
||||
|
||||
|
||||
std::vector<std::string> OpenAL_Output::enumerateHrtf()
|
||||
{
|
||||
if(!mDevice)
|
||||
fail("Device not initialized");
|
||||
|
||||
std::vector<std::string> ret;
|
||||
if(!alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF"))
|
||||
return ret;
|
||||
|
||||
LPALCGETSTRINGISOFT alcGetStringiSOFT = reinterpret_cast<LPALCGETSTRINGISOFT>(
|
||||
alcGetProcAddress(mDevice, "alcGetStringiSOFT")
|
||||
);
|
||||
|
||||
ALCint num_hrtf;
|
||||
alcGetIntegerv(mDevice, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf);
|
||||
ret.reserve(num_hrtf);
|
||||
for(ALCint i = 0;i < num_hrtf;++i)
|
||||
{
|
||||
const ALCchar *entry = alcGetStringiSOFT(mDevice, ALC_HRTF_SPECIFIER_SOFT, i);
|
||||
ret.push_back(entry);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void OpenAL_Output::enableHrtf(const std::string &hrtfname, bool auto_enable)
|
||||
{
|
||||
if(!alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF"))
|
||||
{
|
||||
std::cerr<< "HRTF extension not present" <<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
LPALCGETSTRINGISOFT alcGetStringiSOFT = reinterpret_cast<LPALCGETSTRINGISOFT>(
|
||||
alcGetProcAddress(mDevice, "alcGetStringiSOFT")
|
||||
);
|
||||
LPALCRESETDEVICESOFT alcResetDeviceSOFT = reinterpret_cast<LPALCRESETDEVICESOFT>(
|
||||
alcGetProcAddress(mDevice, "alcResetDeviceSOFT")
|
||||
);
|
||||
|
||||
std::vector<ALCint> attrs;
|
||||
attrs.push_back(ALC_HRTF_SOFT);
|
||||
attrs.push_back(auto_enable ? ALC_DONT_CARE_SOFT : ALC_TRUE);
|
||||
if(!hrtfname.empty())
|
||||
{
|
||||
ALCint index = -1;
|
||||
ALCint num_hrtf;
|
||||
alcGetIntegerv(mDevice, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf);
|
||||
for(ALCint i = 0;i < num_hrtf;++i)
|
||||
{
|
||||
const ALCchar *entry = alcGetStringiSOFT(mDevice, ALC_HRTF_SPECIFIER_SOFT, i);
|
||||
if(hrtfname == entry)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(index < 0)
|
||||
std::cerr<< "Failed to find HRTF name \""<<hrtfname<<"\", using default" <<std::endl;
|
||||
else
|
||||
{
|
||||
attrs.push_back(ALC_HRTF_ID_SOFT);
|
||||
attrs.push_back(index);
|
||||
}
|
||||
}
|
||||
attrs.push_back(0);
|
||||
alcResetDeviceSOFT(mDevice, &attrs[0]);
|
||||
|
||||
ALCint hrtf_state;
|
||||
alcGetIntegerv(mDevice, ALC_HRTF_SOFT, 1, &hrtf_state);
|
||||
if(!hrtf_state)
|
||||
std::cerr<< "Failed to enable HRTF" <<std::endl;
|
||||
else
|
||||
{
|
||||
const ALCchar *hrtf = alcGetString(mDevice, ALC_HRTF_SPECIFIER_SOFT);
|
||||
std::cout<< "Enabled HRTF "<<hrtf <<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenAL_Output::disableHrtf()
|
||||
{
|
||||
if(!alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF"))
|
||||
{
|
||||
std::cerr<< "HRTF extension not present" <<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
LPALCRESETDEVICESOFT alcResetDeviceSOFT = reinterpret_cast<LPALCRESETDEVICESOFT>(
|
||||
alcGetProcAddress(mDevice, "alcResetDeviceSOFT")
|
||||
);
|
||||
|
||||
std::vector<ALCint> attrs;
|
||||
attrs.push_back(ALC_HRTF_SOFT);
|
||||
attrs.push_back(ALC_FALSE);
|
||||
attrs.push_back(0);
|
||||
alcResetDeviceSOFT(mDevice, &attrs[0]);
|
||||
|
||||
ALCint hrtf_state;
|
||||
alcGetIntegerv(mDevice, ALC_HRTF_SOFT, 1, &hrtf_state);
|
||||
if(hrtf_state)
|
||||
std::cerr<< "Failed to disable HRTF" <<std::endl;
|
||||
else
|
||||
std::cout<< "Disabled HRTF" <<std::endl;
|
||||
}
|
||||
|
||||
|
||||
Sound_Handle OpenAL_Output::loadSound(const std::string &fname)
|
||||
{
|
||||
throwALerror();
|
||||
|
|
|
@ -45,9 +45,13 @@ namespace MWSound
|
|||
|
||||
public:
|
||||
virtual std::vector<std::string> enumerate();
|
||||
virtual void init(const std::string &devname="");
|
||||
virtual void init(const std::string &devname=std::string());
|
||||
virtual void deinit();
|
||||
|
||||
virtual std::vector<std::string> enumerateHrtf();
|
||||
virtual void enableHrtf(const std::string &hrtfname, bool auto_enable);
|
||||
virtual void disableHrtf();
|
||||
|
||||
virtual Sound_Handle loadSound(const std::string &fname);
|
||||
virtual void unloadSound(Sound_Handle data);
|
||||
virtual size_t getSoundDataSize(Sound_Handle data) const;
|
||||
|
|
|
@ -24,9 +24,13 @@ namespace MWSound
|
|||
SoundManager &mManager;
|
||||
|
||||
virtual std::vector<std::string> enumerate() = 0;
|
||||
virtual void init(const std::string &devname="") = 0;
|
||||
virtual void init(const std::string &devname=std::string()) = 0;
|
||||
virtual void deinit() = 0;
|
||||
|
||||
virtual std::vector<std::string> enumerateHrtf() = 0;
|
||||
virtual void enableHrtf(const std::string &hrtfname, bool auto_enable) = 0;
|
||||
virtual void disableHrtf() = 0;
|
||||
|
||||
virtual Sound_Handle loadSound(const std::string &fname) = 0;
|
||||
virtual void unloadSound(Sound_Handle data) = 0;
|
||||
virtual size_t getSoundDataSize(Sound_Handle data) const = 0;
|
||||
|
|
|
@ -67,32 +67,44 @@ namespace MWSound
|
|||
mBufferCacheMax *= 1024*1024;
|
||||
mBufferCacheMin = std::min(mBufferCacheMin*1024*1024, mBufferCacheMax);
|
||||
|
||||
std::string hrtfname = Settings::Manager::getString("hrtf", "Sound");
|
||||
int hrtfstate = Settings::Manager::getInt("hrtf enable", "Sound");
|
||||
|
||||
std::cout << "Sound output: " << SOUND_OUT << std::endl;
|
||||
std::cout << "Sound decoder: " << SOUND_IN << std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
std::vector<std::string> names = mOutput->enumerate();
|
||||
std::cout <<"Enumerated output devices:"<< std::endl;
|
||||
for(size_t i = 0;i < names.size();i++)
|
||||
std::cout <<" "<<names[i]<< std::endl;
|
||||
|
||||
std::string devname = Settings::Manager::getString("device", "Sound");
|
||||
try
|
||||
{
|
||||
try {
|
||||
mOutput->init(devname);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
catch(std::exception &e) {
|
||||
if(devname.empty())
|
||||
throw;
|
||||
std::cerr <<"Failed to open device \""<<devname<<"\": " << e.what() << std::endl;
|
||||
mOutput->init();
|
||||
Settings::Manager::setString("device", "Sound", "");
|
||||
}
|
||||
|
||||
names = mOutput->enumerateHrtf();
|
||||
if(!names.empty())
|
||||
{
|
||||
std::cout <<"Enumerated HRTF names:"<< std::endl;
|
||||
for(size_t i = 0;i < names.size();i++)
|
||||
std::cout <<" "<<names[i]<< std::endl;
|
||||
}
|
||||
|
||||
if(hrtfstate == 0)
|
||||
mOutput->disableHrtf();
|
||||
else if(!hrtfname.empty())
|
||||
mOutput->enableHrtf(hrtfname, hrtfstate<0);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
catch(std::exception &e) {
|
||||
std::cout <<"Sound init failed: "<<e.what()<< std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -100,17 +112,14 @@ namespace MWSound
|
|||
SoundManager::~SoundManager()
|
||||
{
|
||||
clear();
|
||||
if(mOutput->isInitialized())
|
||||
SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin();
|
||||
for(;sfxiter != mSoundBuffers->end();++sfxiter)
|
||||
{
|
||||
SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin();
|
||||
for(;sfxiter != mSoundBuffers->end();++sfxiter)
|
||||
{
|
||||
if(sfxiter->mHandle)
|
||||
mOutput->unloadSound(sfxiter->mHandle);
|
||||
sfxiter->mHandle = 0;
|
||||
}
|
||||
mUnusedBuffers.clear();
|
||||
if(sfxiter->mHandle)
|
||||
mOutput->unloadSound(sfxiter->mHandle);
|
||||
sfxiter->mHandle = 0;
|
||||
}
|
||||
mUnusedBuffers.clear();
|
||||
mOutput.reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -179,6 +179,13 @@ buffer cache min = 14
|
|||
# to this much memory until old buffers get purged.
|
||||
buffer cache max = 16
|
||||
|
||||
# Specifies whether to enable HRTF processing. Valid values are: -1 = auto,
|
||||
# 0 = off, 1 = on.
|
||||
hrtf enable = -1
|
||||
|
||||
# Specifies which HRTF to use when HRTF is used. Blank means use the default.
|
||||
hrtf =
|
||||
|
||||
[Video]
|
||||
|
||||
# Resolution of the OpenMW window or screen.
|
||||
|
|
Loading…
Reference in a new issue