Skip to content

Commit 883e1dd

Browse files
committed
Adjusted sound volume to follow Skyrims master volume setting, increased OpenAL active sounds limit to 4000 and improved error handling
1 parent f9779ac commit 883e1dd

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

src/SoundFX/Sound/Sound3DUtil.cpp

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace SoundFX {
77
bool
88
Sound3DUtil::InitializeOpenAL() {
99
if (!InitializeSharedContext()) {
10-
spdlog::error("OpenAL could not be initialized.");
10+
spdlog::critical("OpenAL could not be initialized.");
1111
return false;
1212
}
1313
return true;
@@ -33,7 +33,7 @@ namespace SoundFX {
3333
Sound3DUtil::InitializeDevice() {
3434
ALCdevice *device = alcOpenDevice(nullptr);
3535
if (!device) {
36-
spdlog::error("Failed to open OpenAL device.");
36+
spdlog::critical("Failed to open OpenAL device.");
3737
}
3838
return device;
3939
}
@@ -44,9 +44,15 @@ namespace SoundFX {
4444
return nullptr;
4545
}
4646

47-
ALCcontext *context = alcCreateContext(device, nullptr);
47+
const ALCint attributes[] = {ALC_MONO_SOURCES,
48+
4000, // Maximum number of mono sources
49+
ALC_STEREO_SOURCES,
50+
4000, // Maximum number of stereo sources
51+
0};
52+
53+
ALCcontext *context = alcCreateContext(device, attributes);
4854
if (!context || alcMakeContextCurrent(context) == ALC_FALSE) {
49-
spdlog::error("Failed to create or set OpenAL context.");
55+
spdlog::critical("Failed to create or set OpenAL context.");
5056
alcDestroyContext(context);
5157
alcCloseDevice(device);
5258
return nullptr;
@@ -81,7 +87,12 @@ namespace SoundFX {
8187
}
8288

8389
std::vector<short> samples(fileInfo.frames * fileInfo.channels);
84-
sf_read_short(sndFile, samples.data(), static_cast<sf_count_t>(samples.size()));
90+
if (sf_read_short(sndFile, samples.data(), static_cast<sf_count_t>(samples.size()))
91+
< samples.size()) {
92+
spdlog::error("Failed to read audio samples from file: {}", filePath);
93+
sf_close(sndFile);
94+
return 0;
95+
}
8596
sf_close(sndFile);
8697

8798
ALuint buffer;
@@ -92,6 +103,11 @@ namespace SoundFX {
92103
samples.data(),
93104
static_cast<ALsizei>(samples.size() * sizeof(short)),
94105
fileInfo.samplerate);
106+
if (alGetError() != AL_NO_ERROR) {
107+
spdlog::error("Failed to fill OpenAL buffer with audio data.");
108+
alDeleteBuffers(1, &buffer);
109+
return 0;
110+
}
95111

96112
{
97113
std::lock_guard lock(bufferCacheMutex);
@@ -139,14 +155,23 @@ namespace SoundFX {
139155

140156
ALuint source;
141157
alGenSources(1, &source);
158+
if (alGetError() != AL_NO_ERROR) {
159+
spdlog::error("Failed to generate OpenAL source.");
160+
return 0;
161+
}
162+
142163
alSourcei(source, AL_BUFFER, static_cast<ALint>(buffer));
143164
alSourcef(source, AL_REFERENCE_DISTANCE, referenceDistance);
144165
alSourcef(source, AL_MAX_DISTANCE, maxDistance);
145166
alSourcef(source, AL_ROLLOFF_FACTOR, rolloffFactor);
146-
alSourcef(source, AL_GAIN, gain);
147167
alSourcef(source, AL_MIN_GAIN, minGain);
148168

149169
alSourcePlay(source);
170+
if (alGetError() != AL_NO_ERROR) {
171+
spdlog::error("Failed to play OpenAL source.");
172+
alDeleteSources(1, &source);
173+
return 0;
174+
}
150175

151176
std::thread([source, worldSourcePos, maxDistance, gain] {
152177
ALint state = AL_PLAYING;
@@ -170,7 +195,15 @@ namespace SoundFX {
170195
const float distance = relativeSourcePos.Length();
171196
float volume = 1.0f - distance / maxDistance;
172197
volume = std::clamp(volume, 0.0f, 1.0f);
173-
alSourcef(source, AL_GAIN, volume * gain);
198+
199+
const float ingameVolume = GetIngameVolumeFactor();
200+
const float finalVolume = volume * gain * ingameVolume;
201+
202+
float currentGain;
203+
alGetSourcef(source, AL_GAIN, &currentGain);
204+
if (std::abs(currentGain - finalVolume) > 0.01f) {
205+
alSourcef(source, AL_GAIN, finalVolume);
206+
}
174207

175208
const RE::NiPoint3 forwardVector = GetForwardVector(player->Get3D());
176209
constexpr RE::NiPoint3 upVector = {0.0f, 0.0f, 1.0f};
@@ -191,10 +224,13 @@ namespace SoundFX {
191224
}
192225

193226
alGetSourcei(source, AL_SOURCE_STATE, &state);
194-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
227+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
195228
}
196229

197230
alDeleteSources(1, &source);
231+
if (alGetError() != AL_NO_ERROR) {
232+
spdlog::critical("Failed to delete OpenAL source: {}", source);
233+
}
198234
}).detach();
199235

200236
return source;
@@ -218,4 +254,18 @@ namespace SoundFX {
218254
}
219255
}
220256

257+
float
258+
Sound3DUtil::GetIngameVolumeFactor() {
259+
if (auto *settings = RE::INIPrefSettingCollection::GetSingleton()) {
260+
if (const auto *volumeSetting = settings->GetSetting("fAudioMasterVolume:AudioMenu")) {
261+
const float newVolume = volumeSetting->data.f;
262+
constexpr float epsilon = 0.0001f;
263+
if (std::abs(newVolume - cachedVolume.load()) > epsilon) {
264+
cachedVolume.store(newVolume);
265+
}
266+
return cachedVolume.load();
267+
}
268+
}
269+
return 1.0f;
270+
}
221271
}

src/SoundFX/Sound/Sound3DUtil.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ namespace SoundFX {
3535

3636
static bool
3737
InitializeSharedContext();
38+
static float
39+
GetIngameVolumeFactor();
3840

3941
static inline ALCdevice *sharedDevice = nullptr;
4042
static inline ALCcontext *sharedContext = nullptr;
4143
static inline std::unordered_map<std::string, ALuint> bufferCache;
4244
static inline std::mutex bufferCacheMutex;
45+
static inline std::atomic<float> cachedVolume = 1.0f;
4346
};
4447

4548
}

0 commit comments

Comments
 (0)