diff options
| author | Zephyron <zephyron@citron-emu.org> | 2025-02-04 16:32:59 +1000 |
|---|---|---|
| committer | Mike Lothian <mike@fireburn.co.uk> | 2025-05-11 14:54:45 +0100 |
| commit | a51362fe01e3aa2a787546789d4a6c7c96b394f1 (patch) | |
| tree | fd19a4f1a243795a252b26414cb6d3ccd74feaf4 /src/audio_core/renderer/effect/compressor.cpp | |
| parent | 54ffa573bffea82006d897141a1db4b1db536ea6 (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.cpp | 46 |
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 |
