Skip to content

Commit 5fe01eb

Browse files
committed
First steps of implementing sidechain pre-equalization
1 parent 52547a5 commit 5fe01eb

6 files changed

Lines changed: 532 additions & 52 deletions

File tree

include/private/meta/deesser.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,51 @@ namespace lsp
3737
static constexpr float ZOOM_MAX = GAIN_AMP_0_DB;
3838
static constexpr float ZOOM_DFL = GAIN_AMP_0_DB;
3939
static constexpr float ZOOM_STEP = 0.0125f;
40+
41+
static constexpr float LPF_FREQ_MIN = 1000.0f;
42+
static constexpr float LPF_FREQ_MAX = SPEC_FREQ_MAX;
43+
static constexpr float LPF_FREQ_DFL = 10000.0f;
44+
static constexpr float LPF_FREQ_STEP = 0.025f;
45+
46+
static constexpr float HPF_FREQ_MIN = 100.0f;
47+
static constexpr float HPF_FREQ_MAX = 4000.0f;
48+
static constexpr float HPF_FREQ_DFL = 2000.0f;
49+
static constexpr float HPF_FREQ_STEP = 0.025f;
50+
51+
static constexpr float PF_Q_MIN = 0.0f;
52+
static constexpr float PF_Q_MAX = 1.0f;
53+
static constexpr float PF_Q_DFL = 0.0f;
54+
static constexpr float PF_Q_STEP = 0.0025f;
55+
56+
static constexpr float PEAK1_FREQ_MIN = 1000.0f;
57+
static constexpr float PEAK1_FREQ_MAX = 8000.0f;
58+
static constexpr float PEAK1_FREQ_DFL = 4000.0f;
59+
static constexpr float PEAK1_FREQ_STEP = 0.025f;
60+
61+
static constexpr float PEAK2_FREQ_MIN = 1000.0f;
62+
static constexpr float PEAK2_FREQ_MAX = 8000.0f;
63+
static constexpr float PEAK2_FREQ_DFL = 6000.0f;
64+
static constexpr float PEAK2_FREQ_STEP = 0.025f;
65+
66+
static constexpr float PEAK_Q_MIN = 0.0f;
67+
static constexpr float PEAK_Q_MAX = 100.0f;
68+
static constexpr float PEAK_Q_DFL = 0.0f;
69+
static constexpr float PEAK_Q_STEP = 0.0025f;
70+
71+
static constexpr float PEAK_GAIN_MIN = GAIN_AMP_0_DB;
72+
static constexpr float PEAK_GAIN_MAX = GAIN_AMP_P_24_DB;
73+
static constexpr float PEAK_GAIN_DFL = GAIN_AMP_P_6_DB;
74+
static constexpr float PEAK_GAIN_STEP = 0.0025f;
75+
76+
static constexpr float REACT_TIME_MIN = 0.000f;
77+
static constexpr float REACT_TIME_MAX = 1.000f;
78+
static constexpr float REACT_TIME_DFL = 0.200f;
79+
static constexpr float REACT_TIME_STEP = 0.001f;
80+
81+
static constexpr size_t MESH_POINTS = 640;
82+
static constexpr size_t FFT_RANK = 13;
83+
static constexpr size_t FFT_ITEMS = 1 << FFT_RANK;
84+
static constexpr size_t REFRESH_RATE = 20;
4085
} deesser;
4186

4287
// Plugin type metadata

include/private/plugins/deesser.h

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
#ifndef PRIVATE_PLUGINS_DEESSER_H_
2323
#define PRIVATE_PLUGINS_DEESSER_H_
2424

25-
#include <lsp-plug.in/dsp-units/util/Delay.h>
2625
#include <lsp-plug.in/dsp-units/ctl/Bypass.h>
26+
#include <lsp-plug.in/dsp-units/filters/Equalizer.h>
27+
#include <lsp-plug.in/dsp-units/util/Analyzer.h>
28+
#include <lsp-plug.in/dsp-units/util/Delay.h>
2729
#include <lsp-plug.in/plug-fw/plug.h>
2830
#include <private/meta/deesser.h>
2931

