From 669b5fbced14434f8c08a20273fa1ea9787a8fc9 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 22 Apr 2026 04:45:48 +0200 Subject: [PATCH] fix(sim): simulator volume (#7302) --- .../src/simulation/wasmsimulatorinterface.cpp | 21 +++++++++++++++---- .../src/simulation/wasmsimulatorinterface.h | 2 +- radio/src/targets/simu/audio_driver.cpp | 12 +++++++++++ radio/src/targets/simu/simuaudio.cpp | 7 +------ 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/companion/src/simulation/wasmsimulatorinterface.cpp b/companion/src/simulation/wasmsimulatorinterface.cpp index 8e6f4309b..97657d665 100644 --- a/companion/src/simulation/wasmsimulatorinterface.cpp +++ b/companion/src/simulation/wasmsimulatorinterface.cpp @@ -532,7 +532,8 @@ void WasmSimulatorInterface::setSdPath(const QString & sdPath, void WasmSimulatorInterface::setVolumeGain(const int value) { - m_volumeGain = qBound(0, value * SDL_MIX_MAXVOLUME / 100, SDL_MIX_MAXVOLUME); + // Stored as user-facing gain (0.5x..3.0x) multiplied by 10. + m_volumeGain = value; } void WasmSimulatorInterface::setAnalogValue(uint8_t index, int16_t value) @@ -834,10 +835,22 @@ void WasmSimulatorInterface::queueAudio(const uint8_t * buf, uint32_t len) if (m_audioDevice == 0 || len == 0) return; - // Apply companion volume gain (m_volumeGain is 0..SDL_MIX_MAXVOLUME) + // Apply companion volume gain (m_volumeGain = user gain * 10). + // SDL_MixAudioFormat cannot amplify above unity, so scale manually + // with saturation to support the UI's 0.5..3.0x range. + if (m_volumeGain == 10) { + SDL_QueueAudio(m_audioDevice, buf, len); + return; + } + QByteArray scaled(len, 0); - SDL_MixAudioFormat((uint8_t *)scaled.data(), buf, AUDIO_S16SYS, len, - m_volumeGain); + auto * src = reinterpret_cast(buf); + auto * dst = reinterpret_cast(scaled.data()); + uint32_t n = len / sizeof(int16_t); + for (uint32_t i = 0; i < n; ++i) { + int32_t s = ((int32_t)src[i] * m_volumeGain) / 10; + dst[i] = (int16_t)qBound(INT16_MIN, s, INT16_MAX); + } SDL_QueueAudio(m_audioDevice, scaled.constData(), len); } diff --git a/companion/src/simulation/wasmsimulatorinterface.h b/companion/src/simulation/wasmsimulatorinterface.h index c45ea9b7f..dd9670ffe 100644 --- a/companion/src/simulation/wasmsimulatorinterface.h +++ b/companion/src/simulation/wasmsimulatorinterface.h @@ -112,7 +112,7 @@ class WasmSimulatorInterface : public SimulatorInterface // Audio SDL_AudioDeviceID m_audioDevice = 0; - int m_volumeGain = SDL_MIX_MAXVOLUME; + int m_volumeGain = 10; // unity gain (user gain * 10) // Host-side analog values (polled by WASM via simuGetAnalog) static constexpr int MAX_ANALOGS = 32; diff --git a/radio/src/targets/simu/audio_driver.cpp b/radio/src/targets/simu/audio_driver.cpp index 58d901d55..c7f487966 100644 --- a/radio/src/targets/simu/audio_driver.cpp +++ b/radio/src/targets/simu/audio_driver.cpp @@ -58,6 +58,18 @@ void audioConsumeCurrentBuffer() auto nextBuffer = fifo.getNextFilledBuffer(); if (!nextBuffer) return; +#if !defined(SOFTWARE_VOLUME) + // Simulate the hardware volume chip: scale samples in place. + int volume = simuAudioGetVolume(); + if (volume < VOLUME_LEVEL_MAX) { + auto* buf = const_cast(nextBuffer); + for (uint16_t i = 0; i < buf->size; ++i) { + buf->data[i] = (audio_data_t)( + ((int32_t)buf->data[i] * volume) / VOLUME_LEVEL_MAX); + } + } +#endif + auto data = (const uint8_t*)nextBuffer->data; uint32_t len = nextBuffer->size * sizeof(audio_data_t); simuQueueAudio(data, len); diff --git a/radio/src/targets/simu/simuaudio.cpp b/radio/src/targets/simu/simuaudio.cpp index 6e4c84e93..42b328fda 100644 --- a/radio/src/targets/simu/simuaudio.cpp +++ b/radio/src/targets/simu/simuaudio.cpp @@ -19,7 +19,7 @@ * GNU General Public License for more details. */ -#include "audio.h" +#include "hal/audio_driver.h" #include "simuaudio.h" #include "simulib.h" @@ -32,11 +32,6 @@ static SDL_AudioDeviceID _sdl_audio_device = 0; void simuQueueAudio(const uint8_t* data, uint32_t len) { -#if !defined(SOFTWARE_VOLUME) - int volume = (simuAudioGetVolume() * SDL_MIX_MAXVOLUME ) / VOLUME_LEVEL_MAX; - SDL_MixAudioFormat((uint8_t*)data, data, AUDIO_FMT, len, volume); -#endif - SDL_QueueAudio(_sdl_audio_device, data, len); }