Skip to content

Commit 4063300

Browse files
Draft the plugin class (crude - not building yet)
1 parent 5c29e1c commit 4063300

2 files changed

Lines changed: 99 additions & 96 deletions

File tree

include/private/plugins/saturator.h

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
#ifndef PRIVATE_PLUGINS_SATURATOR_H_
2323
#define PRIVATE_PLUGINS_SATURATOR_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/Oversampler.h>
28+
#include <lsp-plug.in/dsp-units/shaping/Shaper.h>
2729
#include <lsp-plug.in/plug-fw/plug.h>
2830
#include <private/meta/saturator.h>
2931

@@ -37,47 +39,74 @@ namespace lsp
3739
class saturator: public plug::Module
3840
{
3941
protected:
40-
enum mode_t
42+
typedef struct eq_filter_t
4143
{
42-
CD_MONO,
43-
CD_STEREO,
44-
CD_X2_STEREO
45-
};
44+
dspu::filter_params_t sFP; // Filter parameters
45+
// TODO: Add ports
46+
} eq_filter_t;
47+
48+
typedef struct oversampler_t
49+
{
50+
dspu::over_mode_t enOverMode; // Oversampler Mode
51+
size_t nOversampling; // Oversampling Factor
52+
size_t nOverSampleRate; // Oversampled Rate
53+
// TODO: Add ports
54+
} oversampler_t;
55+
56+
typedef struct shaper_t
57+
{
58+
float fPreGain; // Pre Gain
59+
float fPostGain; // Post Gain
60+
float fSlope; // Slope (for sinusoidal saturator)
61+
float fShape; // Shape (for many saturators)
62+
float fHighLevel; // High Level (for asymmetric saturators)
63+
float fLowLevel; // Low Level (for asymmetric saturators)
64+
float fRadius; // Radius (for quarter circle saturator)
65+
float fLevels; // Levels (for bitcrush)
66+
float fCCompanding; // Continuos companding (for continuous A-law and μ-law companders)
67+
float fQCompanding; // Quantized companding (for quantized A-law and μ-law companders)
68+
float fBias; // Bias (for quantized μ-law)
69+
float fDrive; // Drive (for TAP)
70+
float fBlend; // Blend (for TAP)
71+
dspu::sh_function_t enShapingFcn; // Shaping Function
72+
// TODO: Add ports
73+
} shaper_t;
4674

4775
typedef struct channel_t
4876
{
4977
// DSP processing modules
50-
dspu::Delay sLine; // Delay line
51-
dspu::Bypass sBypass; // Bypass
78+
dspu::Bypass sBypass; // Bypass
79+
dspu::Equalizer sPreEQ; // Pre EQ
80+
dspu::Oversampler sOversampler; // Oversampler
81+
dspu::Shaper sShaper; // Nonlinearity
82+
dspu::Equalizer sPostEQ; // Post EQ
5283

5384
// Parameters
54-
ssize_t nDelay; // Actual delay of the signal
55-
float fDryGain; // Dry gain (unprocessed signal)
56-
float fWetGain; // Wet gain (processed signal)
85+
eq_filter_t *vPreEQFilters; // Pre EQ Filters
86+
oversampler_t sOversamplerParams; // Oversampler Parameters
87+
shaper_t sShaperParams; // Shaper Parameters
88+
eq_filter_t *vPostEQFilters; // Post EQ Filters
5789

5890
// Input ports
59-
plug::IPort *pIn; // Input port
60-
plug::IPort *pOut; // Output port
61-
plug::IPort *pDelay; // Delay (in samples)
62-
plug::IPort *pDry; // Dry control
63-
plug::IPort *pWet; // Wet control
91+
plug::IPort *pIn; // Input port
92+
plug::IPort *pOut; // Output port
6493

6594
// Output ports
66-
plug::IPort *pOutDelay; // Output delay time
67-
plug::IPort *pInLevel; // Input signal level
68-
plug::IPort *pOutLevel; // Output signal level
95+
// TODO: Add ports
6996
} channel_t;
7097

7198
protected:
72-
size_t nChannels; // Number of channels
73-
channel_t *vChannels; // Delay channels
74-
float *vBuffer; // Temporary buffer for audio processing
99+
size_t nSampleRate; // Sample rate
100+
size_t nFilters; // Number of filters for Pre and Post EQs of all channels.
101+
size_t nChannels; // Number of channels
102+
channel_t *vChannels; // Delay channels
103+
float *vBuffer; // Temporary buffer for audio processing
75104

