New Deesser, some minor bugs in sc-comp
(cherry picked from commit 599b6c04b61f28f0c9d6c2f30844c44c20927a13)
This commit is contained in:
committed by
Tobias Doerffel
parent
ea0c6c1c7b
commit
552a5951b1
@@ -168,6 +168,18 @@ struct multibandcompressor_metadata: public plugin_metadata<multibandcompressor_
|
||||
PLUGIN_NAME_ID_LABEL("multiband_compressor", "multibandcompressor", "Multiband Compressor")
|
||||
};
|
||||
|
||||
/// Markus's deesser - metadata
|
||||
struct deesser_metadata: public plugin_metadata<deesser_metadata>
|
||||
{
|
||||
enum { in_count = 2, out_count = 2, support_midi = false, require_midi = false, rt_capable = true };
|
||||
enum { param_bypass, param_detected, param_compression, param_detected_led, param_clip_out,
|
||||
param_detection, param_mode,
|
||||
param_threshold, param_ratio, param_laxity, param_makeup,
|
||||
param_f1_freq, param_f2_freq, param_f1_level, param_f2_level, param_f2_q,
|
||||
param_sc_listen, param_count };
|
||||
PLUGIN_NAME_ID_LABEL("deesser", "deesser", "Deesser")
|
||||
};
|
||||
|
||||
/// Markus's 5-band EQ - metadata
|
||||
struct equalizer5band_metadata: public plugin_metadata<equalizer5band_metadata>
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
PER_MODULE_ITEM(compressor, false, "compressor")
|
||||
PER_MODULE_ITEM(sidechaincompressor, false, "sidechaincompressor")
|
||||
PER_MODULE_ITEM(multibandcompressor, false, "multibandcompressor")
|
||||
PER_MODULE_ITEM(deesser, false, "deesser")
|
||||
PER_MODULE_ITEM(equalizer5band, false, "equalizer5band")
|
||||
PER_MODULE_ITEM(equalizer8band, false, "equalizer8band")
|
||||
PER_MODULE_ITEM(equalizer12band, false, "equalizer12band")
|
||||
|
||||
@@ -1052,6 +1052,41 @@ public:
|
||||
virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
|
||||
};
|
||||
|
||||
/// Deesser by Markus Schmidt (based on Thor's compressor and Krzysztof's filters)
|
||||
class deesser_audio_module: public audio_module<deesser_metadata>, public frequency_response_line_graph {
|
||||
private:
|
||||
enum CalfDeessModes {
|
||||
WIDE,
|
||||
SPLIT
|
||||
};
|
||||
float f1_freq_old, f2_freq_old, f1_level_old, f2_level_old, f2_q_old;
|
||||
float f1_freq_old1, f2_freq_old1, f1_level_old1, f2_level_old1, f2_q_old1;
|
||||
uint32_t detected_led;
|
||||
float detected, clip_out;
|
||||
gain_reduction_audio_module compressor;
|
||||
biquad_d2<float> hpL, hpR, lpL, lpR, pL, pR;
|
||||
public:
|
||||
float *ins[in_count];
|
||||
float *outs[out_count];
|
||||
float *params[param_count];
|
||||
uint32_t srate;
|
||||
bool is_active;
|
||||
volatile int last_generation, last_calculated_generation;
|
||||
deesser_audio_module();
|
||||
void activate();
|
||||
void deactivate();
|
||||
void params_changed();
|
||||
float freq_gain(int index, double freq, uint32_t sr)
|
||||
{
|
||||
return hpL.freq_gain(freq, sr) * pL.freq_gain(freq, sr);
|
||||
}
|
||||
void set_sample_rate(uint32_t sr);
|
||||
uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
|
||||
bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context);
|
||||
bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context);
|
||||
int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
|
||||
};
|
||||
|
||||
/// Equalizer 12 Band by Markus Schmidt (based on Krzysztof's filters)
|
||||
class equalizer12band_audio_module: public audio_module<equalizer12band_metadata>, public frequency_response_line_graph {
|
||||
private:
|
||||
|
||||
@@ -283,7 +283,7 @@ CALF_PORT_PROPS(sidechaincompressor) = {
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f2_active", "active" },
|
||||
};
|
||||
|
||||
CALF_PLUGIN_INFO(sidechaincompressor) = { 0x8502, "Sidechaincompressor", "Calf Sidechain Compressor", "Thor Harald Johansen / Markus Schmidt", calf_plugins::calf_copyright_info, "CompressorPlugin" };
|
||||
CALF_PLUGIN_INFO(sidechaincompressor) = { 0x8502, "Sidechaincompressor", "Calf Sidechain Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -373,6 +373,37 @@ CALF_PLUGIN_INFO(multibandcompressor) = { 0x8502, "Multibandcompressor", "Calf M
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CALF_PORT_NAMES(deesser) = {"In L", "In R", "Out L", "Out R"};
|
||||
|
||||
const char *deesser_detection_names[] = { "RMS", "Peak" };
|
||||
const char *deesser_mode_names[] = { "Wide", "Split" };
|
||||
|
||||
|
||||
CALF_PORT_PROPS(deesser) = {
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
|
||||
{ 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "detected", "Detected" },
|
||||
{ 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Gain Reduction" },
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "detected_led", "Active" },
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "Out" },
|
||||
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, deesser_detection_names, "detection", "Detection" },
|
||||
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, deesser_mode_names, "mode", "Mode" },
|
||||
{ 0.0625, 0.000976563, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" },
|
||||
{ 5, 1, 20, 21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" },
|
||||
{ 15, 1, 100, 1, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "laxity", "Laxity" },
|
||||
{ 1, 1, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup" },
|
||||
|
||||
{ 5000, 10, 18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "f1_freq", "Split" },
|
||||
{ 6000, 10, 18000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "f2_freq", "Peak" },
|
||||
{ 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f1_level", "Gain" },
|
||||
{ 4, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "Level" },
|
||||
{ 1, 0.1, 100,1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "f2_q", "Peak Q" },
|
||||
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" },
|
||||
};
|
||||
|
||||
CALF_PLUGIN_INFO(deesser) = { 0x8502, "Deesser", "Calf Deesser", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CALF_PORT_NAMES(equalizer5band) = {"In L", "In R", "Out L", "Out R"};
|
||||
|
||||
CALF_PORT_PROPS(equalizer5band) = {
|
||||
|
||||
@@ -1107,7 +1107,7 @@ void sidechaincompressor_audio_module::params_changed()
|
||||
f2_active = 1.f;
|
||||
break;
|
||||
case DEESSER_SPLIT:
|
||||
f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate);
|
||||
f1L.set_lp_rbj((float)*params[param_f2_freq] * (1 + 0.17), q, (float)srate);
|
||||
f1R.copy_coeffs(f1L);
|
||||
f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate, *params[param_f2_level]);
|
||||
f2R.copy_coeffs(f2L);
|
||||
@@ -1125,7 +1125,7 @@ void sidechaincompressor_audio_module::params_changed()
|
||||
case DERUMBLER_SPLIT:
|
||||
f1L.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate, *params[param_f1_level]);
|
||||
f1R.copy_coeffs(f1L);
|
||||
f2L.set_hp_rbj((float)*params[param_f2_freq] * (1 - 0.17), q, (float)srate);
|
||||
f2L.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate);
|
||||
f2R.copy_coeffs(f2L);
|
||||
f1_active = 1.f;
|
||||
f2_active = 0.f;
|
||||
@@ -1157,7 +1157,7 @@ void sidechaincompressor_audio_module::params_changed()
|
||||
case BANDPASS_1:
|
||||
f1L.set_bp_rbj((float)*params[param_f1_freq], q, (float)srate, *params[param_f1_level]);
|
||||
f1R.copy_coeffs(f1L);
|
||||
f2L.set_highshelf_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
|
||||
f2L.set_hp_rbj((float)*params[param_f2_freq], q, *params[param_f2_level], (float)srate);
|
||||
f2R.copy_coeffs(f2L);
|
||||
f1_active = 1.f;
|
||||
f2_active = 0.f;
|
||||
@@ -1410,6 +1410,222 @@ int sidechaincompressor_audio_module::get_changed_offsets(int index, int generat
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Deesser by Markus Schmidt
|
||||
///
|
||||
/// This module splits the signal in a sidechain- and a process signal.
|
||||
/// The sidechain is processed through Krzystofs filters and compresses
|
||||
/// the process signal via Thor's compression routine afterwards.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
deesser_audio_module::deesser_audio_module()
|
||||
{
|
||||
is_active = false;
|
||||
srate = 0;
|
||||
last_generation = 0;
|
||||
}
|
||||
|
||||
void deesser_audio_module::activate()
|
||||
{
|
||||
is_active = true;
|
||||
// set all filters and strips
|
||||
compressor.activate();
|
||||
params_changed();
|
||||
detected = 0.f;
|
||||
detected_led = 0.f;
|
||||
clip_out = 0.f;
|
||||
}
|
||||
void deesser_audio_module::deactivate()
|
||||
{
|
||||
is_active = false;
|
||||
compressor.deactivate();
|
||||
}
|
||||
|
||||
void deesser_audio_module::params_changed()
|
||||
{
|
||||
// set the params of all filters
|
||||
if(*params[param_f1_freq] != f1_freq_old or *params[param_f1_level] != f1_level_old
|
||||
or *params[param_f2_freq] != f2_freq_old or *params[param_f2_level] != f2_level_old
|
||||
or *params[param_f2_q] != f2_q_old) {
|
||||
float q = 0.707;
|
||||
|
||||
hpL.set_hp_rbj((float)*params[param_f1_freq] * (1 - 0.17), q, (float)srate, *params[param_f1_level]);
|
||||
hpR.copy_coeffs(hpL);
|
||||
lpL.set_lp_rbj((float)*params[param_f1_freq] * (1 + 0.17), q, (float)srate);
|
||||
lpR.copy_coeffs(lpL);
|
||||
pL.set_peakeq_rbj((float)*params[param_f2_freq], *params[param_f2_q], *params[param_f2_level], (float)srate);
|
||||
pR.copy_coeffs(pL);
|
||||
f1_freq_old = *params[param_f1_freq];
|
||||
f1_level_old = *params[param_f1_level];
|
||||
f2_freq_old = *params[param_f2_freq];
|
||||
f2_level_old = *params[param_f2_level];
|
||||
f2_q_old = *params[param_f2_q];
|
||||
}
|
||||
// and set the compressor module
|
||||
compressor.set_params((float)*params[param_laxity], (float)*params[param_laxity] * 1.33, *params[param_threshold], *params[param_ratio], 2.8, *params[param_makeup], *params[param_detection], 0.f, *params[param_bypass], 0.f);
|
||||
}
|
||||
|
||||
void deesser_audio_module::set_sample_rate(uint32_t sr)
|
||||
{
|
||||
srate = sr;
|
||||
compressor.set_sample_rate(srate);
|
||||
}
|
||||
|
||||
uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
|
||||
{
|
||||
bool bypass = *params[param_bypass] > 0.5f;
|
||||
numsamples += offset;
|
||||
if(bypass) {
|
||||
// everything bypassed
|
||||
while(offset < numsamples) {
|
||||
outs[0][offset] = ins[0][offset];
|
||||
outs[1][offset] = ins[1][offset];
|
||||
++offset;
|
||||
}
|
||||
// displays, too
|
||||
clip_out = 0.f;
|
||||
detected = 0.f;
|
||||
detected_led = 0.f;
|
||||
} else {
|
||||
// process
|
||||
|
||||
detected_led -= std::min(detected_led, numsamples);
|
||||
|
||||
while(offset < numsamples) {
|
||||
// cycle through samples
|
||||
float outL = 0.f;
|
||||
float outR = 0.f;
|
||||
float inL = ins[0][offset];
|
||||
float inR = ins[1][offset];
|
||||
|
||||
|
||||
float leftAC = inL;
|
||||
float rightAC = inR;
|
||||
float leftSC = inL;
|
||||
float rightSC = inR;
|
||||
float leftMC = inL;
|
||||
float rightMC = inR;
|
||||
|
||||
leftSC = pL.process(hpL.process(leftSC));
|
||||
rightSC = pR.process(hpR.process(rightSC));
|
||||
leftMC = leftSC;
|
||||
rightMC = rightSC;
|
||||
|
||||
switch ((int)*params[param_mode]) {
|
||||
default:
|
||||
case WIDE:
|
||||
compressor.process(leftAC, rightAC, leftSC, rightSC);
|
||||
break;
|
||||
case SPLIT:
|
||||
compressor.process(leftSC, rightSC, leftSC, rightSC);
|
||||
leftAC = lpL.process(leftAC);
|
||||
rightAC = lpR.process(rightAC);
|
||||
leftAC += leftSC;
|
||||
rightAC += rightSC;
|
||||
break;
|
||||
}
|
||||
|
||||
if(*params[param_sc_listen] > 0.f) {
|
||||
outL = leftMC;
|
||||
outR = rightMC;
|
||||
} else {
|
||||
outL = leftAC;
|
||||
outR = rightAC;
|
||||
}
|
||||
|
||||
// send to output
|
||||
outs[0][offset] = outL;
|
||||
outs[1][offset] = outR;
|
||||
|
||||
if(std::max(fabs(leftSC), fabs(rightSC)) > 0.1) {
|
||||
detected_led = srate >> 3;
|
||||
}
|
||||
clip_out = std::max(fabs(outL), fabs(outR));
|
||||
detected = std::max(fabs(leftMC), fabs(rightMC));
|
||||
|
||||
// next sample
|
||||
++offset;
|
||||
} // cycle trough samples
|
||||
hpL.sanitize();
|
||||
hpR.sanitize();
|
||||
lpL.sanitize();
|
||||
lpR.sanitize();
|
||||
pL.sanitize();
|
||||
pR.sanitize();
|
||||
}
|
||||
// draw meters
|
||||
if(params[param_detected_led] != NULL) {
|
||||
*params[param_detected_led] = detected_led;
|
||||
}
|
||||
if(params[param_clip_out] != NULL) {
|
||||
*params[param_clip_out] = clip_out;
|
||||
}
|
||||
if(params[param_detected] != NULL) {
|
||||
*params[param_detected] = detected;
|
||||
}
|
||||
// draw strip meter
|
||||
if(bypass > 0.5f) {
|
||||
if(params[param_compression] != NULL) {
|
||||
*params[param_compression] = 1.0f;
|
||||
}
|
||||
} else {
|
||||
if(params[param_compression] != NULL) {
|
||||
*params[param_compression] = compressor.get_comp_level();
|
||||
}
|
||||
}
|
||||
// whatever has to be returned x)
|
||||
return outputs_mask;
|
||||
}
|
||||
bool deesser_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
|
||||
{
|
||||
if (!is_active)
|
||||
return false;
|
||||
if (index == param_f1_freq && !subindex) {
|
||||
context->set_line_width(1.5);
|
||||
return ::get_graph(*this, subindex, data, points);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool deesser_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
|
||||
{
|
||||
return get_freq_gridline(subindex, pos, vertical, legend, context);
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
int deesser_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
|
||||
{
|
||||
if (!is_active) {
|
||||
return false;
|
||||
} else {
|
||||
// (fabs(inertia_cutoff.get_last() - old_cutoff) + 100 * fabs(inertia_resonance.get_last() - old_resonance) + fabs(*params[par_mode] - old_mode) > 0.1f)
|
||||
if (*params[param_f1_freq] != f1_freq_old1
|
||||
or *params[param_f2_freq] != f2_freq_old1
|
||||
or *params[param_f1_level] != f1_level_old1
|
||||
or *params[param_f2_level] != f2_level_old1
|
||||
or *params[param_f2_q] !=f2_q_old1)
|
||||
{
|
||||
f1_freq_old1 = *params[param_f1_freq];
|
||||
f2_freq_old1 = *params[param_f2_freq];
|
||||
f1_level_old1 = *params[param_f1_level];
|
||||
f2_level_old1 = *params[param_f2_level];
|
||||
f2_q_old1 = *params[param_f2_q];
|
||||
last_generation++;
|
||||
subindex_graph = 0;
|
||||
subindex_dot = INT_MAX;
|
||||
subindex_gridline = INT_MAX;
|
||||
}
|
||||
else {
|
||||
subindex_graph = 0;
|
||||
subindex_dot = subindex_gridline = generation ? INT_MAX : 0;
|
||||
}
|
||||
if (generation == last_calculated_generation)
|
||||
subindex_graph = INT_MAX;
|
||||
return last_generation;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Gain reduction module implemented by Markus Schmidt
|
||||
/// Nearly all functions of this module are originally written
|
||||
/// by Thor, while some features have been stripped (mainly stereo linking
|
||||
|
||||
Reference in New Issue
Block a user