From 6352e8e3196f78388b6c771073f9e03eaa612673 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Tue, 20 Jun 2023 14:33:09 +1000 Subject: everything everywhere all at once --- source/frontend/StarMainMixer.cpp | 114 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 source/frontend/StarMainMixer.cpp (limited to 'source/frontend/StarMainMixer.cpp') diff --git a/source/frontend/StarMainMixer.cpp b/source/frontend/StarMainMixer.cpp new file mode 100644 index 0000000..46c26cd --- /dev/null +++ b/source/frontend/StarMainMixer.cpp @@ -0,0 +1,114 @@ +#include "StarMainMixer.hpp" +#include "StarJsonExtra.hpp" +#include "StarRoot.hpp" +#include "StarConfiguration.hpp" +#include "StarUniverseClient.hpp" +#include "StarPlayer.hpp" +#include "StarAssets.hpp" +#include "StarWorldClient.hpp" + +namespace Star { + +MainMixer::MainMixer(unsigned sampleRate, unsigned channels) { + m_mixer = make_shared(sampleRate, channels); +} + +void MainMixer::setUniverseClient(UniverseClientPtr universeClient) { + m_universeClient = move(universeClient); +} + +void MainMixer::update(bool muteSfx, bool muteMusic) { + auto assets = Root::singleton().assets(); + + auto updateGroupVolume = [&](MixerGroup group, bool muted, String const& settingName) { + if (m_mutedGroups.contains(group) != muted) { + if (muted) { + m_mutedGroups.add(group); + m_mixer->setGroupVolume(group, 0, 1.0f); + } else { + m_mutedGroups.remove(group); + m_mixer->setGroupVolume(group, m_groupVolumes[group], 1.0f); + } + } else if (!m_mutedGroups.contains(group)) { + float volumeSetting = Root::singleton().configuration()->get(settingName).toFloat() / 100; + if (!m_groupVolumes.contains(group) || volumeSetting != m_groupVolumes[group]) { + m_mixer->setGroupVolume(group, volumeSetting); + m_groupVolumes[group] = volumeSetting; + } + } + }; + + updateGroupVolume(MixerGroup::Effects, muteSfx, "sfxVol"); + updateGroupVolume(MixerGroup::Music, muteMusic, "musicVol"); + updateGroupVolume(MixerGroup::Cinematic, false, "sfxVol"); + + WorldClientPtr currentWorld; + if (m_universeClient) + currentWorld = m_universeClient->worldClient(); + + if (currentWorld) { + for (auto audioInstance : currentWorld->pullPendingAudio()) { + audioInstance->setMixerGroup(MixerGroup::Effects); + m_mixer->play(audioInstance); + } + for (auto audioInstance : currentWorld->pullPendingMusic()) { + audioInstance->setMixerGroup(MixerGroup::Music); + m_mixer->play(audioInstance); + } + + if (m_universeClient && m_universeClient->mainPlayer()->underwater()) { + if (!m_mixer->hasEffect("lowpass")) + m_mixer->addEffect("lowpass", m_mixer->lowpass(32), 0.50f); + if (!m_mixer->hasEffect("echo")) + m_mixer->addEffect("echo", m_mixer->echo(0.2f, 0.6f, 0.4f), 0.50f); + } else { + if (m_mixer->hasEffect("lowpass")) + m_mixer->removeEffect("lowpass", 0.5f); + if (m_mixer->hasEffect("echo")) + m_mixer->removeEffect("echo", 0.5f); + } + + float baseMaxDistance = assets->json("/sfx.config:baseMaxDistance").toFloat(); + Vec2F stereoAdjustmentRange = jsonToVec2F(assets->json("/sfx.config:stereoAdjustmentRange")); + float attenuationGamma = assets->json("/sfx.config:attenuationGamma").toFloat(); + auto playerPos = m_universeClient->mainPlayer()->position(); + auto worldGeometry = currentWorld->geometry(); + + m_mixer->update([&](unsigned channel, Vec2F pos, float rangeMultiplier) { + Vec2F diff = worldGeometry.diff(pos, playerPos); + float diffMagnitude = diff.magnitude(); + if (diffMagnitude == 0.0f) + return 0.0f; + + Vec2F diffNorm = diff / diffMagnitude; + + float stereoIncidence = channel == 0 ? -diffNorm[0] : diffNorm[0]; + + float maxDistance = baseMaxDistance * rangeMultiplier * lerp((stereoIncidence + 1.0f) / 2.0f, stereoAdjustmentRange[0], stereoAdjustmentRange[1]); + + return pow(clamp(diffMagnitude / maxDistance, 0.0f, 1.0f), 1.0f / attenuationGamma); + }); + + } else { + if (m_mixer->hasEffect("lowpass")) + m_mixer->removeEffect("lowpass", 0); + if (m_mixer->hasEffect("echo")) + m_mixer->removeEffect("echo", 0); + + m_mixer->update(); + } +} + +MixerPtr MainMixer::mixer() const { + return m_mixer; +} + +void MainMixer::setVolume(float volume, float rampTime) { + m_mixer->setVolume(volume, rampTime); +} + +void MainMixer::read(int16_t* sampleData, size_t frameCount) { + m_mixer->read(sampleData, frameCount); +} + +} -- cgit v1.2.3