Add an option to select and enable HRTF

openmw-38
Chris Robinson 9 years ago
parent 03a0b1fbfd
commit c75303b652

@ -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", "");
} }
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; std::cout <<"Sound init failed: "<<e.what()<< std::endl;
} }
} }
@ -100,17 +112,14 @@ namespace MWSound
SoundManager::~SoundManager() SoundManager::~SoundManager()
{ {
clear(); clear();
if(mOutput->isInitialized()) SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin();
for(;sfxiter != mSoundBuffers->end();++sfxiter)
{ {
SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin(); if(sfxiter->mHandle)
for(;sfxiter != mSoundBuffers->end();++sfxiter) mOutput->unloadSound(sfxiter->mHandle);
{ sfxiter->mHandle = 0;
if(sfxiter->mHandle)
mOutput->unloadSound(sfxiter->mHandle);
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…
Cancel
Save