nicer volume sliders
This commit is contained in:
parent
5da4b1a4e3
commit
6b8c472978
@ -13,6 +13,26 @@
|
|||||||
|
|
||||||
namespace Star {
|
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 {
|
namespace {
|
||||||
struct WaveData {
|
struct WaveData {
|
||||||
ByteArrayPtr byteArray;
|
ByteArrayPtr byteArray;
|
||||||
|
@ -4,6 +4,15 @@
|
|||||||
|
|
||||||
namespace Star {
|
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(CompressedAudioImpl);
|
||||||
STAR_CLASS(UncompressedAudioImpl);
|
STAR_CLASS(UncompressedAudioImpl);
|
||||||
STAR_CLASS(Audio);
|
STAR_CLASS(Audio);
|
||||||
|
@ -37,6 +37,7 @@ void MainMixer::update(float dt, bool muteSfx, bool muteMusic) {
|
|||||||
}
|
}
|
||||||
} else if (!m_mutedGroups.contains(group)) {
|
} else if (!m_mutedGroups.contains(group)) {
|
||||||
float volumeSetting = Root::singleton().configuration()->get(settingName).toFloat() / 100.0f;
|
float volumeSetting = Root::singleton().configuration()->get(settingName).toFloat() / 100.0f;
|
||||||
|
volumeSetting = perceptualToAmplitude(volumeSetting);
|
||||||
if (!m_groupVolumes.contains(group) || volumeSetting != m_groupVolumes[group]) {
|
if (!m_groupVolumes.contains(group) || volumeSetting != m_groupVolumes[group]) {
|
||||||
m_mixer->setGroupVolume(group, volumeSetting);
|
m_mixer->setGroupVolume(group, volumeSetting);
|
||||||
m_groupVolumes[group] = volumeSetting;
|
m_groupVolumes[group] = volumeSetting;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "StarRoot.hpp"
|
#include "StarRoot.hpp"
|
||||||
#include "StarLogging.hpp"
|
#include "StarLogging.hpp"
|
||||||
#include "StarInterpolation.hpp"
|
#include "StarInterpolation.hpp"
|
||||||
|
#include "StarAudio.hpp"
|
||||||
#include "opus/opus.h"
|
#include "opus/opus.h"
|
||||||
|
|
||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
@ -196,9 +197,11 @@ void Voice::loadJson(Json const& config, bool skipSave) {
|
|||||||
&& change(m_deviceName, config.optString("deviceName"), changed))
|
&& change(m_deviceName, config.optString("deviceName"), changed))
|
||||||
resetDevice();
|
resetDevice();
|
||||||
|
|
||||||
m_threshold = config.getFloat("threshold", m_threshold);
|
m_threshold = config.getFloat("threshold", m_threshold);
|
||||||
m_inputVolume = config.getFloat("inputVolume", m_inputVolume);
|
m_inputAmplitude = perceptualToAmplitude(
|
||||||
m_outputVolume = config.getFloat("outputVolume", m_outputVolume);
|
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))
|
if (change(m_loopback, config.getBool("loopback", m_loopback), changed))
|
||||||
m_clientSpeaker->playing = false;
|
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 (!m_loopback) {
|
||||||
if (active && !m_clientSpeaker->playing)
|
if (active && !m_clientSpeaker->playing)
|
||||||
@ -411,7 +414,7 @@ void Voice::mix(int16_t* buffer, size_t frameCount, unsigned channels) {
|
|||||||
if (mix) {
|
if (mix) {
|
||||||
finalBuffer.resize(sharedBuffer.size(), 0);
|
finalBuffer.resize(sharedBuffer.size(), 0);
|
||||||
|
|
||||||
float vol = m_outputVolume;
|
float vol = m_outputAmplitude;
|
||||||
for (size_t i = 0; i != sharedBuffer.size(); ++i)
|
for (size_t i = 0; i != sharedBuffer.size(); ++i)
|
||||||
finalBuffer[i] = (int16_t)clamp<int>(sharedBuffer[i] * vol, INT16_MIN, INT16_MAX);
|
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;
|
m_capturedChunksFrames -= VOICE_FRAME_SIZE;
|
||||||
|
|
||||||
if (m_inputVolume != 1.0f) {
|
if (m_inputAmplitude != 1.0f) {
|
||||||
for (size_t i = 0; i != samples.size(); ++i)
|
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())) {
|
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;
|
OpusEncoderPtr m_encoder;
|
||||||
|
|
||||||
float m_outputVolume = 1.0f;
|
float m_outputVolume = 1.0f;
|
||||||
float m_inputVolume = 1.0f;
|
float m_inputVolume = 1.0f;
|
||||||
|
|
||||||
|
float m_outputAmplitude = 1.0f;
|
||||||
|
float m_inputAmplitude = 1.0f;
|
||||||
|
|
||||||
float m_threshold = -50.0f;
|
float m_threshold = -50.0f;
|
||||||
|
|
||||||
int64_t m_lastSentTime = 0;
|
int64_t m_lastSentTime = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user