@@ -37,6 +39,19 @@ namespace lsp
3739
class deesser: public plug::Module
3840
{
3941
protected:
42+
enum sc_filter_t
43+
{
44+
SCF_PEAK1,
45+
SCF_PEAK2,
46+
SCF_LOWPASS,
47+
SCF_HIPASS,
48+
SCF_TOTAL,
49+
50+
SCF_OUT_MESH = (1 << (SCF_TOTAL + 1)),
51+
SCF_SYNC_ALL = (1 << (SCF_TOTAL + 2)) - 1
52+
};
53+
54+
4055
typedef struct premix_t
4156
{
4257
float fInToSc; // Input -> Sidechain mix
@@ -63,10 +78,43 @@ namespace lsp
6378
plug::IPort *pScToLink; // Sidechain -> Link mix
6479
} premix_t;
6580

81+
typedef struct preeq_t
82+
{
83+
uint32_t nSyncMesh; // Synchronize mesh
84+
float *vMeshData[SCF_TOTAL+1]; // Mesh data
85+
86+
plug::IPort *pHpfSlope; // Slope of the high-pass filter
87+
plug::IPort *pHpfFreq; // Frequency of the high-pass filter
88+
plug::IPort *pHpfQ; // Q factor of the high-pass filter
89+
plug::IPort *pLpfSlope; // Slope of the low-pass filter
90+
plug::IPort *pLpfFreq; // Frequency of the low-pass filter
91+
plug::IPort *pLpfQ; // Q factor of the low-pass filter
92+
plug::IPort *pPeak1On; // Peak filter 1 enable
93+
plug::IPort *pPeak1Freq; // Peak filter 1 frequency
94+
plug::IPort *pPeak1Gain; // Peak filter 1 gain
95+
plug::IPort *pPeak1Q; // Peak filter 1 Q factor
96+
plug::IPort *pPeak2On; // Peak filter 2 enable
97+
plug::IPort *pPeak2Freq; // Peak filter 2 frequency
98+
plug::IPort *pPeak2Gain; // Peak filter 2 gain
99+
plug::IPort *pPeak2Q; // Peak filter 2 Q factor
100+
plug::IPort *pMesh; // Filter mesh (overall + filters)
101+
} preeq_t;
102+
103+
typedef struct analysis_t
104+
{
105+
float *vFreqs; // Analyzer FFT frequencies
106+
uint32_t *vIndexes; // Analyzer FFT indexes
107+
108+
plug::IPort *pReactivity; // Reactivity
109+
plug::IPort *pShiftGain; // Shift gain port
110+
plug::IPort *pMesh; // FFT analysis data
111+
} analysis_t;
112+
66113
typedef struct channel_t
67114
{
68115
// DSP processing modules
69116
dspu::Bypass sBypass; // Bypass
117+
dspu::Equalizer sSCEq; // Sidechain equalizer
70118

71119
float *vIn; // Input signal
72120
float *vOut; // Output signal
@@ -86,18 +134,29 @@ namespace lsp
86134
float *vBuffer; // Temporary buffer for audio processing
87135
bool bSidechain; // Sidechain version
88136

137+
dspu::Analyzer sAnalyzer; // Analyzer
138+
89139
premix_t sPremix; // Premix settings
140+
analysis_t sAnalysis; // Analyzer parameters
141+
preeq_t sPreEq; // Pre-equalization settings
90142

91143
plug::IPort *pBypass; // Bypass
92144
plug::IPort *pGainIn; // Input gain
93145
plug::IPort *pGainOut; // Output gain
94146

95147
uint8_t *pData; // Allocated data
96148

149+
protected:
150+
static bool set_filter_params(dspu::Equalizer * eq, uint32_t index, const dspu::filter_params_t * fp);
151+
97152
protected:
98153
void do_destroy();
99154
void update_premix();
155+
void update_analyzer();
156+
void update_preeq();
157+
void bind_input_channels();
100158
void premix_channel(uint32_t channel, size_t count);
159+
void output_preeq_meshes();
101160

102161
public:
103162
explicit deesser(const meta::plugin_t *meta);

res/main/ui/plugins/dynamics/deesser.xml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,75 @@
300300
<group text="groups.plug.deesser" vexpand="false" hexpand="true" ipadding="0">
301301

302302
</group>
303+
304+
<group text="groups.pre_equalization" vexpand="false" hexpand="true" ipadding="0">
305+
<grid rows="4" cols="10">
306+
<!-- Row 1 -->
307+
<cell cols="2">
308+
<hbox>
309+
<label text="labels.flt.hpf" />
310+
<combo id="hpf_s" />
311+
</hbox>
312+
</cell>
313+
<cell cols="3">
314+
<button id="pk1_on" text="labels.flt.peak_1" />
315+
</cell>
316+
<cell cols="3">
317+
<button id="pk2_on" text="labels.flt.peak_2" />
318+
</cell>
319+
<cell cols="2">
320+
<hbox>
321+
<label text="labels.flt.lpf" />
322+
<combo id="lpf_s" />
323+
</hbox>
324+
</cell>
325+
326+
<!-- Row 2 -->
327+
<label text="labels.freq" />
328+
<label text="labels.q" />
329+
330+
<label text="labels.freq" />
331+
<label text="labels.q" />
332+
<label text="labels.gain" />
333+
334+
<label text="labels.freq" />
335+
<label text="labels.q" />
336+
<label text="labels.gain" />
337+
338+
<label text="labels.freq" />
339+
<label text="labels.q" />
340+
341+
<!-- Row 3 -->
342+
<knob id="hpf_f" />
343+
<knob id="hpf_q" />
344+
345+
<knob id="pk1_f" />
346+
<knob id="pk1_q" />
347+
<knob id="pk1_g" />
348+
349+
<knob id="pk2_f" />
350+
<knob id="pk2_q" />
351+
<knob id="pk2_g" />
352+
353+
<knob id="lpf_f" />
354+
<knob id="lpf_q" />
355+
356+
<!-- Row 4 -->
357+
<value id="hpf_f" />
358+
<value id="hpf_q" />
359+
360+
<value id="pk1_f" />
361+
<value id="pk1_q" />
362+
<value id="pk1_g" />
363+
364+
<value id="pk2_f" />
365+
<value id="pk2_q" />
366+
<value id="pk2_g" />
367+
368+
<value id="lpf_f" />
369+
<value id="lpf_q" />
370+
</grid>
371+
</group>
303372

304373
<!-- Separator -->
305374
<vsep bg.color="bg" pad.h="2" hreduce="true"/>

src/main/meta/deesser.cpp

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ namespace lsp
4141
{
4242
//-------------------------------------------------------------------------
4343
// Plugin metadata
44+
static const port_item_t de_pf_filter_slope[] =
45+
{
46+
{ "off", "eq.slope.off" },
47+
{ "12 dB/oct", "eq.slope.12dbo" },
48+
{ "24 dB/oct", "eq.slope.24dbo" },
49+
{ "36 dB/oct", "eq.slope.36dbo" },
50+
{ "48 dB/oct", "eq.slope.48dbo" },
51+
{ NULL, NULL }
52+
};
53+
4454

4555
#define DE_PREMIX \
4656
SWITCH("showpmx", "Show pre-mix overlay", "Show premix bar", 0.0f), \
@@ -60,20 +70,43 @@ namespace lsp
6070
#define DE_SHM_LINK_STEREO \
6171
OPT_RETURN_STEREO("link", "shml_", "Side-chain shared memory link")
6272

73+
#define DE_FILTERS \
74+
COMBO("hpf_s", "High-pass filter slope", "HPF slope", 1, de_pf_filter_slope), \
75+
LOG_CONTROL("hpf_f", "High-pass filter frequency", "HPF freq", U_HZ, deesser::HPF_FREQ), \
76+
LOG_CONTROL("hpf_q", "High-pass filter qualifty factor", "HPF Q", U_NONE, deesser::PF_Q), \
77+
COMBO("lpf_s", "Low-pass filter slope", "LPF slope", 0, de_pf_filter_slope), \
78+
LOG_CONTROL("lpf_f", "Low-pass filter frequency", "LPF freq", U_HZ, deesser::LPF_FREQ), \
79+
LOG_CONTROL("lpf_q", "Low-pass filter qualifty factor", "LPF Q", U_NONE, deesser::PF_Q), \
80+
SWITCH("pk1_on", "Peak filter 1 on", "Peak 1 on", 1.0f), \
81+
LOG_CONTROL("pk1_f", "Peak filter 1 frequency", "Peak 1 freq", U_HZ, deesser::PEAK1_FREQ), \
82+
LOG_CONTROL("pk1_g", "Peak filter 1 gain", "Peak 1 gain", U_HZ, deesser::PEAK_GAIN), \
83+
LOG_CONTROL("pk1_q", "Peak filter 1 qualifty factor", "Peak 1 Q", U_NONE, deesser::PEAK_Q), \
84+
SWITCH("pk2_on", "Peak filter 2 on", "Peak 2 on", 1.0f), \
85+
LOG_CONTROL("pk2_f", "Peak filter 2 frequency", "Peak 2 freq", U_HZ, deesser::PEAK2_FREQ), \
86+
LOG_CONTROL("pk2_g", "Peak filter 2 gain", "Peak 2 gain", U_HZ, deesser::PEAK_GAIN), \
87+
LOG_CONTROL("pk2_q", "Peak filter 2 qualifty factor", "Peak 2 Q", U_NONE, deesser::PEAK_Q), \
88+
MESH("sceq", "Side-chain equalization chart", 6, deesser::MESH_POINTS + 4)
89+
90+
#define DE_ANALYSIS(channels) \
91+
LOG_CONTROL("react", "FFT reactivity", "Reactivity", U_MSEC, deesser::REACT_TIME), \
92+
AMP_GAIN("shift", "Shift gain", "Shift", 1.0f, 100.0f), \
93+
MESH("fftg", "FFT analysis graph", 1 + channels*2, deesser::MESH_POINTS + 2)
94+
6395
#define DE_COMMON \
6496
BYPASS, \
6597
IN_GAIN, \
6698
OUT_GAIN, \
67-
SWITCH("showmx", "Show mix overlay", "Show mix bar", 0.0f), \
6899
SWITCH("showsc", "Show sidechain overlay", "Show SC bar", 0.0f), \
69100
LOG_CONTROL("zoom", "Graph zoom", "Zoom", U_GAIN_AMP, deesser::ZOOM)
70101

71102
static const port_t deesser_mono_ports[] =
72103
{
73104
PORTS_MONO_PLUGIN,
74105
DE_SHM_LINK_MONO,
75-
DE_PREMIX,
76106
DE_COMMON,
107+
DE_PREMIX,
108+
DE_ANALYSIS(1),
109+
DE_FILTERS,
77110

78111
PORTS_END
79112
};
@@ -82,8 +115,10 @@ namespace lsp
82115
{
83116
PORTS_STEREO_PLUGIN,
84117
DE_SHM_LINK_STEREO,
85-
DE_PREMIX,
86118
DE_COMMON,
119+
DE_PREMIX,
120+
DE_ANALYSIS(2),
121+
DE_FILTERS,
87122

88123
PORTS_END
89124
};
@@ -93,8 +128,10 @@ namespace lsp
93128
PORTS_MONO_PLUGIN,
94129
PORTS_MONO_SIDECHAIN,
95130
DE_SHM_LINK_MONO,
96-
DE_SC_PREMIX,
97131
DE_COMMON,
132+
DE_SC_PREMIX,
133+
DE_ANALYSIS(1),
134+
DE_FILTERS,
98135

99136
PORTS_END
100137
};
@@ -104,8 +141,10 @@ namespace lsp
104141
PORTS_STEREO_PLUGIN,
105142
PORTS_STEREO_SIDECHAIN,
106143
DE_SHM_LINK_STEREO,
107-
DE_SC_PREMIX,
108144
DE_COMMON,
145+
DE_SC_PREMIX,
146+
DE_ANALYSIS(2),
147+
DE_FILTERS,
109148

110149
PORTS_END
111150
};

0 commit comments

Comments
 (0)