Simplify Multiband Compressor code and fix several bugs.
Eliminated some (not all) repetition in the code. Fixed a bug where old value for Q and separation was taken from the wrong variable. Fixed a bug where having a band bypassed or muted caused the graph to stop redrawing properly. (cherry picked from commit 3be583385b0bfb69bb7e52ee7426fe27d515560c)
This commit is contained in:
committed by
Tobias Doerffel
parent
f8cb1120b0
commit
527a02d648
@@ -792,6 +792,7 @@ private:
|
||||
public:
|
||||
gain_reduction_audio_module();
|
||||
void set_params(float att, float rel, float thr, float rat, float kn, float mak, float det, float stl, float byp, float mu);
|
||||
void update_curve();
|
||||
void process(float &left, float &right, float det_left = NULL, float det_right = NULL);
|
||||
void activate();
|
||||
void deactivate();
|
||||
@@ -910,6 +911,7 @@ public:
|
||||
/// Multibandcompressor by Markus Schmidt
|
||||
class multibandcompressor_audio_module: public audio_module<multibandcompressor_metadata>, public line_graph_iface {
|
||||
private:
|
||||
typedef multibandcompressor_audio_module AM;
|
||||
static const int strips = 4;
|
||||
bool mute[strips];
|
||||
uint32_t clip_inL, clip_inR, clip_outL, clip_outR;
|
||||
@@ -929,6 +931,7 @@ public:
|
||||
void params_changed();
|
||||
uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
|
||||
void set_sample_rate(uint32_t sr);
|
||||
const gain_reduction_audio_module *get_strip_by_param_index(int index) const;
|
||||
virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
|
||||
virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const;
|
||||
virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
using namespace dsp;
|
||||
using namespace calf_plugins;
|
||||
|
||||
#define SET_IF_CONNECTED(name) if (params[AM::param_##name] != NULL) *params[AM::param_##name] = name;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool frequency_response_line_graph::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
|
||||
@@ -398,8 +400,8 @@ void multibandcompressor_audio_module::params_changed()
|
||||
hpL0.set_hp_rbj((float)(*params[param_freq0] * (1 + *params[param_sep0])), *params[param_q0], (float)srate);
|
||||
hpR0.copy_coeffs(hpL0);
|
||||
freq_old[0] = *params[param_freq0];
|
||||
sep_old[0] = *params[param_sep2];
|
||||
q_old[0] = *params[param_q2];
|
||||
sep_old[0] = *params[param_sep0];
|
||||
q_old[0] = *params[param_q0];
|
||||
}
|
||||
if(*params[param_freq1] != freq_old[1] or *params[param_sep1] != sep_old[1] or *params[param_q1] != q_old[1]) {
|
||||
lpL1.set_lp_rbj((float)(*params[param_freq1] * (1 - *params[param_sep1])), *params[param_q1], (float)srate);
|
||||
@@ -407,8 +409,8 @@ void multibandcompressor_audio_module::params_changed()
|
||||
hpL1.set_hp_rbj((float)(*params[param_freq1] * (1 + *params[param_sep1])), *params[param_q1], (float)srate);
|
||||
hpR1.copy_coeffs(hpL1);
|
||||
freq_old[1] = *params[param_freq1];
|
||||
sep_old[1] = *params[param_sep2];
|
||||
q_old[1] = *params[param_q2];
|
||||
sep_old[1] = *params[param_sep1];
|
||||
q_old[1] = *params[param_q1];
|
||||
}
|
||||
if(*params[param_freq2] != freq_old[2] or *params[param_sep2] != sep_old[2] or *params[param_q2] != q_old[2]) {
|
||||
lpL2.set_lp_rbj((float)(*params[param_freq2] * (1 - *params[param_sep2])), *params[param_q2], (float)srate);
|
||||
@@ -420,22 +422,10 @@ void multibandcompressor_audio_module::params_changed()
|
||||
q_old[2] = *params[param_q2];
|
||||
}
|
||||
// set the params of all strips
|
||||
for (int j = 0; j < strips; j ++) {
|
||||
switch (j) {
|
||||
case 0:
|
||||
strip[j].set_params(*params[param_attack0], *params[param_release0], *params[param_threshold0], *params[param_ratio0], *params[param_knee0], *params[param_makeup0], *params[param_detection0], 1.f, *params[param_bypass0], *params[param_mute0]);
|
||||
break;
|
||||
case 1:
|
||||
strip[j].set_params(*params[param_attack1], *params[param_release1], *params[param_threshold1], *params[param_ratio1], *params[param_knee1], *params[param_makeup1], *params[param_detection1], 1.f, *params[param_bypass1], *params[param_mute1]);
|
||||
break;
|
||||
case 2:
|
||||
strip[j].set_params(*params[param_attack2], *params[param_release2], *params[param_threshold2], *params[param_ratio2], *params[param_knee2], *params[param_makeup2], *params[param_detection2], 1.f, *params[param_bypass2], *params[param_mute2]);
|
||||
break;
|
||||
case 3:
|
||||
strip[j].set_params(*params[param_attack3], *params[param_release3], *params[param_threshold3], *params[param_ratio3], *params[param_knee3], *params[param_makeup3], *params[param_detection3], 1.f, *params[param_bypass3], *params[param_mute3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
strip[0].set_params(*params[param_attack0], *params[param_release0], *params[param_threshold0], *params[param_ratio0], *params[param_knee0], *params[param_makeup0], *params[param_detection0], 1.f, *params[param_bypass0], *params[param_mute0]);
|
||||
strip[1].set_params(*params[param_attack1], *params[param_release1], *params[param_threshold1], *params[param_ratio1], *params[param_knee1], *params[param_makeup1], *params[param_detection1], 1.f, *params[param_bypass1], *params[param_mute1]);
|
||||
strip[2].set_params(*params[param_attack2], *params[param_release2], *params[param_threshold2], *params[param_ratio2], *params[param_knee2], *params[param_makeup2], *params[param_detection2], 1.f, *params[param_bypass2], *params[param_mute2]);
|
||||
strip[3].set_params(*params[param_attack3], *params[param_release3], *params[param_threshold3], *params[param_ratio3], *params[param_knee3], *params[param_makeup3], *params[param_detection3], 1.f, *params[param_bypass3], *params[param_mute3]);
|
||||
}
|
||||
|
||||
void multibandcompressor_audio_module::set_sample_rate(uint32_t sr)
|
||||
@@ -447,10 +437,24 @@ void multibandcompressor_audio_module::set_sample_rate(uint32_t sr)
|
||||
}
|
||||
}
|
||||
|
||||
#define BYPASSED_COMPRESSION(index) \
|
||||
if(params[param_compression##index] != NULL) \
|
||||
*params[param_compression##index] = 1.0; \
|
||||
if(params[param_output##index] != NULL) \
|
||||
*params[param_output##index] = 0.0;
|
||||
|
||||
#define ACTIVE_COMPRESSION(index) \
|
||||
if(params[param_compression##index] != NULL) \
|
||||
*params[param_compression##index] = strip[index].get_comp_level(); \
|
||||
if(params[param_output##index] != NULL) \
|
||||
*params[param_output##index] = strip[index].get_output_level();
|
||||
|
||||
uint32_t multibandcompressor_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;
|
||||
for (int i = 0; i < strips; i++)
|
||||
strip[i].update_curve();
|
||||
if(bypass) {
|
||||
// everything bypassed
|
||||
while(offset < numsamples) {
|
||||
@@ -595,165 +599,75 @@ uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t num
|
||||
} // process all strips (no bypass)
|
||||
|
||||
// draw meters
|
||||
if(params[param_clip_inL] != NULL) {
|
||||
*params[param_clip_inL] = clip_inL;
|
||||
}
|
||||
if(params[param_clip_inR] != NULL) {
|
||||
*params[param_clip_inR] = clip_inR;
|
||||
}
|
||||
if(params[param_clip_outL] != NULL) {
|
||||
*params[param_clip_outL] = clip_outL;
|
||||
}
|
||||
if(params[param_clip_outR] != NULL) {
|
||||
*params[param_clip_outR] = clip_outR;
|
||||
}
|
||||
|
||||
if(params[param_meter_inL] != NULL) {
|
||||
*params[param_meter_inL] = meter_inL;
|
||||
}
|
||||
if(params[param_meter_inR] != NULL) {
|
||||
*params[param_meter_inR] = meter_inR;
|
||||
}
|
||||
if(params[param_meter_outL] != NULL) {
|
||||
*params[param_meter_outL] = meter_outL;
|
||||
}
|
||||
if(params[param_meter_outR] != NULL) {
|
||||
*params[param_meter_outR] = meter_outR;
|
||||
}
|
||||
SET_IF_CONNECTED(clip_inL);
|
||||
SET_IF_CONNECTED(clip_inR);
|
||||
SET_IF_CONNECTED(clip_outL);
|
||||
SET_IF_CONNECTED(clip_outR);
|
||||
SET_IF_CONNECTED(meter_inL);
|
||||
SET_IF_CONNECTED(meter_inR);
|
||||
SET_IF_CONNECTED(meter_outL);
|
||||
SET_IF_CONNECTED(meter_outR);
|
||||
// draw strip meters
|
||||
if(bypass > 0.5f) {
|
||||
if(params[param_compression0] != NULL) {
|
||||
*params[param_compression0] = 1.0f;
|
||||
}
|
||||
if(params[param_compression1] != NULL) {
|
||||
*params[param_compression1] = 1.0f;
|
||||
}
|
||||
if(params[param_compression2] != NULL) {
|
||||
*params[param_compression2] = 1.0f;
|
||||
}
|
||||
if(params[param_compression3] != NULL) {
|
||||
*params[param_compression3] = 1.0f;
|
||||
}
|
||||
|
||||
if(params[param_output0] != NULL) {
|
||||
*params[param_output0] = 0.0f;
|
||||
}
|
||||
if(params[param_output1] != NULL) {
|
||||
*params[param_output1] = 0.0f;
|
||||
}
|
||||
if(params[param_output2] != NULL) {
|
||||
*params[param_output2] = 0.0f;
|
||||
}
|
||||
if(params[param_output3] != NULL) {
|
||||
*params[param_output3] = 0.0f;
|
||||
}
|
||||
BYPASSED_COMPRESSION(0)
|
||||
BYPASSED_COMPRESSION(1)
|
||||
BYPASSED_COMPRESSION(2)
|
||||
BYPASSED_COMPRESSION(3)
|
||||
} else {
|
||||
if(params[param_compression0] != NULL) {
|
||||
*params[param_compression0] = strip[0].get_comp_level();
|
||||
}
|
||||
if(params[param_compression1] != NULL) {
|
||||
*params[param_compression1] = strip[1].get_comp_level();
|
||||
}
|
||||
if(params[param_compression2] != NULL) {
|
||||
*params[param_compression2] = strip[2].get_comp_level();
|
||||
}
|
||||
if(params[param_compression3] != NULL) {
|
||||
*params[param_compression3] = strip[3].get_comp_level();
|
||||
}
|
||||
|
||||
if(params[param_output0] != NULL) {
|
||||
*params[param_output0] = strip[0].get_output_level();
|
||||
}
|
||||
if(params[param_output1] != NULL) {
|
||||
*params[param_output1] = strip[1].get_output_level();
|
||||
}
|
||||
if(params[param_output2] != NULL) {
|
||||
*params[param_output2] = strip[2].get_output_level();
|
||||
}
|
||||
if(params[param_output3] != NULL) {
|
||||
*params[param_output3] = strip[3].get_output_level();
|
||||
}
|
||||
ACTIVE_COMPRESSION(0)
|
||||
ACTIVE_COMPRESSION(1)
|
||||
ACTIVE_COMPRESSION(2)
|
||||
ACTIVE_COMPRESSION(3)
|
||||
}
|
||||
// whatever has to be returned x)
|
||||
return outputs_mask;
|
||||
}
|
||||
bool multibandcompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
|
||||
|
||||
const gain_reduction_audio_module *multibandcompressor_audio_module::get_strip_by_param_index(int index) const
|
||||
{
|
||||
// let's handle by the corresponding strip
|
||||
switch (index) {
|
||||
case param_compression0:
|
||||
return strip[0].get_graph(subindex, data, points, context);
|
||||
break;
|
||||
return &strip[0];
|
||||
case param_compression1:
|
||||
return strip[1].get_graph(subindex, data, points, context);
|
||||
break;
|
||||
return &strip[1];
|
||||
case param_compression2:
|
||||
return strip[2].get_graph(subindex, data, points, context);
|
||||
break;
|
||||
return &strip[2];
|
||||
case param_compression3:
|
||||
return strip[3].get_graph(subindex, data, points, context);
|
||||
break;
|
||||
return &strip[3];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool multibandcompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
|
||||
{
|
||||
const gain_reduction_audio_module *m = get_strip_by_param_index(index);
|
||||
if (m)
|
||||
return m->get_graph(subindex, data, points, context);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool multibandcompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
|
||||
{
|
||||
// let's handle by the corresponding strip
|
||||
switch (index) {
|
||||
case param_compression0:
|
||||
return strip[0].get_dot(subindex, x, y, size, context);
|
||||
break;
|
||||
case param_compression1:
|
||||
return strip[1].get_dot(subindex, x, y, size, context);
|
||||
break;
|
||||
case param_compression2:
|
||||
return strip[2].get_dot(subindex, x, y, size, context);
|
||||
break;
|
||||
case param_compression3:
|
||||
return strip[3].get_dot(subindex, x, y, size, context);
|
||||
break;
|
||||
}
|
||||
const gain_reduction_audio_module *m = get_strip_by_param_index(index);
|
||||
if (m)
|
||||
return m->get_dot(subindex, x, y, size, context);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool multibandcompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
|
||||
{
|
||||
// let's handle by the corresponding strip
|
||||
switch (index) {
|
||||
case param_compression0:
|
||||
return strip[0].get_gridline(subindex, pos, vertical, legend, context);
|
||||
break;
|
||||
case param_compression1:
|
||||
return strip[1].get_gridline(subindex, pos, vertical, legend, context);
|
||||
break;
|
||||
case param_compression2:
|
||||
return strip[2].get_gridline(subindex, pos, vertical, legend, context);
|
||||
break;
|
||||
case param_compression3:
|
||||
return strip[3].get_gridline(subindex, pos, vertical, legend, context);
|
||||
break;
|
||||
}
|
||||
const gain_reduction_audio_module *m = get_strip_by_param_index(index);
|
||||
if (m)
|
||||
return m->get_gridline(subindex, pos, vertical, legend, context);
|
||||
return false;
|
||||
}
|
||||
|
||||
int multibandcompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const
|
||||
{
|
||||
// let's handle by the corresponding strip
|
||||
switch (index) {
|
||||
case param_compression0:
|
||||
return strip[0].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
|
||||
break;
|
||||
case param_compression1:
|
||||
return strip[1].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
|
||||
break;
|
||||
case param_compression2:
|
||||
return strip[2].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
|
||||
break;
|
||||
case param_compression3:
|
||||
return strip[3].get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
|
||||
break;
|
||||
}
|
||||
const gain_reduction_audio_module *m = get_strip_by_param_index(index);
|
||||
if (m)
|
||||
return m->get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1533,6 +1447,19 @@ void gain_reduction_audio_module::deactivate()
|
||||
is_active = false;
|
||||
}
|
||||
|
||||
void gain_reduction_audio_module::update_curve()
|
||||
{
|
||||
float linThreshold = threshold;
|
||||
float linKneeSqrt = sqrt(knee);
|
||||
linKneeStart = linThreshold / linKneeSqrt;
|
||||
adjKneeStart = linKneeStart*linKneeStart;
|
||||
float linKneeStop = linThreshold * linKneeSqrt;
|
||||
thres = log(linThreshold);
|
||||
kneeStart = log(linKneeStart);
|
||||
kneeStop = log(linKneeStop);
|
||||
compressedKneeStop = (kneeStop - thres) / ratio + thres;
|
||||
}
|
||||
|
||||
void gain_reduction_audio_module::process(float &left, float &right, float det_left, float det_right)
|
||||
{
|
||||
if(!det_left) {
|
||||
@@ -1547,17 +1474,9 @@ void gain_reduction_audio_module::process(float &left, float &right, float det_l
|
||||
// greatest sounding compressor I've heard!
|
||||
bool rms = detection == 0;
|
||||
bool average = stereo_link == 0;
|
||||
float linThreshold = threshold;
|
||||
float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
|
||||
float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
|
||||
float linKneeSqrt = sqrt(knee);
|
||||
linKneeStart = linThreshold / linKneeSqrt;
|
||||
adjKneeStart = linKneeStart*linKneeStart;
|
||||
float linKneeStop = linThreshold * linKneeSqrt;
|
||||
thres = log(linThreshold);
|
||||
kneeStart = log(linKneeStart);
|
||||
kneeStop = log(linKneeStop);
|
||||
compressedKneeStop = (kneeStop - thres) / ratio + thres;
|
||||
update_curve();
|
||||
|
||||
float absample = average ? (fabs(det_left) + fabs(det_right)) * 0.5f : std::max(fabs(det_left), fabs(det_right));
|
||||
if(rms) absample *= absample;
|
||||
@@ -1861,8 +1780,6 @@ inline void equalizerNband_audio_module<BaseClass, has_lphp>::process_hplp(float
|
||||
}
|
||||
}
|
||||
|
||||
#define SET_IF_CONNECTED(param) if (params[AM::param_##param] != NULL) *params[AM::param_##param] = param;
|
||||
|
||||
template<class BaseClass, bool has_lphp>
|
||||
uint32_t equalizerNband_audio_module<BaseClass, has_lphp>::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user