Phase 4 volume
This commit is contained in:
parent
f78a63ab75
commit
9e52a4200b
6 changed files with 182 additions and 9 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include "renderers/sdl.h"
|
||||
|
||||
#include <Limelight.h>
|
||||
#include <cmath>
|
||||
|
||||
#define TRY_INIT_RENDERER(renderer, opusConfig) \
|
||||
{ \
|
||||
|
|
@ -183,7 +184,7 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength)
|
|||
s_ActiveSession->m_AudioSampleCount++;
|
||||
|
||||
// If audio is muted, don't decode or play the audio
|
||||
if (s_ActiveSession->m_AudioMuted) {
|
||||
if (s_ActiveSession->m_AudioMuted.load(std::memory_order_relaxed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +218,27 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength)
|
|||
if (samplesDecoded > 0) {
|
||||
SDL_assert(desiredBufferSize >= frameSize * samplesDecoded);
|
||||
desiredBufferSize = frameSize * samplesDecoded;
|
||||
|
||||
const float volume = s_ActiveSession->getAudioVolumeScalar();
|
||||
if (volume <= 0.0f) {
|
||||
SDL_memset(buffer, 0, desiredBufferSize);
|
||||
}
|
||||
else if (volume < 1.0f) {
|
||||
const int totalSamples = samplesDecoded * s_ActiveSession->m_ActiveAudioConfig.channelCount;
|
||||
if (s_ActiveSession->m_AudioRenderer->getAudioBufferFormat() == IAudioRenderer::AudioFormat::Float32NE) {
|
||||
float* output = (float*)buffer;
|
||||
for (int i = 0; i < totalSamples; i++) {
|
||||
output[i] = SDL_clamp(output[i] * volume, -1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
short* output = (short*)buffer;
|
||||
for (int i = 0; i < totalSamples; i++) {
|
||||
const int scaled = (int) std::lround((float)output[i] * volume);
|
||||
output[i] = (short)SDL_clamp(scaled, -32768, 32767);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
desiredBufferSize = 0;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,21 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i
|
|||
m_SpecialKeyCombos[KeyComboToggleGamepadInput].scanCode = SDL_SCANCODE_G;
|
||||
m_SpecialKeyCombos[KeyComboToggleGamepadInput].enabled = true;
|
||||
|
||||
m_SpecialKeyCombos[KeyComboVolumeUp].keyCombo = KeyComboVolumeUp;
|
||||
m_SpecialKeyCombos[KeyComboVolumeUp].keyCode = SDLK_u;
|
||||
m_SpecialKeyCombos[KeyComboVolumeUp].scanCode = SDL_SCANCODE_U;
|
||||
m_SpecialKeyCombos[KeyComboVolumeUp].enabled = true;
|
||||
|
||||
m_SpecialKeyCombos[KeyComboVolumeDown].keyCombo = KeyComboVolumeDown;
|
||||
m_SpecialKeyCombos[KeyComboVolumeDown].keyCode = SDLK_j;
|
||||
m_SpecialKeyCombos[KeyComboVolumeDown].scanCode = SDL_SCANCODE_J;
|
||||
m_SpecialKeyCombos[KeyComboVolumeDown].enabled = true;
|
||||
|
||||
m_SpecialKeyCombos[KeyComboToggleMute].keyCombo = KeyComboToggleMute;
|
||||
m_SpecialKeyCombos[KeyComboToggleMute].keyCode = SDLK_n;
|
||||
m_SpecialKeyCombos[KeyComboToggleMute].scanCode = SDL_SCANCODE_N;
|
||||
m_SpecialKeyCombos[KeyComboToggleMute].enabled = true;
|
||||
|
||||
m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCombo = KeyComboTogglePointerRegionLock;
|
||||
m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].keyCode = SDLK_l;
|
||||
m_SpecialKeyCombos[KeyComboTogglePointerRegionLock].scanCode = SDL_SCANCODE_L;
|
||||
|
|
|
|||
|
|
@ -167,6 +167,9 @@ private:
|
|||
KeyComboPasteText,
|
||||
KeyComboToggleKeyboardMouseInput,
|
||||
KeyComboToggleGamepadInput,
|
||||
KeyComboVolumeUp,
|
||||
KeyComboVolumeDown,
|
||||
KeyComboToggleMute,
|
||||
KeyComboTogglePointerRegionLock,
|
||||
KeyComboQuitAndExit,
|
||||
KeyComboMax
|
||||
|
|
|
|||
|
|
@ -150,6 +150,30 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo)
|
|||
}
|
||||
break;
|
||||
|
||||
case KeyComboVolumeUp:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Detected volume up combo");
|
||||
if (auto session = Session::get(); session != nullptr) {
|
||||
session->adjustAudioVolume(0.05f);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyComboVolumeDown:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Detected volume down combo");
|
||||
if (auto session = Session::get(); session != nullptr) {
|
||||
session->adjustAudioVolume(-0.05f);
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyComboToggleMute:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Detected audio mute toggle combo");
|
||||
if (auto session = Session::get(); session != nullptr) {
|
||||
session->toggleAudioMute();
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyComboTogglePointerRegionLock:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Detected pointer region lock toggle combo");
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE 103
|
||||
#define SDL_CODE_GAMECONTROLLER_SET_CONTROLLER_LED 104
|
||||
#define SDL_CODE_GAMECONTROLLER_SET_ADAPTIVE_TRIGGERS 105
|
||||
#define SDL_CODE_HIDE_STATUS_OVERLAY 106
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
|
@ -187,12 +188,14 @@ void Session::clConnectionStatusUpdate(int connectionStatus)
|
|||
switch (connectionStatus)
|
||||
{
|
||||
case CONN_STATUS_POOR:
|
||||
s_ActiveSession->m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed);
|
||||
s_ActiveSession->m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate,
|
||||
s_ActiveSession->m_StreamConfig.bitrate > 5000 ?
|
||||
"Slow connection to PC\nReduce your bitrate" : "Poor connection to PC");
|
||||
s_ActiveSession->m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true);
|
||||
break;
|
||||
case CONN_STATUS_OKAY:
|
||||
s_ActiveSession->m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed);
|
||||
s_ActiveSession->m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, false);
|
||||
break;
|
||||
}
|
||||
|
|
@ -556,8 +559,11 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere
|
|||
m_VideoDecoder(nullptr),
|
||||
m_DecoderLock(SDL_CreateMutex()),
|
||||
m_AudioMuted(false),
|
||||
m_ManualAudioMuted(false),
|
||||
m_AudioVolumeScalar(1.0f),
|
||||
m_AllowGamepadInput(true),
|
||||
m_AllowKeyboardMouseInput(true),
|
||||
m_StatusOverlayGeneration(0),
|
||||
m_QtWindow(nullptr),
|
||||
m_UnexpectedTermination(true), // Failure prior to streaming is unexpected
|
||||
m_InputHandler(nullptr),
|
||||
|
|
@ -579,6 +585,43 @@ void Session::setGamepadInputAllowed(bool allowed)
|
|||
notifyInputPermissionState();
|
||||
}
|
||||
|
||||
void Session::setAudioVolumeScalar(float scalar)
|
||||
{
|
||||
scalar = SDL_clamp(scalar, 0.0f, 1.0f);
|
||||
m_AudioVolumeScalar.store(scalar, std::memory_order_relaxed);
|
||||
notifyAudioVolumeState();
|
||||
}
|
||||
|
||||
void Session::adjustAudioVolume(float delta)
|
||||
{
|
||||
const float current = getAudioVolumeScalar();
|
||||
const float next = SDL_clamp(current + delta, 0.0f, 1.0f);
|
||||
setAudioVolumeScalar(next);
|
||||
}
|
||||
|
||||
void Session::toggleAudioMute()
|
||||
{
|
||||
const bool muted = !m_ManualAudioMuted.load(std::memory_order_relaxed);
|
||||
m_ManualAudioMuted.store(muted, std::memory_order_relaxed);
|
||||
|
||||
updateEffectiveAudioMuteState();
|
||||
notifyAudioVolumeState();
|
||||
}
|
||||
|
||||
void Session::notifyAudioVolumeState()
|
||||
{
|
||||
char buffer[64];
|
||||
if (m_ManualAudioMuted.load(std::memory_order_relaxed)) {
|
||||
SDL_snprintf(buffer, sizeof(buffer), "Volume: MUTED");
|
||||
}
|
||||
else {
|
||||
const int percent = (int)SDL_roundf(getAudioVolumeScalar() * 100.0f);
|
||||
SDL_snprintf(buffer, sizeof(buffer), "Volume: %d%%", percent);
|
||||
}
|
||||
|
||||
showTemporaryStatusOverlay(buffer);
|
||||
}
|
||||
|
||||
void Session::setKeyboardMouseInputAllowed(bool allowed)
|
||||
{
|
||||
bool previous = m_AllowKeyboardMouseInput.exchange(allowed, std::memory_order_relaxed);
|
||||
|
|
@ -608,8 +651,41 @@ void Session::notifyInputPermissionState()
|
|||
isKeyboardMouseInputAllowed() ? "ON" : "OFF",
|
||||
isGamepadInputAllowed() ? "ON" : "OFF");
|
||||
|
||||
m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, buffer);
|
||||
showTemporaryStatusOverlay(buffer);
|
||||
}
|
||||
|
||||
Uint32 Session::statusOverlayTimeoutCallback(Uint32, void* param)
|
||||
{
|
||||
SDL_Event event = {};
|
||||
event.type = SDL_USEREVENT;
|
||||
event.user.code = SDL_CODE_HIDE_STATUS_OVERLAY;
|
||||
event.user.data1 = param;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Session::showTemporaryStatusOverlay(const char* text, Uint32 timeoutMs)
|
||||
{
|
||||
if (m_MouseEmulationRefCount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, text);
|
||||
m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true);
|
||||
|
||||
const uint32_t generation = m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed) + 1;
|
||||
SDL_AddTimer(timeoutMs, statusOverlayTimeoutCallback, (void*)(uintptr_t)generation);
|
||||
}
|
||||
|
||||
void Session::updateEffectiveAudioMuteState()
|
||||
{
|
||||
bool muted = m_ManualAudioMuted.load(std::memory_order_relaxed);
|
||||
if (!muted && m_Preferences->muteOnFocusLoss && m_Window != nullptr) {
|
||||
muted = SDL_GetKeyboardFocus() != m_Window;
|
||||
}
|
||||
|
||||
m_AudioMuted.store(muted, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
Session::~Session()
|
||||
|
|
@ -1584,10 +1660,12 @@ void Session::notifyMouseEmulationMode(bool enabled)
|
|||
|
||||
// We re-use the status update overlay for mouse mode notification
|
||||
if (m_MouseEmulationRefCount > 0) {
|
||||
m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed);
|
||||
m_OverlayManager.updateOverlayText(Overlay::OverlayStatusUpdate, "Gamepad mouse mode active\nLong press Start to deactivate");
|
||||
m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, true);
|
||||
}
|
||||
else {
|
||||
m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed);
|
||||
m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1788,6 +1866,13 @@ void Session::start()
|
|||
// We're now active
|
||||
s_ActiveSession = this;
|
||||
|
||||
m_AllowGamepadInput.store(true, std::memory_order_relaxed);
|
||||
m_AllowKeyboardMouseInput.store(true, std::memory_order_relaxed);
|
||||
m_ManualAudioMuted.store(false, std::memory_order_relaxed);
|
||||
m_AudioMuted.store(false, std::memory_order_relaxed);
|
||||
m_AudioVolumeScalar.store(1.0f, std::memory_order_relaxed);
|
||||
m_StatusOverlayGeneration.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
// Initialize the gamepad code with our preferences
|
||||
// NB: m_InputHandler must be initialize before starting the connection.
|
||||
m_InputHandler = new SdlInputHandler(*m_Preferences, m_StreamConfig.width, m_StreamConfig.height);
|
||||
|
|
@ -2009,6 +2094,7 @@ void Session::exec()
|
|||
// issues that could cause indefinite timeouts, delayed joystick detection,
|
||||
// and other problems.
|
||||
if (!SDL_WaitEventTimeout(&event, 1000)) {
|
||||
updateEffectiveAudioMuteState();
|
||||
presence.runCallbacks();
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2025,10 +2111,14 @@ void Session::exec()
|
|||
// ARM core in the Steam Link, so we will wait 10 ms instead.
|
||||
SDL_Delay(10);
|
||||
#endif
|
||||
updateEffectiveAudioMuteState();
|
||||
presence.runCallbacks();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
updateEffectiveAudioMuteState();
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
|
|
@ -2070,6 +2160,12 @@ void Session::exec()
|
|||
m_InputHandler->setAdaptiveTriggers((uint16_t)(uintptr_t)event.user.data1,
|
||||
(DualSenseOutputReport *)event.user.data2);
|
||||
break;
|
||||
case SDL_CODE_HIDE_STATUS_OVERLAY:
|
||||
if ((uint32_t)(uintptr_t)event.user.data1 == m_StatusOverlayGeneration.load(std::memory_order_relaxed) &&
|
||||
m_MouseEmulationRefCount == 0) {
|
||||
m_OverlayManager.setOverlayState(Overlay::OverlayStatusUpdate, false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SDL_assert(false);
|
||||
}
|
||||
|
|
@ -2079,15 +2175,9 @@ void Session::exec()
|
|||
// Early handling of some events
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
if (m_Preferences->muteOnFocusLoss) {
|
||||
m_AudioMuted = true;
|
||||
}
|
||||
m_InputHandler->notifyFocusLost();
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
if (m_Preferences->muteOnFocusLoss) {
|
||||
m_AudioMuted = false;
|
||||
}
|
||||
m_InputHandler->notifyFocusGained();
|
||||
break;
|
||||
case SDL_WINDOWEVENT_LEAVE:
|
||||
|
|
|
|||
|
|
@ -142,6 +142,16 @@ public:
|
|||
void toggleKeyboardMouseInputAllowed();
|
||||
void notifyInputPermissionState();
|
||||
|
||||
float getAudioVolumeScalar() const
|
||||
{
|
||||
return m_AudioVolumeScalar.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void setAudioVolumeScalar(float scalar);
|
||||
void adjustAudioVolume(float delta);
|
||||
void toggleAudioMute();
|
||||
void notifyAudioVolumeState();
|
||||
|
||||
signals:
|
||||
void stageStarting(QString stage);
|
||||
|
||||
|
|
@ -259,6 +269,12 @@ private:
|
|||
static
|
||||
int drSubmitDecodeUnit(PDECODE_UNIT du);
|
||||
|
||||
static
|
||||
Uint32 statusOverlayTimeoutCallback(Uint32 interval, void* param);
|
||||
|
||||
void showTemporaryStatusOverlay(const char* text, Uint32 timeoutMs = 1500);
|
||||
void updateEffectiveAudioMuteState();
|
||||
|
||||
StreamingPreferences* m_Preferences;
|
||||
bool m_IsFullScreen;
|
||||
SupportedVideoFormatList m_SupportedVideoFormats; // Sorted in order of descending priority
|
||||
|
|
@ -271,9 +287,12 @@ private:
|
|||
IVideoDecoder* m_VideoDecoder;
|
||||
SDL_mutex* m_DecoderLock;
|
||||
bool m_AudioDisabled;
|
||||
bool m_AudioMuted;
|
||||
std::atomic<bool> m_AudioMuted;
|
||||
std::atomic<bool> m_ManualAudioMuted;
|
||||
std::atomic<float> m_AudioVolumeScalar;
|
||||
std::atomic<bool> m_AllowGamepadInput;
|
||||
std::atomic<bool> m_AllowKeyboardMouseInput;
|
||||
std::atomic<uint32_t> m_StatusOverlayGeneration;
|
||||
Uint32 m_FullScreenFlag;
|
||||
QQuickWindow* m_QtWindow;
|
||||
bool m_UnexpectedTermination;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue