Deluge Firmware 1.3.0
Build date: 2025.09.14
Loading...
Searching...
No Matches
rms_feedback.h
1/*
2 * Copyright © 2023-2024 Mark Adams
3 *
4 * This file is part of The Synthstrom Audible Deluge Firmware.
5 *
6 * The Synthstrom Audible Deluge Firmware is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software Foundation,
8 * either version 3 of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with this program.
15 * If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#include "definitions_cxx.hpp"
21#include "dsp/filter/ladder_components.h"
22#include "dsp_ng/core/types.hpp"
23#include <cmath>
24#include <span>
25
26namespace deluge::dsp {
27class [[gnu::hot]] RMSFeedbackCompressor {
28public:
29 RMSFeedbackCompressor();
30
32 constexpr void setup(q31_t a, q31_t r, q31_t t, q31_t rat, q31_t fc, FixedPoint<31> blend, float baseGain) {
33 setAttack(a);
34 setRelease(r);
35 setThreshold(t);
36 setRatio(rat);
37 setSidechain(fc);
38 setBlend(blend);
39 baseGain_ = baseGain;
40 }
41
43 void reset() {
44 state = 0;
45 er = 0;
46 mean = 0;
47 onLastTime = false;
48 }
49
59 void render(StereoBuffer<q31_t> buffer, q31_t volAdjustL, q31_t volAdjustR, q31_t finalVolume);
60
64 void renderVolNeutral(StereoBuffer<q31_t> buffer, q31_t finalVolume);
65
68 [[nodiscard]] float runEnvelope(float current, float desired, float numSamples) const;
69
71 [[nodiscard]] inline constexpr q31_t getAttack() const { return attackKnobPos; }
72
74 [[nodiscard]] inline constexpr float getAttackMS() const { return attackMS; }
75
79 constexpr int32_t setAttack(q31_t attack) {
80 // this exp will be between 1 and 7ish, half the knob range is about 2.5
81 attackMS = 0.5 + (std::exp(2 * float(attack) / ONE_Q31f) - 1) * 10;
82 a_ = (-1000.0f / kSampleRate) / attackMS;
83 attackKnobPos = attack;
84 return attackMS;
85 };
86
88 [[nodiscard]] inline constexpr q31_t getRelease() const { return releaseKnobPos; }
89
91 [[nodiscard]] inline constexpr float getReleaseMS() const { return releaseMS; }
92
96 constexpr int32_t setRelease(q31_t release) {
97 // this exp will be between 1 and 7ish, half the knob range is about 2.5
98 releaseMS = 50 + (std::exp(2 * float(release) / ONE_Q31f) - 1) * 50;
99 r_ = (-1000.0f / kSampleRate) / releaseMS;
100 releaseKnobPos = release;
101 return releaseMS;
102 };
103
105 [[nodiscard]] inline constexpr q31_t getThreshold() const { return thresholdKnobPos; }
109 constexpr void setThreshold(q31_t t) {
110 thresholdKnobPos = t;
111 threshold = 1 - 0.8f * (float(thresholdKnobPos) / ONE_Q31f);
112 }
113
115 [[nodiscard]] inline constexpr q31_t getRatio() const { return ratioKnobPos; }
116
118 [[nodiscard]] inline constexpr float getRatioForDisplay() const { return ratio; }
119
123 constexpr int32_t setRatio(q31_t rat) {
124 ratioKnobPos = rat;
125 fraction = 0.5f + (float(ratioKnobPos) / ONE_Q31f) / 2;
126 ratio = 1 / (1 - fraction);
127 return ratio;
128 }
129
131 q31_t getSidechain() { return sideChainKnobPos; }
132
134 [[nodiscard]] inline constexpr float getSidechainForDisplay() const { return fc_hz; }
135
139 constexpr int32_t setSidechain(q31_t f) {
140 sideChainKnobPos = f;
141 // this exp will be between 1 and 5ish, half the knob range is about 2
142 // the result will then be from 0 to 100hz with half the knob range at 60hz
143 fc_hz = (std::exp(1.5 * float(f) / ONE_Q31f) - 1) * 30;
144 float fc = fc_hz / float(kSampleRate);
145 float wc = fc / (1 + fc);
146 hpfA_ = wc * ONE_Q31;
147 return fc_hz;
148 }
149
151 constexpr FixedPoint<31> getBlend() { return wet; }
152
154 constexpr int32_t getBlendForDisplay() { return wet.raw() > (127 << 24) ? 100 : 100 * (wet.raw() >> 24) >> 7; }
155
158 constexpr int32_t setBlend(FixedPoint<31> blend) {
159 // hack to allow it to get to full wet. Safe since this isn't a modulatable param and doesn't need the headroom
160 dry = 1.f - blend;
161 wet = blend;
162 return getBlendForDisplay();
163 }
164
169 constexpr void setBaseGain(float baseGain) { baseGain_ = baseGain; }
170
172 void updateER(float numSamples, q31_t finalVolume);
173
175 float calcRMS(StereoBuffer<q31_t> buffer);
176
178 uint8_t gainReduction = 0;
179
180private:
182 float a_ = (-1000.0f / kSampleRate);
184 float r_ = (-1000.0f / kSampleRate);
188 float fraction = 0.5;
193 float er = 0;
195 float threshdb = 17;
197 float threshold = 1;
199 q31_t hpfA_ = ONE_Q16;
200
202 float state = 0;
204 q31_t currentVolumeL = 0;
206 q31_t currentVolumeR = 0;
208 float rms = 0;
210 float mean = 0;
213 bool onLastTime = false;
214
215 // sidechain filter
218 // for display
219 float attackMS = 0;
220 float releaseMS = 0;
221 float ratio = 2;
222 float fc_hz;
223
227
228 // raw knob positions
229 q31_t thresholdKnobPos = 0;
230 q31_t ratioKnobPos = 0;
231 q31_t attackKnobPos = 0;
232 q31_t releaseKnobPos = 0;
233 q31_t sideChainKnobPos = 0;
234 FixedPoint<31> dry;
235 FixedPoint<31> wet;
236};
237} // namespace deluge::dsp
Fixed point number with a configurable number of fractional bits.
Definition fixedpoint.h:47
constexpr int32_t setBlend(FixedPoint< 31 > blend)
Definition rms_feedback.h:158
constexpr int32_t setAttack(q31_t attack)
Definition rms_feedback.h:79
constexpr q31_t getRelease() const
Get the current release time constant in terms of the full knob range (0 to 2^31)
Definition rms_feedback.h:88
constexpr q31_t getThreshold() const
Get the current theshold as a full-scale (0 to 2^31) number.
Definition rms_feedback.h:105
constexpr FixedPoint< 31 > getBlend()
returns blend in q31
Definition rms_feedback.h:151
q31_t currentVolumeL
Current left channel volume as a 5.26 signed fixed-point number.
Definition rms_feedback.h:204
q31_t currentVolumeR
Current right channel volume as a 5.26 signed fixed-point number.
Definition rms_feedback.h:206
float fraction
Definition rms_feedback.h:188
constexpr void setup(q31_t a, q31_t r, q31_t t, q31_t rat, q31_t fc, FixedPoint< 31 > blend, float baseGain)
takes in all values as knob positions in the range 0-ONE_Q31
Definition rms_feedback.h:32
q31_t hpfA_
A parameter for the internal HPF.
Definition rms_feedback.h:199
float threshold
The raw threshold value.
Definition rms_feedback.h:197
constexpr float getRatioForDisplay() const
Get the current ratio as a float.
Definition rms_feedback.h:118
float rms
Log-RMS value of the last render.
Definition rms_feedback.h:208
float mean
Mean value of the last render.
Definition rms_feedback.h:210
constexpr void setThreshold(q31_t t)
Definition rms_feedback.h:109
constexpr void setBaseGain(float baseGain)
Definition rms_feedback.h:169
float threshdb
Threshold, in decibels.
Definition rms_feedback.h:195
constexpr float getReleaseMS() const
Get the current release time constant in MS for a 3db change.
Definition rms_feedback.h:91
float state
State for the internal envelope follower.
Definition rms_feedback.h:202
constexpr float getSidechainForDisplay() const
Get the current sidechain cutoff frequency in hertz.
Definition rms_feedback.h:134
q31_t getSidechain()
Get the current sidechain cutoff frequency as a full-scale (0 to 2^31) integer.
Definition rms_feedback.h:131
uint8_t gainReduction
Amount of gain reduction applied during the last render pass, in 6.2 fixed point decibels.
Definition rms_feedback.h:178
constexpr int32_t setRelease(q31_t release)
Definition rms_feedback.h:96
constexpr int32_t setSidechain(q31_t f)
Definition rms_feedback.h:139
void reset()
Reset the state of the compressor so no gain reduction is applied at the start of the next render win...
Definition rms_feedback.h:43
float er
Definition rms_feedback.h:193
uint32_t lastSaturationTanHWorkingValue[2]
tanh working values for output saturation
Definition rms_feedback.h:212
constexpr float getAttackMS() const
Get the current attack time constant in MS for a 3db change.
Definition rms_feedback.h:74
float a_
Attack time constant, in inverse samples.
Definition rms_feedback.h:182
constexpr q31_t getAttack() const
Get the current attack time constant in terms of the full knob range (0 to 2^31)
Definition rms_feedback.h:71
float baseGain_
Definition rms_feedback.h:226
constexpr int32_t setRatio(q31_t rat)
Definition rms_feedback.h:123
float r_
Release time constant, in inverse samples.
Definition rms_feedback.h:184
constexpr q31_t getRatio() const
Get the current ratio as a full-scale (0 to 2^31) number.
Definition rms_feedback.h:115
constexpr int32_t getBlendForDisplay()
returns blend as an integer percentage
Definition rms_feedback.h:154
Definition ladder_components.h:23