nicer volume sliders
This commit is contained in:
parent
5da4b1a4e3
commit
6b8c472978
@ -13,6 +13,26 @@
|
||||
|
||||
namespace Star {
|
||||
|
||||
float const DefaultPerceptualRangeDb = 40.f;
|
||||
float const DefaultPerceptualBoostRangeDb = 6.f;
|
||||
// https://github.com/discord/perceptual
|
||||
float perceptualToAmplitude(float perceptual, float normalizedMax, float range, float boostRange) {
|
||||
if (perceptual == 0.f) return 0.f;
|
||||
float dB = perceptual > normalizedMax
|
||||
? ((perceptual - normalizedMax) / normalizedMax) * boostRange
|
||||
: (perceptual / normalizedMax) * range - range;
|
||||
return normalizedMax * pow(10.f, dB / 20.f);
|
||||
}
|
||||
|
||||
float amplitudeToPerceptual(float amp, float normalizedMax, float range, float boostRange) {
|
||||
if (amp == 0.f) return 0.f;
|
||||
float const dB = 20.f * log10(amp / normalizedMax);
|
||||
float perceptual = dB > 0.f
|
||||
? dB / boostRange + 1
|
||||
: (range + dB) / range;
|
||||
return normalizedMax * perceptual;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct WaveData {
|
||||
ByteArrayPtr byteArray;
|
||||
|
@ -4,6 +4,15 @@
|
||||
|
||||
namespace Star {
|
||||
|
||||
extern float const DefaultPerceptualRangeDb;
|
||||
extern float const DefaultPerceptualBoostRangeDb;
|
||||
|
||||
float perceptualToAmplitude(float perceptual, float normalizedMax = 1.f,
|
||||
float range = DefaultPerceptualRangeDb, float boostRange = DefaultPerceptualBoostRangeDb);
|
||||
|
||||
float amplitudeToPerceptual(float amp, float normalizedMax = 1.f,
|
||||
float range = DefaultPerceptualRangeDb, float boostRange = DefaultPerceptualBoostRangeDb);
|
||||
|
||||
STAR_CLASS(CompressedAudioImpl);
|
||||
STAR_CLASS(UncompressedAudioImpl);
|
||||
STAR_CLASS(Audio);
|
||||
|
@ -37,6 +37,7 @@ void MainMixer::update(float dt, bool muteSfx, bool muteMusic) {
|
||||
}
|
||||
} else if (!m_mutedGroups.contains(group)) {
|
||||
float volumeSetting = Root::singleton().configuration()->get(settingName).toFloat() / 100.0f;
|
||||
volumeSetting = perceptualToAmplitude(volumeSetting);
|
||||
if (!m_groupVolumes.contains(group) || volumeSetting != m_groupVolumes[group]) {
|
||||
m_mixer->setGroupVolume(group, volumeSetting);
|
||||
m_groupVolumes[group] = volumeSetting;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "StarRoot.hpp"
|
||||
#include "StarLogging.hpp"
|
||||
#include "StarInterpolation.hpp"
|
||||
#include "StarAudio.hpp"
|
||||
#include "opus/opus.h"
|
||||
|
||||
#include "SDL2/SDL.h"
|
||||
@ -196,9 +197,11 @@ void Voice::loadJson(Json const& config, bool skipSave) {
|
||||
&& change(m_deviceName, config.optString("deviceName"), changed))
|
||||
resetDevice();
|
||||
|
||||
m_threshold = config.getFloat("threshold", m_threshold);
|
||||
m_inputVolume = config.getFloat("inputVolume", m_inputVolume);
|
||||
m_outputVolume = config.getFloat("outputVolume", m_outputVolume);
|
||||
m_threshold = config.getFloat("threshold", m_threshold);
|
||||
m_inputAmplitude = perceptualToAmplitude(
|
||||
m_inputVolume = config.getFloat("inputVolume", m_inputVolume));
|
||||
m_outputAmplitude = perceptualToAmplitude(
|
||||
m_outputVolume = config.getFloat("outputVolume", m_outputVolume));
|
||||
|
||||
if (change(m_loopback, config.getBool("loopback", m_loopback), changed))
|
||||
m_clientSpeaker->playing = false;
|
||||
@ -321,7 +324,7 @@ void Voice::readAudioData(uint8_t* stream, int len) {
|
||||
}
|
||||
}
|
||||
|
||||
m_clientSpeaker->decibelLevel = getAudioLoudness((int16_t*)stream, sampleCount, m_inputVolume);
|
||||
m_clientSpeaker->decibelLevel = getAudioLoudness((int16_t*)stream, sampleCount, m_inputAmplitude);
|
||||
|
||||
if (!m_loopback) {
|
||||
if (active && !m_clientSpeaker->playing)
|
||||
@ -411,7 +414,7 @@ void Voice::mix(int16_t* buffer, size_t frameCount, unsigned channels) {
|
||||
if (mix) {
|
||||
finalBuffer.resize(sharedBuffer.size(), 0);
|
||||
|
||||
float vol = m_outputVolume;
|
||||
float vol = m_outputAmplitude;
|
||||
for (size_t i = 0; i != sharedBuffer.size(); ++i)
|
||||
finalBuffer[i] = (int16_t)clamp<int>(sharedBuffer[i] * vol, INT16_MIN, INT16_MAX);
|
||||
|
||||
@ -678,9 +681,9 @@ void Voice::thread() {
|
||||
}
|
||||
m_capturedChunksFrames -= VOICE_FRAME_SIZE;
|
||||
|
||||
if (m_inputVolume != 1.0f) {
|
||||
if (m_inputAmplitude != 1.0f) {
|
||||
for (size_t i = 0; i != samples.size(); ++i)
|
||||
samples[i] *= m_inputVolume;
|
||||
samples[i] *= m_inputAmplitude;
|
||||
}
|
||||
|
||||
if (int encodedSize = opus_encode(m_encoder.get(), samples.data(), VOICE_FRAME_SIZE, (unsigned char*)encoded.ptr(), encoded.size())) {
|
||||
|
@ -173,9 +173,13 @@ private:
|
||||
|
||||
|
||||
OpusEncoderPtr m_encoder;
|
||||
|
||||
|
||||
float m_outputVolume = 1.0f;
|
||||
float m_inputVolume = 1.0f;
|
||||
|
||||
float m_outputAmplitude = 1.0f;
|
||||
float m_inputAmplitude = 1.0f;
|
||||
|
||||
float m_threshold = -50.0f;
|
||||
|
||||
int64_t m_lastSentTime = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user