Merge pull request #843 from kcat/master

Add HRTF options and fix an incorrect SoundID
openmw-38
scrawl 9 years ago
commit 3890afd6f5

@ -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", "");
}
}
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;
}
}
@ -100,8 +112,6 @@ namespace MWSound
SoundManager::~SoundManager()
{
clear();
if(mOutput->isInitialized())
{
SoundBufferList::element_type::iterator sfxiter = mSoundBuffers->begin();
for(;sfxiter != mSoundBuffers->end();++sfxiter)
{
@ -110,7 +120,6 @@ namespace MWSound
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…
Cancel
Save