mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
Add audio volume controls to settings
This commit is contained in:
parent
f5185c08cf
commit
7060c80b81
9 changed files with 79 additions and 5 deletions
|
|
@ -30,6 +30,8 @@ public:
|
||||||
void playWaterEnter();
|
void playWaterEnter();
|
||||||
void playWaterExit();
|
void playWaterExit();
|
||||||
void playMeleeSwing();
|
void playMeleeSwing();
|
||||||
|
void setVolumeScale(float scale) { volumeScale = scale; }
|
||||||
|
float getVolumeScale() const { return volumeScale; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Sample {
|
struct Sample {
|
||||||
|
|
@ -66,6 +68,7 @@ private:
|
||||||
std::chrono::steady_clock::time_point lastMeleeSwingAt{};
|
std::chrono::steady_clock::time_point lastMeleeSwingAt{};
|
||||||
bool meleeSwingWarned = false;
|
bool meleeSwingWarned = false;
|
||||||
std::string voiceProfileKey;
|
std::string voiceProfileKey;
|
||||||
|
float volumeScale = 1.0f;
|
||||||
|
|
||||||
void preloadCandidates(std::vector<Sample>& out, const std::vector<std::string>& candidates);
|
void preloadCandidates(std::vector<Sample>& out, const std::vector<std::string>& candidates);
|
||||||
void preloadLandingSet(FootstepSurface surface, const std::string& material);
|
void preloadLandingSet(FootstepSurface surface, const std::string& material);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ public:
|
||||||
|
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
void playFootstep(FootstepSurface surface, bool sprinting);
|
void playFootstep(FootstepSurface surface, bool sprinting);
|
||||||
|
void setVolumeScale(float scale) { volumeScale = scale; }
|
||||||
|
float getVolumeScale() const { return volumeScale; }
|
||||||
|
|
||||||
bool isInitialized() const { return assetManager != nullptr; }
|
bool isInitialized() const { return assetManager != nullptr; }
|
||||||
bool hasAnySamples() const { return sampleCount > 0; }
|
bool hasAnySamples() const { return sampleCount > 0; }
|
||||||
|
|
@ -61,6 +63,7 @@ private:
|
||||||
std::chrono::steady_clock::time_point lastPlayTime = std::chrono::steady_clock::time_point{};
|
std::chrono::steady_clock::time_point lastPlayTime = std::chrono::steady_clock::time_point{};
|
||||||
|
|
||||||
std::mt19937 rng;
|
std::mt19937 rng;
|
||||||
|
float volumeScale = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace audio
|
} // namespace audio
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ public:
|
||||||
void stopMusic(float fadeMs = 2000.0f);
|
void stopMusic(float fadeMs = 2000.0f);
|
||||||
void crossfadeTo(const std::string& mpqPath, float fadeMs = 3000.0f);
|
void crossfadeTo(const std::string& mpqPath, float fadeMs = 3000.0f);
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
|
void setVolume(int volume);
|
||||||
|
int getVolume() const { return volumePercent; }
|
||||||
|
|
||||||
bool isPlaying() const { return playing; }
|
bool isPlaying() const { return playing; }
|
||||||
bool isInitialized() const { return assetManager != nullptr; }
|
bool isInitialized() const { return assetManager != nullptr; }
|
||||||
|
|
@ -32,9 +34,11 @@ private:
|
||||||
|
|
||||||
pipeline::AssetManager* assetManager = nullptr;
|
pipeline::AssetManager* assetManager = nullptr;
|
||||||
std::string currentTrack;
|
std::string currentTrack;
|
||||||
|
bool currentTrackIsFile = false;
|
||||||
std::string tempFilePath;
|
std::string tempFilePath;
|
||||||
ProcessHandle playerPid = INVALID_PROCESS;
|
ProcessHandle playerPid = INVALID_PROCESS;
|
||||||
bool playing = false;
|
bool playing = false;
|
||||||
|
int volumePercent = 30;
|
||||||
|
|
||||||
// Crossfade state
|
// Crossfade state
|
||||||
bool crossfading = false;
|
bool crossfading = false;
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,8 @@ public:
|
||||||
double getLastWMORenderMs() const { return lastWMORenderMs; }
|
double getLastWMORenderMs() const { return lastWMORenderMs; }
|
||||||
double getLastM2RenderMs() const { return lastM2RenderMs; }
|
double getLastM2RenderMs() const { return lastM2RenderMs; }
|
||||||
audio::MusicManager* getMusicManager() { return musicManager.get(); }
|
audio::MusicManager* getMusicManager() { return musicManager.get(); }
|
||||||
|
audio::FootstepManager* getFootstepManager() { return footstepManager.get(); }
|
||||||
|
audio::ActivitySoundManager* getActivitySoundManager() { return activitySoundManager.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
core::Window* window = nullptr;
|
core::Window* window = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ private:
|
||||||
bool pendingVsync = false;
|
bool pendingVsync = false;
|
||||||
int pendingResIndex = 0;
|
int pendingResIndex = 0;
|
||||||
bool pendingShadows = true;
|
bool pendingShadows = true;
|
||||||
|
int pendingMusicVolume = 30;
|
||||||
|
int pendingSfxVolume = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render player info window
|
* Render player info window
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,7 @@ bool ActivitySoundManager::playOneShot(const std::vector<Sample>& clips, float v
|
||||||
|
|
||||||
std::uniform_real_distribution<float> pitchDist(pitchLo, pitchHi);
|
std::uniform_real_distribution<float> pitchDist(pitchLo, pitchHi);
|
||||||
float pitch = pitchDist(rng);
|
float pitch = pitchDist(rng);
|
||||||
|
volume *= volumeScale;
|
||||||
if (volume < 0.1f) volume = 0.1f;
|
if (volume < 0.1f) volume = 0.1f;
|
||||||
if (volume > 1.2f) volume = 1.2f;
|
if (volume > 1.2f) volume = 1.2f;
|
||||||
std::string filter = "asetrate=44100*" + std::to_string(pitch) +
|
std::string filter = "asetrate=44100*" + std::to_string(pitch) +
|
||||||
|
|
@ -241,7 +242,7 @@ void ActivitySoundManager::startSwimLoop() {
|
||||||
out.write(reinterpret_cast<const char*>(sample.data.data()), static_cast<std::streamsize>(sample.data.size()));
|
out.write(reinterpret_cast<const char*>(sample.data.data()), static_cast<std::streamsize>(sample.data.size()));
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
float volume = swimMoving ? 0.85f : 0.65f;
|
float volume = (swimMoving ? 0.85f : 0.65f) * volumeScale;
|
||||||
std::string filter = "volume=" + std::to_string(volume);
|
std::string filter = "volume=" + std::to_string(volume);
|
||||||
|
|
||||||
swimLoopPid = platform::spawnProcess({
|
swimLoopPid = platform::spawnProcess({
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ bool FootstepManager::playRandomStep(FootstepSurface surface, bool sprinting) {
|
||||||
std::uniform_real_distribution<float> pitchDist(0.97f, 1.05f);
|
std::uniform_real_distribution<float> pitchDist(0.97f, 1.05f);
|
||||||
std::uniform_real_distribution<float> volumeDist(0.92f, 1.00f);
|
std::uniform_real_distribution<float> volumeDist(0.92f, 1.00f);
|
||||||
float pitch = pitchDist(rng);
|
float pitch = pitchDist(rng);
|
||||||
float volume = volumeDist(rng) * (sprinting ? 1.0f : 0.88f);
|
float volume = volumeDist(rng) * (sprinting ? 1.0f : 0.88f) * volumeScale;
|
||||||
if (volume > 1.0f) volume = 1.0f;
|
if (volume > 1.0f) volume = 1.0f;
|
||||||
if (volume < 0.1f) volume = 0.1f;
|
if (volume < 0.1f) volume = 0.1f;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,13 +60,14 @@ void MusicManager::playMusic(const std::string& mpqPath, bool loop) {
|
||||||
args.push_back("0");
|
args.push_back("0");
|
||||||
}
|
}
|
||||||
args.push_back("-volume");
|
args.push_back("-volume");
|
||||||
args.push_back("30");
|
args.push_back(std::to_string(volumePercent));
|
||||||
args.push_back(tempFilePath);
|
args.push_back(tempFilePath);
|
||||||
|
|
||||||
playerPid = platform::spawnProcess(args);
|
playerPid = platform::spawnProcess(args);
|
||||||
if (playerPid != INVALID_PROCESS) {
|
if (playerPid != INVALID_PROCESS) {
|
||||||
playing = true;
|
playing = true;
|
||||||
currentTrack = mpqPath;
|
currentTrack = mpqPath;
|
||||||
|
currentTrackIsFile = false;
|
||||||
LOG_INFO("Music: Playing ", mpqPath);
|
LOG_INFO("Music: Playing ", mpqPath);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("Music: Failed to spawn ffplay process");
|
LOG_ERROR("Music: Failed to spawn ffplay process");
|
||||||
|
|
@ -91,13 +92,14 @@ void MusicManager::playFilePath(const std::string& filePath, bool loop) {
|
||||||
args.push_back("0");
|
args.push_back("0");
|
||||||
}
|
}
|
||||||
args.push_back("-volume");
|
args.push_back("-volume");
|
||||||
args.push_back("30");
|
args.push_back(std::to_string(volumePercent));
|
||||||
args.push_back(filePath);
|
args.push_back(filePath);
|
||||||
|
|
||||||
playerPid = platform::spawnProcess(args);
|
playerPid = platform::spawnProcess(args);
|
||||||
if (playerPid != INVALID_PROCESS) {
|
if (playerPid != INVALID_PROCESS) {
|
||||||
playing = true;
|
playing = true;
|
||||||
currentTrack = filePath;
|
currentTrack = filePath;
|
||||||
|
currentTrackIsFile = true;
|
||||||
LOG_INFO("Music: Playing file ", filePath);
|
LOG_INFO("Music: Playing file ", filePath);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR("Music: Failed to spawn ffplay process");
|
LOG_ERROR("Music: Failed to spawn ffplay process");
|
||||||
|
|
@ -109,6 +111,27 @@ void MusicManager::stopMusic(float fadeMs) {
|
||||||
stopCurrentProcess();
|
stopCurrentProcess();
|
||||||
playing = false;
|
playing = false;
|
||||||
currentTrack.clear();
|
currentTrack.clear();
|
||||||
|
currentTrackIsFile = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MusicManager::setVolume(int volume) {
|
||||||
|
if (volume < 0) volume = 0;
|
||||||
|
if (volume > 100) volume = 100;
|
||||||
|
if (volumePercent == volume) return;
|
||||||
|
volumePercent = volume;
|
||||||
|
if (playing && !currentTrack.empty()) {
|
||||||
|
std::string track = currentTrack;
|
||||||
|
bool isFile = currentTrackIsFile;
|
||||||
|
stopCurrentProcess();
|
||||||
|
playing = false;
|
||||||
|
currentTrack.clear();
|
||||||
|
currentTrackIsFile = false;
|
||||||
|
if (isFile) {
|
||||||
|
playFilePath(track, true);
|
||||||
|
} else {
|
||||||
|
playMusic(track, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MusicManager::crossfadeTo(const std::string& mpqPath, float fadeMs) {
|
void MusicManager::crossfadeTo(const std::string& mpqPath, float fadeMs) {
|
||||||
|
|
|
||||||
|
|
@ -1807,6 +1807,22 @@ void GameScreen::renderSettingsWindow() {
|
||||||
pendingFullscreen = window->isFullscreen();
|
pendingFullscreen = window->isFullscreen();
|
||||||
pendingVsync = window->isVsyncEnabled();
|
pendingVsync = window->isVsyncEnabled();
|
||||||
pendingShadows = renderer ? renderer->areShadowsEnabled() : true;
|
pendingShadows = renderer ? renderer->areShadowsEnabled() : true;
|
||||||
|
if (renderer) {
|
||||||
|
if (auto* music = renderer->getMusicManager()) {
|
||||||
|
pendingMusicVolume = music->getVolume();
|
||||||
|
}
|
||||||
|
if (auto* footstep = renderer->getFootstepManager()) {
|
||||||
|
float scale = footstep->getVolumeScale();
|
||||||
|
pendingSfxVolume = static_cast<int>(scale * 100.0f + 0.5f);
|
||||||
|
if (pendingSfxVolume < 0) pendingSfxVolume = 0;
|
||||||
|
if (pendingSfxVolume > 100) pendingSfxVolume = 100;
|
||||||
|
} else if (auto* activity = renderer->getActivitySoundManager()) {
|
||||||
|
float scale = activity->getVolumeScale();
|
||||||
|
pendingSfxVolume = static_cast<int>(scale * 100.0f + 0.5f);
|
||||||
|
if (pendingSfxVolume < 0) pendingSfxVolume = 0;
|
||||||
|
if (pendingSfxVolume > 100) pendingSfxVolume = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
pendingResIndex = 0;
|
pendingResIndex = 0;
|
||||||
int curW = window->getWidth();
|
int curW = window->getWidth();
|
||||||
int curH = window->getHeight();
|
int curH = window->getHeight();
|
||||||
|
|
@ -1822,7 +1838,7 @@ void GameScreen::renderSettingsWindow() {
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
float screenW = io.DisplaySize.x;
|
float screenW = io.DisplaySize.x;
|
||||||
float screenH = io.DisplaySize.y;
|
float screenH = io.DisplaySize.y;
|
||||||
ImVec2 size(360.0f, 240.0f);
|
ImVec2 size(380.0f, 320.0f);
|
||||||
ImVec2 pos((screenW - size.x) * 0.5f, (screenH - size.y) * 0.5f);
|
ImVec2 pos((screenW - size.x) * 0.5f, (screenH - size.y) * 0.5f);
|
||||||
|
|
||||||
ImGui::SetNextWindowPos(pos, ImGuiCond_Always);
|
ImGui::SetNextWindowPos(pos, ImGuiCond_Always);
|
||||||
|
|
@ -1848,6 +1864,16 @@ void GameScreen::renderSettingsWindow() {
|
||||||
}
|
}
|
||||||
ImGui::Combo(resLabel, &pendingResIndex, resItems, kResCount);
|
ImGui::Combo(resLabel, &pendingResIndex, resItems, kResCount);
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
ImGui::Text("Audio");
|
||||||
|
ImGui::SliderInt("Music Volume", &pendingMusicVolume, 0, 100, "%d");
|
||||||
|
ImGui::SliderInt("SFX Volume", &pendingSfxVolume, 0, 100, "%d");
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
if (ImGui::Button("Apply", ImVec2(-1, 0))) {
|
if (ImGui::Button("Apply", ImVec2(-1, 0))) {
|
||||||
window->setVsync(pendingVsync);
|
window->setVsync(pendingVsync);
|
||||||
|
|
@ -1855,6 +1881,16 @@ void GameScreen::renderSettingsWindow() {
|
||||||
window->applyResolution(kResolutions[pendingResIndex][0], kResolutions[pendingResIndex][1]);
|
window->applyResolution(kResolutions[pendingResIndex][0], kResolutions[pendingResIndex][1]);
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
renderer->setShadowsEnabled(pendingShadows);
|
renderer->setShadowsEnabled(pendingShadows);
|
||||||
|
if (auto* music = renderer->getMusicManager()) {
|
||||||
|
music->setVolume(pendingMusicVolume);
|
||||||
|
}
|
||||||
|
float sfxScale = static_cast<float>(pendingSfxVolume) / 100.0f;
|
||||||
|
if (auto* footstep = renderer->getFootstepManager()) {
|
||||||
|
footstep->setVolumeScale(sfxScale);
|
||||||
|
}
|
||||||
|
if (auto* activity = renderer->getActivitySoundManager()) {
|
||||||
|
activity->setVolumeScale(sfxScale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue