+ GUI, Multiband Compressor, Toggle button: apply more fixes and additions by Markus Schmidt

(cherry picked from commit 6717c99440d6bef04a16447145d8beb2b0b3f16e)
This commit is contained in:
Krzysztof Foltman
2009-10-10 00:10:12 +01:00
committed by Tobias Doerffel
parent 86212e2691
commit b89707c6da
4 changed files with 110 additions and 93 deletions

View File

@@ -190,6 +190,7 @@ struct line_graph_iface
virtual bool get_static_graph(int index, int subindex, float value, float *data, int points, cairo_iface *context) { return false; }
/// Return which graphs need to be redrawn and which can be cached for later reuse
/// @param index Parameter/graph number (usually tied to particular plugin control port)
/// @param generation 0 (at start) or the last value returned by the function (corresponds to a set of input values)
/// @param subindex_graph First graph that has to be redrawn (because it depends on values that might have changed)
/// @param subindex_dot First dot that has to be redrawn

View File

@@ -902,7 +902,7 @@ private:
float linSlope, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop;
float compressedKneeStop, adjKneeStart, thres;
float attack, release, threshold, ratio, knee, makeup, detection, bypass, mute, meter_out, meter_comp;
float old_threshold, old_ratio, old_knee, old_makeup, old_bypass;
float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_mute, old_detection;
int last_generation;
uint32_t srate;
bool is_active;
@@ -928,8 +928,6 @@ public:
class multibandcompressor_audio_module: public audio_module<multibandcompressor_metadata>, public line_graph_iface {
private:
static const int strips = 4;
float meter_out[strips];
float meter_comp[strips];
bool mute[strips];
uint32_t clip_inL, clip_inR, clip_outL, clip_outR;
float meter_inL, meter_inR, meter_outL, meter_outR;
@@ -954,7 +952,6 @@ public:
virtual int get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline);
};
/// Filterclavier --- MIDI controlled filter by Hans Baier
class filterclavier_audio_module:
public audio_module<filterclavier_metadata>,

View File

@@ -239,20 +239,20 @@ CALF_PORT_NAMES(multibandcompressor) = {"In L", "In R", "Out L", "Out R"};
const char *multibandcompressor_detection_names[] = { "RMS", "Peak" };
CALF_PORT_PROPS(multibandcompressor) = {
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
{ 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
{ 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" },
{ 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, "meter_inL", "Input L" },
{ 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, "meter_inR", "Input R" },
{ 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, "meter_outL", "Output L" },
{ 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, "meter_outR", "Output R" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
{ 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_in", "Input" },
{ 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Output" },
{ 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, "meter_inL", "Input L" },
{ 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, "meter_inR", "Input R" },
{ 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, "meter_outL", "Output L" },
{ 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, "meter_outR", "Output R" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB" },
{ 120, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" },
{ 1200, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" },
{ 100, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" },
{ 1000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" },
{ 6000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Split 3/4" },
{ -0.17, -0.5, 0.5, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S" },
@@ -316,7 +316,9 @@ CALF_PORT_PROPS(multibandcompressor) = {
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute3", "Mute" },
};
CALF_PLUGIN_INFO(multibandcompressor) = { 0x8502, "MultibandCompressor", "Calf Multiband Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
CALF_PLUGIN_INFO(multibandcompressor) = { 0x8502, "Multibandcompressor", "Calf Multiband Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

View File

@@ -519,9 +519,12 @@ uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples,
bool bypass = *params[param_bypass] > 0.5f;
if(bypass) {
int count = numsamples * sizeof(float);
memcpy(outs[0], ins[0], count);
memcpy(outs[1], ins[1], count);
numsamples += offset;
while(offset < numsamples) {
outs[0][offset] = ins[0][offset];
outs[1][offset] = ins[1][offset];
++offset;
}
if(params[param_compression] != NULL) {
*params[param_compression] = 1.f;
@@ -637,14 +640,21 @@ uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples,
return inputs_mask;
}
/// Multibandcompressor by Markus Schmidt
///
/// This module splits the signal in four different bands
/// and sends them through multiple filters (implemented by
/// Krzysztof). They are processed by a compressing routine
/// (implemented by Thor) afterwards and summed up to the
/// final output again.
///////////////////////////////////////////////////////////////////////////////////////////////
multibandcompressor_audio_module::multibandcompressor_audio_module()
{
is_active = false;
srate = 0;
// zero all dsplays
// zero all displays
clip_inL = 0.f;
clip_inR = 0.f;
clip_outL = 0.f;
@@ -768,16 +778,13 @@ uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t num
clip_inR -= std::min(clip_inR, numsamples);
clip_outL -= std::min(clip_outL, numsamples);
clip_outR -= std::min(clip_outR, numsamples);
meter_inL -= meter_inL * 5.f * numsamples / srate;
meter_inR -= meter_inR * 5.f * numsamples / srate;
meter_outL -= meter_outL * 5.f * numsamples / srate;
meter_outR -= meter_outR * 5.f * numsamples / srate;
for(int k = 0; k < strips; k ++) {
meter_out[k] -= meter_out[k] * 5.f * numsamples / srate;
}
meter_inL -= meter_inL * 2.5 * numsamples / srate;
meter_inR -= meter_inR * 2.5 * numsamples / srate;
meter_outL -= meter_outL * 2.5 * numsamples / srate;
meter_outR -= meter_outR * 2.5 * numsamples / srate;
while(offset < numsamples) {
// cycle trough samples
// cycle through samples
float inL = ins[0][offset];
float inR = ins[1][offset];
// in level
@@ -841,7 +848,7 @@ uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t num
} // process single strip
// even out filters gain reduction
// 3dB - levelled manually (based on sep and q settings)
// 3dB - levelled manually (based on default sep and q settings)
outL *= 1.414213562;
outR *= 1.414213562;
@@ -866,22 +873,21 @@ uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t num
if(outR > 1.f) {
clip_outR = srate >> 3;
}
// in / out meters
if(meter_inL < inL) {
// rise up in / out meters
if(inL > meter_inL) {
meter_inL = inL;
}
if(meter_inR < inR) {
if(inR > meter_inR) {
meter_inR = inR;
}
if(meter_outL < outL) {
if(outL > meter_outL) {
meter_outL = outL;
}
if(meter_outR < outR) {
if(outR > meter_outR) {
meter_outR = outR;
}
// next sample
++offset;
// printf("inL: %+7.4f inR: %+7.4f outL: %+7.4f outR: %+7.4f input: %+7.4f output: %+7.4f\n", inL, inR, outL, outR, *params[param_level_in], *params[param_level_out]);
} // cycle trough samples
} // process all strips (no bypass)
@@ -970,8 +976,8 @@ uint32_t multibandcompressor_audio_module::process(uint32_t offset, uint32_t num
return outputs_mask;
}
bool multibandcompressor_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
{
// printf("get_graph : %i\n", index);
{
// let's handle by the corresponding strip
switch (index) {
case param_compression0:
return strip[0].get_graph(subindex, data, points, context);
@@ -991,7 +997,7 @@ bool multibandcompressor_audio_module::get_graph(int index, int subindex, float
bool multibandcompressor_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context)
{
// printf("get_dot : %i\n", index);
// let's handle by the corresponding strip
switch (index) {
case param_compression0:
return strip[0].get_dot(subindex, x, y, size, context);
@@ -1011,7 +1017,7 @@ bool multibandcompressor_audio_module::get_dot(int index, int subindex, float &x
bool multibandcompressor_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context)
{
// printf("get_gridline: %i\n", index);
// let's handle by the corresponding strip
switch (index) {
case param_compression0:
return strip[0].get_gridline(subindex, pos, vertical, legend, context);
@@ -1030,8 +1036,8 @@ bool multibandcompressor_audio_module::get_gridline(int index, int subindex, flo
}
int multibandcompressor_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline)
{
// printf("get_changed : %i\n", index);
{
// 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);
@@ -1048,7 +1054,11 @@ int multibandcompressor_audio_module::get_changed_offsets(int index, int generat
}
return 0;
}
/// Gain reduction module by Markus Schmidt
/// 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
/// and frequency correction as implemented in his Compressor above)
/// To save some CPU.
////////////////////////////////////////////////////////////////////////////////
gain_reduction_audio_module::gain_reduction_audio_module()
{
@@ -1059,10 +1069,11 @@ gain_reduction_audio_module::gain_reduction_audio_module()
void gain_reduction_audio_module::activate()
{
is_active = true;
linSlope = 0.f;
meter_out = 0.f;
meter_comp = 0.f;
linSlope = 0.f;
meter_out = 0.f;
meter_comp = 1.f;
float l, r;
l = r = 0.f;
float byp = bypass;
bypass = 0.0;
process(l, r);
@@ -1076,52 +1087,50 @@ void gain_reduction_audio_module::deactivate()
void gain_reduction_audio_module::process(float &left, float &right)
{
if(bypass > 0.5f) {
meter_comp = 1.f;
meter_out = 0.f;
return;
}
// this routine is mainly copied from thor's compressor module
// greatest sounding compressor I've heard!
bool rms = detection == 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;
float compression = 1.f;
float absample = (fabs(left) + fabs(right)) * 0.5f;
if(rms) absample *= absample;
meter_out -= meter_out * 5.f * 1 / srate;
linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
float gain = 1.f;
if(bypass < 0.5f) {
// this routine is mainly copied from thor's compressor module
// greatest sounding compressor I've heard!
bool rms = detection == 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;
float absample = (fabs(left) + fabs(right)) * 0.5f;
if(rms) absample *= absample;
linSlope += (absample - linSlope) * (absample > linSlope ? attack_coeff : release_coeff);
float gain = 1.f;
if(linSlope > 0.f) {
gain = output_gain(linSlope, rms);
if(linSlope > 0.f) {
gain = output_gain(linSlope, rms);
}
compression = gain;
gain *= makeup;
left *= gain;
right *= gain;
detected = rms ? sqrt(linSlope) : linSlope;
}
compression = gain;
gain *= makeup;
left *= gain;
right *= gain;
float maxLR = std::max(fabs(left), fabs(right));
if(maxLR > meter_out) {
meter_out = maxLR;
}
meter_comp = compression;
detected = rms ? sqrt(linSlope) : linSlope;
}
float gain_reduction_audio_module::output_level(float slope) {
@@ -1170,8 +1179,7 @@ void gain_reduction_audio_module::set_params(float att, float rel, float thr, fl
detection = det;
bypass = byp;
mute = mu;
// if bypass, zero meters
if(bypass > 0.5 or mute > 0.f) {
if(mute > 0.f) {
meter_out = 0.f;
meter_comp = 1.f;
}
@@ -1194,17 +1202,18 @@ bool gain_reduction_audio_module::get_graph(int subindex, float *data, int point
for (int i = 0; i < points; i++)
{
float input = dB_grid_inv(-1.0 + i * 2.0 / (points - 1));
float output = output_level(input);
if (subindex == 0)
data[i] = dB_grid(input);
else
data[i] = dB_grid(output);
else {
float output = output_level(input);
data[i] = dB_grid(output);
}
}
if (subindex == (bypass > 0.5f ? 1 : 0))
if (subindex == (bypass > 0.5f ? 1 : 0) or mute > 0.1f)
context->set_source_rgba(0.35, 0.4, 0.2, 0.3);
else {
context->set_source_rgba(0.35, 0.4, 0.2, 1);
context->set_line_width(2);
context->set_line_width(1.5);
}
return true;
}
@@ -1215,9 +1224,15 @@ bool gain_reduction_audio_module::get_dot(int subindex, float &x, float &y, int
return false;
if (!subindex)
{
x = 0.5 + 0.5 * dB_grid(detected);
y = dB_grid(bypass > 0.5f ? detected : output_level(detected));
return bypass > 0.5f ? false : true;
if(bypass > 0.5f or mute > 0.f) {
return false;
} else {
bool rms = detection == 0;
float det = rms ? sqrt(detected) : detected;
x = 0.5 + 0.5 * dB_grid(det);
y = dB_grid(bypass > 0.5f or mute > 0.f ? det : output_level(det));
return true;
}
}
return false;
}
@@ -1247,13 +1262,15 @@ int gain_reduction_audio_module::get_changed_offsets(int generation, int &subind
subindex_dot = 0;
subindex_gridline = generation ? INT_MAX : 0;
if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs(makeup - old_makeup) + fabs(bypass - old_bypass) > 0.01f)
if (fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs(makeup - old_makeup) + fabs(detection - old_detection) + fabs(bypass - old_bypass) + fabs(mute - old_mute) > 0.000001f)
{
old_threshold = threshold;
old_ratio = ratio;
old_knee = knee;
old_makeup = makeup;
old_bypass = bypass;
old_ratio = ratio;
old_knee = knee;
old_makeup = makeup;
old_detection = detection;
old_bypass = bypass;
old_mute = mute;
last_generation++;
}