summaryrefslogtreecommitdiff
path: root/src/audio_core/renderer/effect/compressor.cpp
diff options
context:
space:
mode:
authorZephyron <zephyron@citron-emu.org>2025-02-04 16:32:59 +1000
committerMike Lothian <mike@fireburn.co.uk>2025-05-11 14:54:45 +0100
commita51362fe01e3aa2a787546789d4a6c7c96b394f1 (patch)
treefd19a4f1a243795a252b26414cb6d3ccd74feaf4 /src/audio_core/renderer/effect/compressor.cpp
parent54ffa573bffea82006d897141a1db4b1db536ea6 (diff)
audio_core/renderer: Add compressor and splitter support for Rev13
Implement new audio features available in AudioRenderer Revision 13: - Add AudioRendererRevision enum to track version-specific features - Implement CompressorEffect with statistics tracking support - Add SplitterDestination with previous volume reset functionality - Add version checks for feature compatibility The compressor provides dynamic range compression with configurable parameters and optional statistics tracking. The splitter improvements allow for more flexible volume management between audio transitions. These changes maintain compatibility with older revisions while enabling new features in Rev13.
Diffstat (limited to 'src/audio_core/renderer/effect/compressor.cpp')
-rw-r--r--src/audio_core/renderer/effect/compressor.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/audio_core/renderer/effect/compressor.cpp b/src/audio_core/renderer/effect/compressor.cpp
index fea0aefcf..3b32670f7 100644
--- a/src/audio_core/renderer/effect/compressor.cpp
+++ b/src/audio_core/renderer/effect/compressor.cpp
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <cmath>
#include "audio_core/renderer/effect/compressor.h"
namespace AudioCore::Renderer {
@@ -37,4 +39,48 @@ CpuAddr CompressorInfo::GetWorkbuffer(s32 index) {
return GetSingleBuffer(index);
}
+CompressorEffect::CompressorEffect(std::size_t sample_count_) : sample_count{sample_count_} {}
+
+void CompressorEffect::Process(std::span<f32> output_buffer, std::span<const f32> input_buffer) {
+ if (!IsEnabled() || !parameter.IsChannelCountValid()) {
+ std::copy(input_buffer.begin(), input_buffer.end(), output_buffer.begin());
+ return;
+ }
+
+ if (!result_state.empty() && parameter.statistics_reset) {
+ statistics.Reset(static_cast<u16>(parameter.channel_count));
+ }
+
+ // Process audio with compressor effect
+ for (u32 sample_index = 0; sample_index < sample_count; sample_index++) {
+ float mean = 0.0f;
+ for (u32 channel = 0; channel < parameter.channel_count; channel++) {
+ const auto sample = input_buffer[sample_index * parameter.channel_count + channel];
+ mean += sample * sample;
+ }
+ mean /= static_cast<float>(parameter.channel_count);
+
+ // Calculate compression gain
+ float compression_gain = 1.0f;
+ if (mean > parameter.threshold) {
+ compression_gain = parameter.threshold / mean;
+ compression_gain = std::pow(compression_gain, 1.0f - (1.0f / parameter.ratio));
+ }
+
+ // Apply compression
+ for (u32 channel = 0; channel < parameter.channel_count; channel++) {
+ const auto in_sample = input_buffer[sample_index * parameter.channel_count + channel];
+ const auto out_sample = in_sample * compression_gain * parameter.input_gain;
+ output_buffer[sample_index * parameter.channel_count + channel] = out_sample;
+
+ // Update statistics if enabled
+ if (parameter.statistics_enabled) {
+ statistics.maximum_mean = std::max(statistics.maximum_mean, mean);
+ statistics.minimum_gain = std::min(statistics.minimum_gain, compression_gain);
+ statistics.last_samples[channel] = std::abs(in_sample) * (1.0f / 32768.0f);
+ }
+ }
+ }
+}
+
} // namespace AudioCore::Renderer