76-
plug::IPort *pBypass; // Bypass
77-
plug::IPort *pGainOut; // Output gain
78-
plug::IPort *pComment; // Comment
105+
plug::IPort *pBypass; // Bypass
106+
plug::IPort *pComment; // Comment
107+
// TODO: Add ports
79108

80-
uint8_t *pData; // Allocated data
109+
uint8_t *pData; // Allocated data
81110

82111
protected:
83112
void do_destroy();

src/main/plug/saturator.cpp

Lines changed: 44 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ namespace lsp
6262
++nChannels;
6363

6464
// Initialize other parameters
65+
nSampleRate = 0;
66+
nFilters = 0;
6567
vChannels = NULL;
6668
vBuffer = NULL;
6769

6870
pBypass = NULL;
69-
pGainOut = NULL;
7071
pComment = NULL;
7172

7273
pData = NULL;
@@ -101,21 +102,16 @@ namespace lsp
101102
channel_t *c = &vChannels[i];
102103

103104
// Construct in-place DSP processors
104-
c->sLine.construct();
105105
c->sBypass.construct();
106+
c->sPreEQ.construct();
107+
c->sOversampler.construct();
108+
c->sShaper.construct();
109+
c->sPostEQ.construct();
106110

107-
// Initialize fields
108-
c->nDelay = 0;
109-
c->fDryGain = 0.0f;
110-
c->fWetGain = 0.0f;
111+
// TODO: Calls to equalizers init methods here?
111112

112113
c->pIn = NULL;
113114
c->pOut = NULL;
114-
c->pDelay = NULL;
115-
c->pDry = NULL;
116-
c->pWet = NULL;
117-
118-
c->pOutDelay = NULL;
119115
}
120116

121117
// Bind ports
@@ -142,22 +138,15 @@ namespace lsp
142138
{
143139
channel_t *pc = &vChannels[0];
144140

145-
// Share some controls across all channels
146-
c->pDelay = pc->pDelay;
147-
c->pDry = pc->pDry;
148-
c->pWet = pc->pWet;
141+
// TODO: Ports shared between channels go here
149142
}
150143
else
151144
{
152-
// Initialize input controls for the first channel
153-
BIND_PORT(c->pDelay);
154-
BIND_PORT(c->pDry);
155-
BIND_PORT(c->pWet);
145+
// TODO: Initialize input controls for the first channel
156146
}
157147
}
158148

159-
// Bind output gain
160-
BIND_PORT(pGainOut);
149+
// TODO: Bind output ports.
161150
BIND_PORT(pComment);
162151

163152
// Bind output meters
@@ -168,14 +157,12 @@ namespace lsp
168157
if (i > 0)
169158
{
170159
channel_t *pc = &vChannels[0];
171-
// Share some meters across all channels
172-
c->pOutDelay = pc->pOutDelay;
160+
// TODO: Output ports shared between channels go here
173161
}
174162
else
175-
BIND_PORT(c->pOutDelay);
176-
177-
BIND_PORT(c->pInLevel);
178-
BIND_PORT(c->pOutLevel);
163+
{
164+
// TODO: Initialize output ports for the first channel
165+
}
179166
}
180167
}
181168

@@ -194,7 +181,10 @@ namespace lsp
194181
{
195182
channel_t *c = &vChannels[i];
196183
c->sBypass.destroy();
197-
c->sLine.destroy();
184+
c->sPreEQ.destroy();
185+
c->sOversampler.destroy();
186+
c->sShaper.destroy();
187+
c->sPostEQ.destroy();
198188
}
199189
vChannels = NULL;
200190
}
@@ -211,31 +201,33 @@ namespace lsp
211201

212202
void saturator::update_sample_rate(long sr)
213203
{
204+
if (sr == nSampleRate)
205+
return;
206+
214207
// Update sample rate for the bypass processors
215208
for (size_t i=0; i<nChannels; ++i)
216209
{
217210
channel_t *c = &vChannels[i];
218-
c->sLine.init(dspu::millis_to_samples(sr, meta::saturator::DELAY_OUT_MAX_TIME));
219211
c->sBypass.init(sr);
212+
c->sPreEQ.set_sample_rate(sr);
213+
c->sShaper.set_sample_rate(sr);
214+
c->sPostEQ.set_sample_rate(sr);
220215
}
216+
217+
nSampleRate = sr;
221218
}
222219

