Deluge Firmware 1.3.0
Build date: 2025.04.16
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/stereo_sample.h"
23#include <cmath>
24#include <span>
25
26class [[gnu::hot]] RMSFeedbackCompressor {
27public:
28 RMSFeedbackCompressor();
29
31 constexpr void setup(q31_t a, q31_t r, q31_t t, q31_t rat, q31_t fc, q31_t blend, float baseGain) {
32 setAttack(a);
33 setRelease(r);
34 setThreshold(t);
35 setRatio(rat);
36 setSidechain(fc);
37 setBlend(blend);
38 baseGain_ = baseGain;
39 }
40
42 void reset() {
43 state = 0;
44 er = 0;
45 mean = 0;
46 onLastTime = false;
47 }
48
58 void render(std::span<StereoSample> buffer, q31_t volAdjustL, q31_t volAdjustR, q31_t finalVolume);
59
63 void renderVolNeutral(std::span<StereoSample> buffer, q31_t finalVolume);
64
67 [[nodiscard]] float runEnvelope(float current, float desired, float numSamples) const;
68
70 [[nodiscard]] inline constexpr q31_t getAttack() const { return attackKnobPos; }
71
73 [[nodiscard]] inline constexpr float getAttackMS() const { return attackMS; }
74
78 constexpr int32_t setAttack(q31_t attack) {
79 // this exp will be between 1 and 7ish, half the knob range is about 2.5
80 attackMS = 0.5 + (std::exp(2 * float(attack) / ONE_Q31f) - 1) * 10;
81 a_ = (-1000.0f / kSampleRate) / attackMS;
82 attackKnobPos = attack;
83 return attackMS;
84 };
85
87 [[nodiscard]] inline constexpr q31_t getRelease() const { return releaseKnobPos; }
88
90 [[nodiscard]] inline constexpr float getReleaseMS() const { return releaseMS; }
91
95 constexpr int32_t setRelease(q31_t release) {
96 // this exp will be between 1 and 7ish, half the knob range is about 2.5
97 releaseMS = 50 + (std::exp(2 * float(release) / ONE_Q31f) - 1) * 50;
98 r_ = (-1000.0f / kSampleRate) / releaseMS;
99 releaseKnobPos = release;
100 return releaseMS;
101 };
102
104 [[nodiscard]] inline constexpr q31_t getThreshold() const { return thresholdKnobPos; }
108 constexpr void setThreshold(q31_t t) {
109 thresholdKnobPos = t;
110 threshold = 1 - 0.8f * (float(thresholdKnobPos) / ONE_Q31f);
111 }
112
114 [[nodiscard]] inline constexpr q31_t getRatio() const { return ratioKnobPos; }
115
117 [[nodiscard]] inline constexpr float getRatioForDisplay() const { return ratio; }
118
122 constexpr int32_t setRatio(q31_t rat) {
123 ratioKnobPos = rat;
124 fraction = 0.5f + (float(ratioKnobPos) / ONE_Q31f) / 2;
125 ratio = 1 / (1 - fraction);
126 return ratio;
127 }
128
130 q31_t getSidechain() { return sideChainKnobPos; }
131
133 [[nodiscard]] inline constexpr float getSidechainForDisplay() const { return fc_hz; }
134
138 constexpr int32_t setSidechain(q31_t f) {
139 sideChainKnobPos = f;
140 // this exp will be between 1 and 5ish, half the knob range is about 2
141 // the result will then be from 0 to 100hz with half the knob range at 60hz
142 fc_hz = (std::exp(1.5 * float(f) / ONE_Q31f) - 1) * 30;
143 float fc = fc_hz / float(kSampleRate);
144 float wc = fc / (1 + fc);
145 hpfA_ = wc * ONE_Q31;
146 return fc_hz;
147 }
148
150 constexpr q31_t getBlend() { return wet; }
152 constexpr int32_t getBlendForDisplay() { return wet > (127 << 24) ? 100 : 100 * (wet >> 24) >> 7; }
153
156 constexpr int32_t setBlend(q31_t blend) {
157 // hack to allow it to get to full wet. Safe since this isn't a modulatable param and doesn't need the headroom
158 dry = ONE_Q31 - blend;
159 wet = blend;
160 return getBlendForDisplay();
161 }
162
167 constexpr void setBaseGain(float baseGain) { baseGain_ = baseGain; }
168
170 void updateER(float numSamples, q31_t finalVolume);
171
173 float calcRMS(std::span<StereoSample> buffer);
174
176 uint8_t gainReduction = 0;
177
178private:
180 float a_ = (-1000.0f / kSampleRate);
182 float r_ = (-1000.0f / kSampleRate);
186 float fraction = 0.5;
191 float er = 0;
193 float threshdb = 17;
195 float threshold = 1;
197 q31_t hpfA_ = ONE_Q16;
198
200 float state = 0;
202 q31_t currentVolumeL = 0;
204 q31_t currentVolumeR = 0;
206 float rms = 0;
208 float mean = 0;
211 bool onLastTime = false;
212
213 // sidechain filter
216 // for display
217 float attackMS = 0;
218 float releaseMS = 0;
219 float ratio = 2;
220 float fc_hz;
221
225
226 // raw knob positions
227 q31_t thresholdKnobPos = 0;
228 q31_t ratioKnobPos = 0;
229 q31_t attackKnobPos = 0;
230 q31_t releaseKnobPos = 0;
231 q31_t sideChainKnobPos = 0;
232 q31_t dry;
233 q31_t wet;
234};
constexpr void setBaseGain(float baseGain)
Definition rms_feedback.h:167
constexpr void setThreshold(q31_t t)
Definition rms_feedback.h:108
constexpr q31_t getRatio() const
Get the current ratio as a full-scale (0 to 2^31) number.
Definition rms_feedback.h:114
constexpr void setup(q31_t a, q31_t r, q31_t t, q31_t rat, q31_t fc, q31_t blend, float baseGain)
takes in all values as knob positions in the range 0-ONE_Q31
Definition rms_feedback.h:31
uint8_t gainReduction
Amount of gain reduction applied during the last render pass, in 6.2 fixed point decibels.
Definition rms_feedback.h:176
constexpr int32_t setAttack(q31_t attack)
Definition rms_feedback.h:78
constexpr float getAttackMS() const
Get the current attack time constant in MS for a 3db change.
Definition rms_feedback.h:73
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:70
float a_
Attack time constant, in inverse samples.
Definition rms_feedback.h:180
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:87
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:42
constexpr q31_t getBlend()
returns blend in q31
Definition rms_feedback.h:150
uint32_t lastSaturationTanHWorkingValue[2]
tanh working values for output saturation
Definition rms_feedback.h:210
q31_t currentVolumeR
Current right channel volume as a 5.26 signed fixed-point number.
Definition rms_feedback.h:204
constexpr float getReleaseMS() const
Get the current release time constant in MS for a 3db change.
Definition rms_feedback.h:90
float threshdb
Threshold, in decibels.
Definition rms_feedback.h:193
constexpr int32_t setSidechain(q31_t f)
Definition rms_feedback.h:138
float state
State for the internal envelope follower.
Definition rms_feedback.h:200
float rms
Log-RMS value of the last render.
Definition rms_feedback.h:206
q31_t hpfA_
A parameter for the internal HPF.
Definition rms_feedback.h:197
constexpr q31_t getThreshold() const
Get the current theshold as a full-scale (0 to 2^31) number.
Definition rms_feedback.h:104
float er
Definition rms_feedback.h:191
constexpr float getSidechainForDisplay() const
Get the current sidechain cutoff frequency in hertz.
Definition rms_feedback.h:133
constexpr int32_t getBlendForDisplay()
returns blend as an integer percentage
Definition rms_feedback.h:152
constexpr int32_t setRatio(q31_t rat)
Definition rms_feedback.h:122
constexpr int32_t setRelease(q31_t release)
Definition rms_feedback.h:95
float r_
Release time constant, in inverse samples.
Definition rms_feedback.h:182
constexpr int32_t setBlend(q31_t blend)
Definition rms_feedback.h:156
q31_t getSidechain()
Get the current sidechain cutoff frequency as a full-scale (0 to 2^31) integer.
Definition rms_feedback.h:130
float fraction
Definition rms_feedback.h:186
float threshold
The raw threshold value.
Definition rms_feedback.h:195
q31_t currentVolumeL
Current left channel volume as a 5.26 signed fixed-point number.
Definition rms_feedback.h:202
float mean
Mean value of the last render.
Definition rms_feedback.h:208
float baseGain_
Definition rms_feedback.h:224
constexpr float getRatioForDisplay() const
Get the current ratio as a float.
Definition rms_feedback.h:117
Definition ladder_components.h:23