mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 07:53:53 +00:00
Add an option to select and enable HRTF
This commit is contained in:
parent
03a0b1fbfd
commit
c75303b652
5 changed files with 172 additions and 19 deletions
|
@ -19,6 +19,28 @@
|
||||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||||
#endif
|
#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 MAKE_PTRID(id) ((void*)(uintptr_t)id)
|
||||||
#define GET_PTRID(ptr) ((ALuint)(uintptr_t)ptr)
|
#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)
|
Sound_Handle OpenAL_Output::loadSound(const std::string &fname)
|
||||||
{
|
{
|
||||||
throwALerror();
|
throwALerror();
|
||||||
|
|
|
@ -45,9 +45,13 @@ namespace MWSound
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual std::vector<std::string> enumerate();
|
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 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 Sound_Handle loadSound(const std::string &fname);
|
||||||
virtual void unloadSound(Sound_Handle data);
|
virtual void unloadSound(Sound_Handle data);
|
||||||
virtual size_t getSoundDataSize(Sound_Handle data) const;
|
virtual size_t getSoundDataSize(Sound_Handle data) const;
|
||||||
|
|
|
@ -24,9 +24,13 @@ namespace MWSound
|
||||||
SoundManager &mManager;
|
SoundManager &mManager;
|
||||||
|
|
||||||
virtual std::vector<std::string> enumerate() = 0;
|
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 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 Sound_Handle loadSound(const std::string &fname) = 0;
|
||||||
virtual void unloadSound(Sound_Handle data) = 0;
|
virtual void unloadSound(Sound_Handle data) = 0;
|
||||||
virtual size_t getSoundDataSize(Sound_Handle data) const = 0;
|
virtual size_t getSoundDataSize(Sound_Handle data) const = 0;
|
||||||
|
|
|
@ -67,32 +67,44 @@ namespace MWSound
|
||||||
mBufferCacheMax *= 1024*1024;
|
mBufferCacheMax *= 1024*1024;
|
||||||
mBufferCacheMin = std::min(mBufferCacheMin*1024*1024, mBufferCacheMax);
|
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 output: " << SOUND_OUT << std::endl;
|
||||||
std::cout << "Sound decoder: " << SOUND_IN << std::endl;
|
std::cout << "Sound decoder: " << SOUND_IN << std::endl;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
std::vector<std::string> names = mOutput->enumerate();
|
std::vector<std::string> names = mOutput->enumerate();
|
||||||
std::cout <<"Enumerated output devices:"<< std::endl;
|
std::cout <<"Enumerated output devices:"<< std::endl;
|
||||||
for(size_t i = 0;i < names.size();i++)
|
for(size_t i = 0;i < names.size();i++)
|
||||||
std::cout <<" "<<names[i]<< std::endl;
|
std::cout <<" "<<names[i]<< std::endl;
|
||||||
|
|
||||||
std::string devname = Settings::Manager::getString("device", "Sound");
|
std::string devname = Settings::Manager::getString("device", "Sound");
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
mOutput->init(devname);
|
mOutput->init(devname);
|
||||||
}
|
}
|
||||||
catch(std::exception &e)
|
catch(std::exception &e) {
|
||||||
{
|
|
||||||
if(devname.empty())
|
if(devname.empty())
|
||||||
throw;
|
throw;
|
||||||
std::cerr <<"Failed to open device \""<<devname<<"\": " << e.what() << std::endl;
|
std::cerr <<"Failed to open device \""<<devname<<"\": " << e.what() << std::endl;
|
||||||
mOutput->init();
|
mOutput->init();
|
||||||
Settings::Manager::setString("device", "Sound", "");
|
Settings::Manager::setString("device", "Sound", "");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch(std::exception &e)
|
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) {
|
||||||
std::cout <<"Sound init failed: "<<e.what()<< std::endl;
|
std::cout <<"Sound init failed: "<<e.what()<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,8 +112,6 @@ namespace MWSound
|
||||||
SoundManager::~SoundManager()
|
SoundManager::~SoundManager()
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
if(mOutput->isInitialized())
|
|
||||||
{
|
|
||||||
SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin();
|
SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin();
|
||||||
for(;sfxiter != mSoundBuffers->end();++sfxiter)
|
for(;sfxiter != mSoundBuffers->end();++sfxiter)
|
||||||
{
|
{
|
||||||
|
@ -110,7 +120,6 @@ namespace MWSound
|
||||||
sfxiter->mHandle = 0;
|
sfxiter->mHandle = 0;
|
||||||
}
|
}
|
||||||
mUnusedBuffers.clear();
|
mUnusedBuffers.clear();
|
||||||
}
|
|
||||||
mOutput.reset();
|
mOutput.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,13 @@ buffer cache min = 14
|
||||||
# to this much memory until old buffers get purged.
|
# to this much memory until old buffers get purged.
|
||||||
buffer cache max = 16
|
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]
|
[Video]
|
||||||
|
|
||||||
# Resolution of the OpenMW window or screen.
|
# Resolution of the OpenMW window or screen.
|
||||||
|
|
Loading…
Reference in a new issue