223220
void saturator::update_settings()
224221
{
225-
float out_gain = pGainOut->value();
226222
bool bypass = pBypass->value() >= 0.5f;
227223

228224
for (size_t i=0; i<nChannels; ++i)
229225
{
230226
channel_t *c = &vChannels[i];
231227

232-
// Store the parameters for each processor
233-
c->fDryGain = c->pDry->value() * out_gain;
234-
c->fWetGain = c->pWet->value() * out_gain;
235-
c->nDelay = c->pDelay->value();
228+
// TODO: Store the parameters for each processor
236229

237-
// Update processors
238-
c->sLine.set_delay(c->nDelay);
230+
// TODO: Update processors
239231
c->sBypass.set_bypass(bypass);
240232
}
241233

@@ -265,28 +257,25 @@ namespace lsp
265257
if ((in == NULL) || (out == NULL))
266258
continue;
267259

268-
// Input and output gain meters
269-
float in_gain = 0.0f;
270-
float out_gain = 0.0f;
271-
272260
// Process the channel with BUFFER_SIZE chunks
273261
// Note: since input buffer pointer can be the same to output buffer pointer,
274262
// we need to store the processed signal data to temporary buffer before
275263
// it gets processed by the dspu::Bypass processor.
276264
for (size_t n=0; n<samples; )
277265
{
278-
const size_t count = lsp_min(samples - n, BUFFER_SIZE);
279-
280-
// Pre-process signal (fill buffer)
281-
c->sLine.process_ramping(vBuffer, in, c->fWetGain, c->nDelay, count);
266+
const size_t to_do = samples - n;
267+
const size_t to_do_up = c->sOversamplerParams.nOversampling * to_do;
282268

283-
// Apply 'dry' control
284-
if (c->fDryGain > 0.0f)
285-
dsp::fmadd_k3(vBuffer, in, c->fDryGain, count);
269+
const size_t count_up = lsp_min(to_do_up, BUFFER_SIZE);
270+
const size_t count = count_up / c->sOversamplerParams.nOversampling;
286271

287-
// Compute the gain of input and output signal.
288-
in_gain = lsp_max(in_gain, dsp::abs_max(in, count));
289-
out_gain = lsp_max(out_gain, dsp::abs_max(vBuffer, count));
272+
c->sPreEQ.process(vBuffer, in, count);
273+
dsp::mul_k2(vBuffer, c->sShaperParams.fPreGain, count);
274+
c->sOversampler.upsample(vBuffer, vBuffer, count);
275+
c->sShaper.process_overwrite(vBuffer, vBuffer, count_up);
276+
c->sOversampler.downsample(vBuffer, vBuffer, count);
277+
dsp::mul_k2(vBuffer, c->sShaperParams.fPostGain, count);
278+
c->sPostEQ.process(vBuffer, in, count);
290279

291280
// Process the
292281
// - dry (unprocessed) signal stored in 'in'
@@ -299,14 +288,6 @@ namespace lsp
299288
out += count;
300289
n += count;
301290
}
302-
303-
// Update meters
304-
c->pInLevel->set_value(in_gain);
305-
c->pOutLevel->set_value(out_gain);
306-
307-
// Output the delay value in milliseconds
308-
float millis = dspu::samples_to_millis(fSampleRate, c->nDelay);
309-
c->pOutDelay->set_value(millis);
310291
}
311292
}
312293

@@ -323,22 +304,16 @@ namespace lsp
323304

324305
v->begin_object(c, sizeof(channel_t));
325306
{
326-
v->write_object("sLine", &c->sLine);
327307
v->write_object("sBypass", &c->sBypass);
308+
v->write_object("sPreEQ", &c->sPreEQ);
309+
v->write_object("sOversampler", &c->sOversampler);
310+
v->write_object("sShaper", &c->sShaper);
311+
v->write_object("sPostEQ", &c->sPostEQ);
328312

329-
v->write("nDelay", c->nDelay);
330-
v->write("fDryGain", c->fDryGain);
331-
v->write("fWetWain", c->fWetGain);
313+
// TODO: Dump the various parameters structures
332314

333315
v->write("pIn", c->pIn);
334316
v->write("pOut", c->pOut);
335-
v->write("pDelay", c->pDelay);
336-
v->write("pDry", c->pDry);
337-
v->write("pWet", c->pWet);
338-
339-
v->write("pOutDelay", c->pOutDelay);
340-
v->write("pInLevel", c->pInLevel);
341-
v->write("pOutLevel", c->pOutLevel);
342317
}
343318
v->end_object();
344319
}
@@ -347,7 +322,6 @@ namespace lsp
347322
v->write("vBuffer", vBuffer);
348323

349324
v->write("pBypass", pBypass);
350-
v->write("pGainOut", pGainOut);
351325

352326
v->write("pData", pData);
353327
}

0 commit comments

Comments
 (0)