From ee27e71c6982de4babf904c52a47761c0f4b1d5c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Nov 2025 17:48:46 +0200 Subject: [PATCH] Mixer: use Peak dB instead of RMS dB --- src/framework/audio/common/audiotypes.h | 10 ++--- src/framework/audio/common/rpc/rpcpacker.h | 4 +- src/framework/audio/engine/internal/mixer.cpp | 37 ++++++++--------- src/framework/audio/engine/internal/mixer.h | 3 -- .../audio/engine/internal/mixerchannel.cpp | 41 ++++++++----------- .../audio/engine/internal/mixerchannel.h | 3 -- src/framework/audio/tests/rpcpacker_tests.cpp | 2 - 7 files changed, 39 insertions(+), 61 deletions(-) diff --git a/src/framework/audio/common/audiotypes.h b/src/framework/audio/common/audiotypes.h index 5999dfef05bd9..bdc3018645a35 100644 --- a/src/framework/audio/common/audiotypes.h +++ b/src/framework/audio/common/audiotypes.h @@ -360,13 +360,11 @@ struct AudioParams { }; struct AudioSignalVal { - float amplitude = 0.f; volume_dbfs_t pressure = 0.f; inline bool operator ==(const AudioSignalVal& other) const { - return muse::is_equal(amplitude, other.amplitude) - && pressure == other.pressure; + return pressure == other.pressure; } }; @@ -375,9 +373,9 @@ using AudioSignalChanges = async::Channel; static constexpr volume_dbfs_t MINIMUM_OPERABLE_DBFS_LEVEL = volume_dbfs_t::make(-100.f); struct AudioSignalsNotifier { - void updateSignalValues(const audioch_t audioChNumber, const float newAmplitude) + void updateSignalValues(const audioch_t audioChNumber, const float newPeak) { - volume_dbfs_t newPressure = (newAmplitude > 0.f) ? volume_dbfs_t(muse::linear_to_db(newAmplitude)) : MINIMUM_OPERABLE_DBFS_LEVEL; + volume_dbfs_t newPressure = (newPeak > 0.f) ? volume_dbfs_t(muse::linear_to_db(newPeak)) : MINIMUM_OPERABLE_DBFS_LEVEL; newPressure = std::max(newPressure, MINIMUM_OPERABLE_DBFS_LEVEL); AudioSignalVal& signalVal = m_signalValuesMap[audioChNumber]; @@ -390,9 +388,7 @@ struct AudioSignalsNotifier { return; } - signalVal.amplitude = newAmplitude; signalVal.pressure = newPressure; - m_needNotifyAboutChanges = true; } diff --git a/src/framework/audio/common/rpc/rpcpacker.h b/src/framework/audio/common/rpc/rpcpacker.h index 99f09b7db2462..6e8e8f30e1741 100644 --- a/src/framework/audio/common/rpc/rpcpacker.h +++ b/src/framework/audio/common/rpc/rpcpacker.h @@ -271,12 +271,12 @@ inline void unpack_custom(muse::msgpack::UnPacker& p, muse::audio::SoundTrackFor inline void pack_custom(muse::msgpack::Packer& p, const muse::audio::AudioSignalVal& value) { - p.process(value.amplitude, value.pressure); + p.process(value.pressure); } inline void unpack_custom(muse::msgpack::UnPacker& p, muse::audio::AudioSignalVal& value) { - p.process(value.amplitude, value.pressure); + p.process(value.pressure); } inline void pack_custom(muse::msgpack::Packer& p, const muse::audio::InputProcessingProgress::ChunkInfo& value) diff --git a/src/framework/audio/engine/internal/mixer.cpp b/src/framework/audio/engine/internal/mixer.cpp index fac4522519984..6f3cc2807675e 100644 --- a/src/framework/audio/engine/internal/mixer.cpp +++ b/src/framework/audio/engine/internal/mixer.cpp @@ -182,8 +182,6 @@ void Mixer::setOutputSpec(const OutputSpec& spec) m_outputSpec = spec; - m_limiter = std::make_unique(spec.sampleRate); - AbstractAudioSource::setOutputSpec(spec); for (auto& channel : m_trackChannels) { @@ -557,37 +555,34 @@ void Mixer::completeOutput(float* buffer, samples_t samplesPerChannel) return; } - float totalSquaredSum = 0.f; - float volume = muse::db_to_linear(m_masterParams.volume); + const float volume = muse::db_to_linear(m_masterParams.volume); + float globalPeak = 0.f; for (audioch_t audioChNum = 0; audioChNum < m_outputSpec.audioChannelCount; ++audioChNum) { - float singleChannelSquaredSum = 0.f; - gain_t totalGain = dsp::balanceGain(m_masterParams.balance, audioChNum) * volume; + const gain_t totalGain = dsp::balanceGain(m_masterParams.balance, audioChNum) * volume; + float peak = 0.f; for (samples_t s = 0; s < samplesPerChannel; ++s) { - int idx = s * m_outputSpec.audioChannelCount + audioChNum; + const size_t idx = s * m_outputSpec.audioChannelCount + audioChNum; + const float resultSample = buffer[idx] * totalGain; + const float absSample = std::fabs(resultSample); - float resultSample = buffer[idx] * totalGain; buffer[idx] = resultSample; - float squaredSample = resultSample * resultSample; - totalSquaredSum += squaredSample; - singleChannelSquaredSum += squaredSample; + if (absSample > peak) { + peak = absSample; + } } - float rms = dsp::samplesRootMeanSquare(singleChannelSquaredSum, samplesPerChannel); - m_audioSignalNotifier.updateSignalValues(audioChNum, rms); - } - - m_isSilence = RealIsNull(totalSquaredSum); - m_audioSignalNotifier.notifyAboutChanges(); + m_audioSignalNotifier.updateSignalValues(audioChNum, peak); - if (!m_limiter->isActive()) { - return; + if (peak > globalPeak) { + globalPeak = peak; + } } - float totalRms = dsp::samplesRootMeanSquare(totalSquaredSum, samplesPerChannel * m_outputSpec.audioChannelCount); - m_limiter->process(totalRms, buffer, m_outputSpec.audioChannelCount, samplesPerChannel); + m_isSilence = RealIsNull(globalPeak); + m_audioSignalNotifier.notifyAboutChanges(); } void Mixer::notifyNoAudioSignal() diff --git a/src/framework/audio/engine/internal/mixer.h b/src/framework/audio/engine/internal/mixer.h index a36ae872bf24f..f486f945033d6 100644 --- a/src/framework/audio/engine/internal/mixer.h +++ b/src/framework/audio/engine/internal/mixer.h @@ -34,7 +34,6 @@ #include "../iclock.h" #include "../ifxresolver.h" -#include "dsp/limiter.h" #include "mixerchannel.h" namespace muse { @@ -113,8 +112,6 @@ class Mixer : public AbstractAudioSource, public Injectable, public async::Async std::vector m_auxChannelInfoList; - dsp::LimiterPtr m_limiter = nullptr; - std::set m_clocks; mutable AudioSignalsNotifier m_audioSignalNotifier; diff --git a/src/framework/audio/engine/internal/mixerchannel.cpp b/src/framework/audio/engine/internal/mixerchannel.cpp index 43a35fab0400a..9b5d29d60c6be 100644 --- a/src/framework/audio/engine/internal/mixerchannel.cpp +++ b/src/framework/audio/engine/internal/mixerchannel.cpp @@ -38,8 +38,7 @@ MixerChannel::MixerChannel(const TrackId trackId, IAudioSourcePtr source, const const modularity::ContextPtr& iocCtx) : Injectable(iocCtx), m_trackId(trackId), m_outputSpec(outputSpec), - m_audioSource(std::move(source)), - m_compressor(std::make_unique(outputSpec.sampleRate)) + m_audioSource(std::move(source)) { ONLY_AUDIO_ENGINE_THREAD; } @@ -219,39 +218,35 @@ samples_t MixerChannel::process(float* buffer, samples_t samplesPerChannel) void MixerChannel::completeOutput(float* buffer, unsigned int samplesCount) { - unsigned int channelsCount = audioChannelsCount(); - float volume = muse::db_to_linear(m_params.volume); - float totalSquaredSum = 0.f; + const unsigned int channelsCount = audioChannelsCount(); + const float volume = muse::db_to_linear(m_params.volume); + float globalPeak = 0.f; for (audioch_t audioChNum = 0; audioChNum < channelsCount; ++audioChNum) { - float singleChannelSquaredSum = 0.f; - - gain_t totalGain = dsp::balanceGain(m_params.balance, audioChNum) * volume; + const gain_t totalGain = dsp::balanceGain(m_params.balance, audioChNum) * volume; + float peak = 0.f; for (unsigned int s = 0; s < samplesCount; ++s) { - int idx = s * channelsCount + audioChNum; + const unsigned int idx = s * channelsCount + audioChNum; + const float resultSample = buffer[idx] * totalGain; + const float absSample = std::fabs(resultSample); - float resultSample = buffer[idx] * totalGain; buffer[idx] = resultSample; - float squaredSample = resultSample * resultSample; - singleChannelSquaredSum += squaredSample; - totalSquaredSum += squaredSample; + if (absSample > peak) { + peak = absSample; + } } - float rms = dsp::samplesRootMeanSquare(singleChannelSquaredSum, samplesCount); - m_audioSignalNotifier.updateSignalValues(audioChNum, rms); - } + m_audioSignalNotifier.updateSignalValues(audioChNum, peak); - m_isSilent = RealIsNull(totalSquaredSum); - m_audioSignalNotifier.notifyAboutChanges(); - - if (!m_compressor->isActive()) { - return; + if (peak > globalPeak) { + globalPeak = peak; + } } - float totalRms = dsp::samplesRootMeanSquare(totalSquaredSum, samplesCount * channelsCount); - m_compressor->process(totalRms, buffer, channelsCount, samplesCount); + m_isSilent = RealIsNull(globalPeak); + m_audioSignalNotifier.notifyAboutChanges(); } bool MixerChannel::isSilent() const diff --git a/src/framework/audio/engine/internal/mixerchannel.h b/src/framework/audio/engine/internal/mixerchannel.h index 5a476892106ce..aa0e5c684ae44 100644 --- a/src/framework/audio/engine/internal/mixerchannel.h +++ b/src/framework/audio/engine/internal/mixerchannel.h @@ -28,7 +28,6 @@ #include "../ifxresolver.h" #include "../ifxprocessor.h" -#include "dsp/compressor.h" #include "track.h" namespace muse::audio::engine { @@ -76,8 +75,6 @@ class MixerChannel : public ITrackAudioOutput, public Injectable, public async:: IAudioSourcePtr m_audioSource = nullptr; std::vector m_fxProcessors = {}; - dsp::CompressorPtr m_compressor = nullptr; - bool m_isSilent = true; async::Notification m_mutedChanged; diff --git a/src/framework/audio/tests/rpcpacker_tests.cpp b/src/framework/audio/tests/rpcpacker_tests.cpp index 710853ddafe9c..add55b0741705 100644 --- a/src/framework/audio/tests/rpcpacker_tests.cpp +++ b/src/framework/audio/tests/rpcpacker_tests.cpp @@ -295,11 +295,9 @@ TEST_F(Audio_RpcPackerTests, AudioSourceParams) TEST_F(Audio_RpcPackerTests, AudioSignalVal) { AudioSignalVal origin; - origin.amplitude = 0.6f; origin.pressure = 0.5; KNOWN_FIELDS(origin, - origin.amplitude, origin.pressure); ByteArray data = rpc::RpcPacker::pack(origin);