From 9845de9d944731c43febd6645fafca8672c8c367 Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Sat, 28 Aug 2010 09:56:32 +0100 Subject: [PATCH 1/4] Initialise old-state variables to prevent "stuck" graphs. (cherry picked from commit 2a795084ee9e73712a4b690b84158cc745ff1d30) --- plugins/ladspa_effect/calf/src/modules_comp.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/ladspa_effect/calf/src/modules_comp.cpp b/plugins/ladspa_effect/calf/src/modules_comp.cpp index 15f96a8bb..c42a05470 100644 --- a/plugins/ladspa_effect/calf/src/modules_comp.cpp +++ b/plugins/ladspa_effect/calf/src/modules_comp.cpp @@ -1277,6 +1277,11 @@ sidechaingate_audio_module::sidechaingate_audio_module() is_active = false; srate = 0; last_generation = 0; + + f1_freq_old = f2_freq_old = f1_level_old = f2_level_old = 0; + f1_freq_old1 = f2_freq_old1 = f1_level_old1 = f2_level_old1 = 0; + sc_mode_old = sc_mode_old1 = WIDEBAND; // doesn't matter as long as it's sane + } void sidechaingate_audio_module::activate() @@ -1889,6 +1894,17 @@ expander_audio_module::expander_audio_module() is_active = false; srate = 0; last_generation = 0; + + old_range = 0.f; + old_threshold = 0.f; + old_ratio = 0.f; + old_knee = 0.f; + old_makeup = 0.f; + old_detection = 0.f; + old_bypass = 0.f; + old_mute = 0.f; + old_trigger = 0.f; + old_stereo_link = 0.f; } void expander_audio_module::activate() From 017e382b35f2f88ae0c9fc26d25add7249477fa0 Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Sat, 28 Aug 2010 10:15:07 +0100 Subject: [PATCH 2/4] More variable initialisation. (cherry picked from commit 40bbe048f27fc7190001383f93097127119ee667) --- plugins/ladspa_effect/calf/src/modules_comp.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/plugins/ladspa_effect/calf/src/modules_comp.cpp b/plugins/ladspa_effect/calf/src/modules_comp.cpp index c42a05470..a1240e45e 100644 --- a/plugins/ladspa_effect/calf/src/modules_comp.cpp +++ b/plugins/ladspa_effect/calf/src/modules_comp.cpp @@ -512,6 +512,11 @@ sidechaincompressor_audio_module::sidechaincompressor_audio_module() is_active = false; srate = 0; last_generation = 0; + f1_freq_old1 = 0.f; + f2_freq_old1 = 0.f; + f1_level_old1 = 0.f; + f2_level_old1 = 0.f; + sc_mode_old1 = WIDEBAND; } void sidechaincompressor_audio_module::activate() @@ -899,6 +904,11 @@ deesser_audio_module::deesser_audio_module() is_active = false; srate = 0; last_generation = 0; + f1_freq_old1 = 0.f; + f2_freq_old1 = 0.f; + f1_level_old1 = 0.f; + f2_level_old1 = 0.f; + f2_q_old1 = 0.f; } void deesser_audio_module::activate() @@ -1668,6 +1678,13 @@ gain_reduction_audio_module::gain_reduction_audio_module() is_active = false; srate = 0; last_generation = 0; + old_threshold = 0.f; + old_ratio = 0.f; + old_knee = 0.f; + old_makeup = 0.f; + old_detection = 0.f; + old_bypass = 0.f; + old_mute = 0.f; } void gain_reduction_audio_module::activate() From d22dbc7d70a0365c09084ad923b2db30ff60dbdb Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Sun, 29 Aug 2010 23:31:22 +0100 Subject: [PATCH 3/4] Refactor metering code out of distortion plugins. (cherry picked from commit 84d873861da7b4ad205061b00fcc9f73c47140b6) --- plugins/ladspa_effect/calf/src/calf/modules.h | 1 - .../calf/src/calf/modules_dist.h | 13 +- .../calf/src/calf/plugin_tools.h | 80 +++++++++ plugins/ladspa_effect/calf/src/calf/vumeter.h | 95 ++++++++++ .../ladspa_effect/calf/src/modules_dist.cpp | 165 +++--------------- 5 files changed, 207 insertions(+), 147 deletions(-) create mode 100644 plugins/ladspa_effect/calf/src/calf/plugin_tools.h create mode 100644 plugins/ladspa_effect/calf/src/calf/vumeter.h diff --git a/plugins/ladspa_effect/calf/src/calf/modules.h b/plugins/ladspa_effect/calf/src/calf/modules.h index d20421879..b9395c68d 100644 --- a/plugins/ladspa_effect/calf/src/calf/modules.h +++ b/plugins/ladspa_effect/calf/src/calf/modules.h @@ -29,7 +29,6 @@ #include "giface.h" #include "metadata.h" #include "loudness.h" -#include "primitives.h" namespace calf_plugins { diff --git a/plugins/ladspa_effect/calf/src/calf/modules_dist.h b/plugins/ladspa_effect/calf/src/calf/modules_dist.h index 6c49c372d..d7be7dd79 100644 --- a/plugins/ladspa_effect/calf/src/calf/modules_dist.h +++ b/plugins/ladspa_effect/calf/src/calf/modules_dist.h @@ -28,6 +28,7 @@ #include "audio_fx.h" #include "giface.h" #include "metadata.h" +#include "plugin_tools.h" namespace calf_plugins { @@ -37,8 +38,8 @@ private: float hp_pre_freq_old, lp_pre_freq_old; float hp_post_freq_old, lp_post_freq_old; float p_level_old, p_freq_old, p_q_old; - uint32_t clip_in, clip_out; - float meter_in, meter_out, meter_drive; + stereo_in_out_metering meters; + float meter_drive; dsp::biquad_d2 lp[2][4], hp[2][4]; dsp::biquad_d2 p[2]; dsp::tap_distortion dist[2]; @@ -57,8 +58,8 @@ public: class exciter_audio_module: public audio_module { private: float freq_old; - uint32_t clip_in, clip_out; - float meter_in, meter_out, meter_drive; + stereo_in_out_metering meters; + float meter_drive; dsp::biquad_d2 hp[2][4]; dsp::tap_distortion dist[2]; public: @@ -76,8 +77,8 @@ public: class bassenhancer_audio_module: public audio_module { private: float freq_old; - uint32_t clip_in, clip_out; - float meter_in, meter_out, meter_drive; + stereo_in_out_metering meters; + float meter_drive; dsp::biquad_d2 lp[2][4]; dsp::tap_distortion dist[2]; public: diff --git a/plugins/ladspa_effect/calf/src/calf/plugin_tools.h b/plugins/ladspa_effect/calf/src/calf/plugin_tools.h new file mode 100644 index 000000000..aad5cdf6b --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/plugin_tools.h @@ -0,0 +1,80 @@ +/* Calf DSP plugin pack + * Tools to use in plugins + * + * Copyright (C) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#ifndef CALF_PLUGIN_TOOLS_H +#define CALF_PLUGIN_TOOLS_H + +#include + +#include "giface.h" +#include "vumeter.h" + +namespace calf_plugins { + +/// Base class for universal stereo level metering +struct stereo_in_out_metering_base +{ + dsp::vumeter vumeter_in, vumeter_out; + + stereo_in_out_metering_base() + { + reset(); + } + void reset() + { + vumeter_in.reset(); + vumeter_out.reset(); + } +}; + +/// Universal stereo level metering for a specific plugin +template +class stereo_in_out_metering: public stereo_in_out_metering_base +{ +public: + inline void process(float *const *params, const float *const *inputs, const float *const *outputs, unsigned int offset, unsigned int nsamples) + { + if (params[Metadata::param_meter_in] || params[Metadata::param_clip_in]) { + if (inputs) + vumeter_in.update_stereo(inputs[0] ? inputs[0] + offset : NULL, inputs[1] ? inputs[1] + offset : NULL, nsamples); + else + vumeter_in.update_zeros(nsamples); + if (params[Metadata::param_meter_in]) + *params[Metadata::param_meter_in] = vumeter_in.level; + if (params[Metadata::param_clip_in]) + *params[Metadata::param_clip_in] = vumeter_in.clip > 0 ? 1.f : 0.f; + } + if (params[Metadata::param_meter_out] || params[Metadata::param_clip_out]) { + if (outputs) + vumeter_out.update_stereo(outputs[0] ? outputs[0] + offset : NULL, outputs[1] ? outputs[1] + offset : NULL, nsamples); + else + vumeter_out.update_zeros(nsamples); + if (params[Metadata::param_meter_out]) + *params[Metadata::param_meter_out] = vumeter_out.level; + if (params[Metadata::param_clip_out]) + *params[Metadata::param_clip_out] = vumeter_out.clip > 0 ? 1.f : 0.f; + } + } +}; + +}; + +#endif + diff --git a/plugins/ladspa_effect/calf/src/calf/vumeter.h b/plugins/ladspa_effect/calf/src/calf/vumeter.h new file mode 100644 index 000000000..6ef1e7622 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/vumeter.h @@ -0,0 +1,95 @@ +/* Calf DSP Library + * Peak metering facilities. + * + * Copyright (C) 2007 Krzysztof Foltman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef __CALF_VUMETER_H +#define __CALF_VUMETER_H + +namespace dsp { + +/// Peak meter class +struct vumeter +{ + /// Measured signal level + float level; + /// Falloff of signal level (b1 coefficient of a 1-pole filter) + float falloff; + /// Clip indicator (set to 1 when |value| >= 1, fading otherwise) + float clip; + /// Falloff of clip indicator (b1 coefficient of a 1-pole filter); set to 1 if no falloff is required (manual reset of clip indicator) + float clip_falloff; + + vumeter() + { + falloff = 0.999f; + clip_falloff = 0.999f; + reset(); + } + + void reset() + { + level = 0; + clip = 0; + } + + /// Update peak meter based on input signal + inline void update(const float *src, unsigned int len) + { + update_stereo(src, NULL, len); + } + /// Update peak meter based on louder of two input signals + inline void update_stereo(const float *src1, const float *src2, unsigned int len) + { + // "Age" the old level by falloff^length + level *= pow(falloff, len); + // Same for clip level (using different fade constant) + clip *= pow(clip_falloff, len); + dsp::sanitize(level); + dsp::sanitize(clip); + // Process input samples - to get peak value, take a max of all values in the input signal and "aged" old peak + // Clip is set to 1 if any sample is out-of-range, if no clip occurs, the "aged" value is assumed + if (src1) + run_sample_loop(src1, len); + if (src2) + run_sample_loop(src2, len); + } + inline void run_sample_loop(const float *src, unsigned int len) + { + float tmp = level; + for (unsigned int i = 0; i < len; i++) { + float sig = fabs(src[i]); + tmp = std::max(tmp, sig); + if (sig >= 1.f) + clip = 1.f; + } + level = tmp; + } + /// Update clip meter as if update was called with all-zero input signal + inline void update_zeros(unsigned int len) + { + level *= pow((double)falloff, (double)len); + clip *= pow((double)clip_falloff, (double)len); + dsp::sanitize(level); + dsp::sanitize(clip); + } +}; + +}; + +#endif diff --git a/plugins/ladspa_effect/calf/src/modules_dist.cpp b/plugins/ladspa_effect/calf/src/modules_dist.cpp index aba40fc74..1592e3267 100644 --- a/plugins/ladspa_effect/calf/src/modules_dist.cpp +++ b/plugins/ladspa_effect/calf/src/modules_dist.cpp @@ -38,10 +38,6 @@ saturator_audio_module::saturator_audio_module() { is_active = false; srate = 0; - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; meter_drive = 0.f; } @@ -50,6 +46,8 @@ void saturator_audio_module::activate() is_active = true; // set all filters params_changed(); + meters.reset(); + meter_drive = 0.f; } void saturator_audio_module::deactivate() { @@ -120,6 +118,8 @@ void saturator_audio_module::set_sample_rate(uint32_t sr) uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { bool bypass = *params[param_bypass] > 0.5f; + uint32_t orig_offset = offset; + uint32_t orig_numsamples = numsamples; numsamples += offset; if(bypass) { // everything bypassed @@ -137,18 +137,9 @@ uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, u } ++offset; } - // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; - meter_drive = 0.f; + meters.reset(); + meters.process(params, NULL, NULL, 0, 0); } else { - - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); - meter_in = 0.f; - meter_out = 0.f; meter_drive = 0.f; float in_avg[2] = {0.f, 0.f}; float out_avg[2] = {0.f, 0.f}; @@ -157,7 +148,6 @@ uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, u while(offset < numsamples) { // cycle through samples float out[2], in[2] = {0.f, 0.f}; - float maxIn, maxOut = 0.f; int c = 0; if(in_count > 1 && out_count > 1) { @@ -178,6 +168,8 @@ uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, u proc[0] = in[0] * *params[param_level_in]; proc[1] = in[1] * *params[param_level_in]; + float onedivlevelin = 1.0 / *params[param_level_in]; + for (int i = 0; i < c; ++i) { // all pre filters in chain proc[i] = lp[i][1].process(lp[i][0].process(proc[i])); @@ -200,7 +192,7 @@ uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, u proc[i] = hp[i][2].process(hp[i][3].process(proc[i])); //subtract gain - proc[i] /= *params[param_level_in]; + proc[i] *= onedivlevelin; } if(in_count > 1 && out_count > 1) { @@ -209,42 +201,23 @@ uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, u outs[0][offset] = out[0]; out[1] = ((proc[1] * *params[param_mix]) + in[1] * (1 - *params[param_mix])) * *params[param_level_out]; outs[1][offset] = out[1]; - maxIn = std::max(fabs(in[0]), fabs(in[1])); - maxOut = std::max(fabs(out[0]), fabs(out[1])); } else if(out_count > 1) { // mono -> pseudo stereo out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out]; outs[0][offset] = out[0]; out[1] = out[0]; outs[1][offset] = out[1]; - maxOut = fabs(out[0]); - maxIn = fabs(in[0]); } else { // stereo -> mono // or full mono out[0] = ((proc[0] * *params[param_mix]) + in[0] * (1 - *params[param_mix])) * *params[param_level_out]; outs[0][offset] = out[0]; - maxIn = fabs(in[0]); - maxOut = fabs(out[0]); } - - if(maxIn > 1.f) { - clip_in = srate >> 3; - } - if(maxOut > 1.f) { - clip_out = srate >> 3; - } - // set up in / out meters - if(maxIn > meter_in) { - meter_in = maxIn; - } - if(maxOut > meter_out) { - meter_out = maxOut; - } - + // next sample ++offset; } // cycle trough samples + meters.process(params, ins, outs, orig_offset, orig_numsamples); tube_avg = (sqrt(std::max(out_avg[0], out_avg[1])) / numsamples) - (sqrt(std::max(in_avg[0], in_avg[1])) / numsamples); meter_drive = (5.0f * fabs(tube_avg) * (float(*params[param_blend]) + 30.0f)); @@ -270,19 +243,6 @@ uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, u p[1].sanitize(); } // draw meters - if(params[param_clip_in] != NULL) { - *params[param_clip_in] = clip_in; - } - if(params[param_clip_out] != NULL) { - *params[param_clip_out] = clip_out; - } - - if(params[param_meter_in] != NULL) { - *params[param_meter_in] = meter_in; - } - if(params[param_meter_out] != NULL) { - *params[param_meter_out] = meter_out; - } if(params[param_meter_drive] != NULL) { *params[param_meter_drive] = meter_drive; } @@ -300,10 +260,6 @@ exciter_audio_module::exciter_audio_module() { is_active = false; srate = 0; - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; meter_drive = 0.f; } @@ -351,6 +307,8 @@ void exciter_audio_module::set_sample_rate(uint32_t sr) uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { + uint32_t orig_offset = offset; + uint32_t orig_numsamples = numsamples; bool bypass = *params[param_bypass] > 0.5f; numsamples += offset; if(bypass) { @@ -369,25 +327,19 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin } ++offset; } + meters.reset(); + meters.process(params, NULL, NULL, 0, 0); // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; meter_drive = 0.f; } else { - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); - meter_in = 0.f; - meter_out = 0.f; meter_drive = 0.f; // process while(offset < numsamples) { // cycle through samples float out[2], in[2] = {0.f, 0.f}; - float maxIn, maxOut, maxDrive = 0.f; + float maxDrive = 0.f; int c = 0; if(in_count > 1 && out_count > 1) { @@ -434,8 +386,6 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin else out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out]; outs[1][offset] = out[1]; - maxIn = std::max(fabs(in[0]), fabs(in[1])); - maxOut = std::max(fabs(out[0]), fabs(out[1])); maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount], dist[1].get_distortion_level() * *params[param_amount]); } else if(out_count > 1) { @@ -447,8 +397,6 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin outs[0][offset] = out[0]; out[1] = out[0]; outs[1][offset] = out[1]; - maxOut = fabs(out[0]); - maxIn = fabs(in[0]); maxDrive = dist[0].get_distortion_level() * *params[param_amount]; } else { // stereo -> mono @@ -458,24 +406,10 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin else out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; outs[0][offset] = out[0]; - maxIn = fabs(in[0]); - maxOut = fabs(out[0]); maxDrive = dist[0].get_distortion_level() * *params[param_amount]; } - if(maxIn > 1.f) { - clip_in = srate >> 3; - } - if(maxOut > 1.f) { - clip_out = srate >> 3; - } // set up in / out meters - if(maxIn > meter_in) { - meter_in = maxIn; - } - if(maxOut > meter_out) { - meter_out = maxOut; - } if(maxDrive > meter_drive) { meter_drive = maxDrive; } @@ -483,6 +417,7 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin // next sample ++offset; } // cycle trough samples + meters.process(params, ins, outs, orig_offset, orig_numsamples); // clean up hp[0][0].sanitize(); hp[1][0].sanitize(); @@ -494,19 +429,6 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin hp[1][3].sanitize(); } // draw meters - if(params[param_clip_in] != NULL) { - *params[param_clip_in] = clip_in; - } - if(params[param_clip_out] != NULL) { - *params[param_clip_out] = clip_out; - } - - if(params[param_meter_in] != NULL) { - *params[param_meter_in] = meter_in; - } - if(params[param_meter_out] != NULL) { - *params[param_meter_out] = meter_out; - } if(params[param_meter_drive] != NULL) { *params[param_meter_drive] = meter_drive; } @@ -524,16 +446,14 @@ bassenhancer_audio_module::bassenhancer_audio_module() { is_active = false; srate = 0; - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; + meters.reset(); meter_drive = 0.f; } void bassenhancer_audio_module::activate() { is_active = true; + meters.reset(); // set all filters params_changed(); } @@ -575,6 +495,8 @@ void bassenhancer_audio_module::set_sample_rate(uint32_t sr) uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { bool bypass = *params[param_bypass] > 0.5f; + uint32_t orig_offset = offset; + uint32_t orig_numsamples = numsamples; numsamples += offset; if(bypass) { // everything bypassed @@ -593,24 +515,17 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples ++offset; } // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; + meters.reset(); + meters.process(params, NULL, NULL, 0, 0); meter_drive = 0.f; } else { - - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); - meter_in = 0.f; - meter_out = 0.f; meter_drive = 0.f; // process while(offset < numsamples) { // cycle through samples float out[2], in[2] = {0.f, 0.f}; - float maxIn, maxOut, maxDrive = 0.f; + float maxDrive = 0.f; int c = 0; if(in_count > 1 && out_count > 1) { @@ -657,8 +572,6 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples else out[1] = (proc[1] * *params[param_amount] + in[1]) * *params[param_level_out]; outs[1][offset] = out[1]; - maxIn = std::max(fabs(in[0]), fabs(in[1])); - maxOut = std::max(fabs(out[0]), fabs(out[1])); maxDrive = std::max(dist[0].get_distortion_level() * *params[param_amount], dist[1].get_distortion_level() * *params[param_amount]); } else if(out_count > 1) { @@ -670,8 +583,6 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples outs[0][offset] = out[0]; out[1] = out[0]; outs[1][offset] = out[1]; - maxOut = fabs(out[0]); - maxIn = fabs(in[0]); maxDrive = dist[0].get_distortion_level() * *params[param_amount]; } else { // stereo -> mono @@ -681,24 +592,10 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples else out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out]; outs[0][offset] = out[0]; - maxIn = fabs(in[0]); - maxOut = fabs(out[0]); maxDrive = dist[0].get_distortion_level() * *params[param_amount]; } - if(maxIn > 1.f) { - clip_in = srate >> 3; - } - if(maxOut > 1.f) { - clip_out = srate >> 3; - } // set up in / out meters - if(maxIn > meter_in) { - meter_in = maxIn; - } - if(maxOut > meter_out) { - meter_out = maxOut; - } if(maxDrive > meter_drive) { meter_drive = maxDrive; } @@ -706,6 +603,7 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples // next sample ++offset; } // cycle trough samples + meters.process(params, ins, outs, orig_offset, orig_numsamples); // clean up lp[0][0].sanitize(); lp[1][0].sanitize(); @@ -717,19 +615,6 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples lp[1][3].sanitize(); } // draw meters - if(params[param_clip_in] != NULL) { - *params[param_clip_in] = clip_in; - } - if(params[param_clip_out] != NULL) { - *params[param_clip_out] = clip_out; - } - - if(params[param_meter_in] != NULL) { - *params[param_meter_in] = meter_in; - } - if(params[param_meter_out] != NULL) { - *params[param_meter_out] = meter_out; - } if(params[param_meter_drive] != NULL) { *params[param_meter_drive] = meter_drive; } From 1d759dc23925bbdd4cf3bc6c7bc134090c3f30a9 Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Sun, 29 Aug 2010 23:53:15 +0100 Subject: [PATCH 4/4] Use generic single VU meter in some dynamics plugins as well. (cherry picked from commit 50505a2d304555bb3b766c43af5cd1a27de331e2) --- .../calf/src/calf/modules_comp.h | 13 +- .../calf/src/calf/plugin_tools.h | 5 + .../ladspa_effect/calf/src/modules_comp.cpp | 134 ++++-------------- .../ladspa_effect/calf/src/modules_dist.cpp | 9 +- 4 files changed, 38 insertions(+), 123 deletions(-) diff --git a/plugins/ladspa_effect/calf/src/calf/modules_comp.h b/plugins/ladspa_effect/calf/src/calf/modules_comp.h index 934b289b1..9f8923a60 100644 --- a/plugins/ladspa_effect/calf/src/calf/modules_comp.h +++ b/plugins/ladspa_effect/calf/src/calf/modules_comp.h @@ -29,6 +29,7 @@ #include "giface.h" #include "loudness.h" #include "metadata.h" +#include "plugin_tools.h" namespace calf_plugins { @@ -97,8 +98,7 @@ public: class compressor_audio_module: public audio_module, public line_graph_iface { private: typedef compressor_audio_module AM; - uint32_t clip_in, clip_out; - float meter_in, meter_out; + stereo_in_out_metering meters; gain_reduction_audio_module compressor; public: typedef std::complex cfloat; @@ -138,8 +138,7 @@ private: CalfScModes sc_mode; mutable CalfScModes sc_mode_old, sc_mode_old1; float f1_active, f2_active; - uint32_t clip_in, clip_out; - float meter_in, meter_out; + stereo_in_out_metering meters; gain_reduction_audio_module compressor; dsp::biquad_d2 f1L, f1R, f2L, f2R; public: @@ -225,8 +224,7 @@ public: class gate_audio_module: public audio_module, public line_graph_iface { private: typedef gate_audio_module AM; - uint32_t clip_in, clip_out; - float meter_in, meter_out; + stereo_in_out_metering meters; expander_audio_module gate; public: typedef std::complex cfloat; @@ -266,8 +264,7 @@ private: CalfScModes sc_mode; mutable CalfScModes sc_mode_old, sc_mode_old1; float f1_active, f2_active; - uint32_t clip_in, clip_out; - float meter_in, meter_out; + stereo_in_out_metering meters; expander_audio_module gate; dsp::biquad_d2 f1L, f1R, f2L, f2R; public: diff --git a/plugins/ladspa_effect/calf/src/calf/plugin_tools.h b/plugins/ladspa_effect/calf/src/calf/plugin_tools.h index aad5cdf6b..cd497b2e9 100644 --- a/plugins/ladspa_effect/calf/src/calf/plugin_tools.h +++ b/plugins/ladspa_effect/calf/src/calf/plugin_tools.h @@ -72,6 +72,11 @@ public: *params[Metadata::param_clip_out] = vumeter_out.clip > 0 ? 1.f : 0.f; } } + void bypassed(float *const *params, unsigned int nsamples) + { + reset(); + process(params, NULL, NULL, 0, nsamples); + } }; }; diff --git a/plugins/ladspa_effect/calf/src/modules_comp.cpp b/plugins/ladspa_effect/calf/src/modules_comp.cpp index a1240e45e..35fad9c42 100644 --- a/plugins/ladspa_effect/calf/src/modules_comp.cpp +++ b/plugins/ladspa_effect/calf/src/modules_comp.cpp @@ -363,6 +363,7 @@ compressor_audio_module::compressor_audio_module() is_active = false; srate = 0; last_generation = 0; + meters.reset(); } void compressor_audio_module::activate() @@ -371,10 +372,7 @@ void compressor_audio_module::activate() // set all filters and strips compressor.activate(); params_changed(); - meter_in = 0.f; - meter_out = 0.f; - clip_in = 0.f; - clip_out = 0.f; + meters.reset(); } void compressor_audio_module::deactivate() { @@ -395,6 +393,8 @@ void compressor_audio_module::set_sample_rate(uint32_t sr) uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { + uint32_t orig_offset = offset; + uint32_t orig_numsamples = numsamples; bool bypass = *params[param_bypass] > 0.5f; numsamples += offset; if(bypass) { @@ -405,16 +405,10 @@ uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, ++offset; } // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; + meters.bypassed(params, orig_numsamples); } else { // process - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); - compressor.update_curve(); while(offset < numsamples) { @@ -439,26 +433,11 @@ uint32_t compressor_audio_module::process(uint32_t offset, uint32_t numsamples, outs[0][offset] = outL; outs[1][offset] = outR; - // clip LED's - if(std::max(fabs(inL), fabs(inR)) > 1.f) { - clip_in = srate >> 3; - } - if(std::max(fabs(outL), fabs(outR)) > 1.f) { - clip_out = srate >> 3; - } - // rise up out meter - meter_in = std::max(fabs(inL), fabs(inR));; - meter_out = std::max(fabs(outL), fabs(outR));; - // next sample ++offset; } // cycle trough samples + meters.process(params, ins, outs, orig_offset, orig_numsamples); } - // draw meters - SET_IF_CONNECTED(clip_in) - SET_IF_CONNECTED(clip_out) - SET_IF_CONNECTED(meter_in) - SET_IF_CONNECTED(meter_out) // draw strip meter if(bypass > 0.5f) { if(params[param_compression] != NULL) { @@ -517,6 +496,7 @@ sidechaincompressor_audio_module::sidechaincompressor_audio_module() f1_level_old1 = 0.f; f2_level_old1 = 0.f; sc_mode_old1 = WIDEBAND; + meters.reset(); } void sidechaincompressor_audio_module::activate() @@ -525,10 +505,7 @@ void sidechaincompressor_audio_module::activate() // set all filters and strips compressor.activate(); params_changed(); - meter_in = 0.f; - meter_out = 0.f; - clip_in = 0.f; - clip_out = 0.f; + meters.reset(); } void sidechaincompressor_audio_module::deactivate() { @@ -685,6 +662,8 @@ void sidechaincompressor_audio_module::set_sample_rate(uint32_t sr) uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { + uint32_t orig_offset = offset; + uint32_t orig_numsamples = numsamples; bool bypass = *params[param_bypass] > 0.5f; numsamples += offset; if(bypass) { @@ -695,15 +674,10 @@ uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t num ++offset; } // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; + meters.bypassed(params, orig_numsamples); } else { // process - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); compressor.update_curve(); while(offset < numsamples) { @@ -783,32 +757,16 @@ uint32_t sidechaincompressor_audio_module::process(uint32_t offset, uint32_t num // send to output outs[0][offset] = outL; outs[1][offset] = outR; - - // clip LED's - if(std::max(fabs(inL), fabs(inR)) > 1.f) { - clip_in = srate >> 3; - } - if(std::max(fabs(outL), fabs(outR)) > 1.f) { - clip_out = srate >> 3; - } - // rise up out meter - meter_in = std::max(fabs(inL), fabs(inR));; - meter_out = std::max(fabs(outL), fabs(outR));; - + // next sample ++offset; } // cycle trough samples + meters.process(params, ins, outs, orig_offset, orig_numsamples); f1L.sanitize(); f1R.sanitize(); f2L.sanitize(); f2R.sanitize(); - } - // draw meters - SET_IF_CONNECTED(clip_in) - SET_IF_CONNECTED(clip_out) - SET_IF_CONNECTED(meter_in) - SET_IF_CONNECTED(meter_out) // draw strip meter if(bypass > 0.5f) { if(params[param_compression] != NULL) { @@ -1139,6 +1097,7 @@ gate_audio_module::gate_audio_module() is_active = false; srate = 0; last_generation = 0; + meters.reset(); } void gate_audio_module::activate() @@ -1147,10 +1106,7 @@ void gate_audio_module::activate() // set all filters and strips gate.activate(); params_changed(); - meter_in = 0.f; - meter_out = 0.f; - clip_in = 0.f; - clip_out = 0.f; + meters.reset(); } void gate_audio_module::deactivate() { @@ -1171,6 +1127,8 @@ void gate_audio_module::set_sample_rate(uint32_t sr) uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { + uint32_t orig_offset = offset; + uint32_t orig_numsamples = numsamples; bool bypass = *params[param_bypass] > 0.5f; numsamples += offset; if(bypass) { @@ -1181,15 +1139,9 @@ uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32 ++offset; } // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; + meters.bypassed(params, orig_numsamples); } else { // process - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); - gate.update_curve(); while(offset < numsamples) { @@ -1214,26 +1166,11 @@ uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32 outs[0][offset] = outL; outs[1][offset] = outR; - // clip LED's - if(std::max(fabs(inL), fabs(inR)) > 1.f) { - clip_in = srate >> 3; - } - if(std::max(fabs(outL), fabs(outR)) > 1.f) { - clip_out = srate >> 3; - } - // rise up out meter - meter_in = std::max(fabs(inL), fabs(inR));; - meter_out = std::max(fabs(outL), fabs(outR));; - // next sample ++offset; } // cycle trough samples + meters.process(params, ins, outs, orig_offset, orig_numsamples); } - // draw meters - SET_IF_CONNECTED(clip_in) - SET_IF_CONNECTED(clip_out) - SET_IF_CONNECTED(meter_in) - SET_IF_CONNECTED(meter_out) // draw strip meter if(bypass > 0.5f) { if(params[param_gating] != NULL) { @@ -1291,7 +1228,7 @@ sidechaingate_audio_module::sidechaingate_audio_module() f1_freq_old = f2_freq_old = f1_level_old = f2_level_old = 0; f1_freq_old1 = f2_freq_old1 = f1_level_old1 = f2_level_old1 = 0; sc_mode_old = sc_mode_old1 = WIDEBAND; // doesn't matter as long as it's sane - + meters.reset(); } void sidechaingate_audio_module::activate() @@ -1300,10 +1237,7 @@ void sidechaingate_audio_module::activate() // set all filters and strips gate.activate(); params_changed(); - meter_in = 0.f; - meter_out = 0.f; - clip_in = 0.f; - clip_out = 0.f; + meters.reset(); } void sidechaingate_audio_module::deactivate() { @@ -1460,6 +1394,8 @@ void sidechaingate_audio_module::set_sample_rate(uint32_t sr) uint32_t sidechaingate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask) { + uint32_t orig_offset = offset; + uint32_t orig_numsamples = numsamples; bool bypass = *params[param_bypass] > 0.5f; numsamples += offset; if(bypass) { @@ -1470,15 +1406,10 @@ uint32_t sidechaingate_audio_module::process(uint32_t offset, uint32_t numsample ++offset; } // displays, too - clip_in = 0.f; - clip_out = 0.f; - meter_in = 0.f; - meter_out = 0.f; + meters.bypassed(params, orig_offset); } else { // process - clip_in -= std::min(clip_in, numsamples); - clip_out -= std::min(clip_out, numsamples); gate.update_curve(); while(offset < numsamples) { @@ -1559,31 +1490,16 @@ uint32_t sidechaingate_audio_module::process(uint32_t offset, uint32_t numsample outs[0][offset] = outL; outs[1][offset] = outR; - // clip LED's - if(std::max(fabs(inL), fabs(inR)) > 1.f) { - clip_in = srate >> 3; - } - if(std::max(fabs(outL), fabs(outR)) > 1.f) { - clip_out = srate >> 3; - } - // rise up out meter - meter_in = std::max(fabs(inL), fabs(inR));; - meter_out = std::max(fabs(outL), fabs(outR));; - // next sample ++offset; } // cycle trough samples + meters.process(params, ins, outs, orig_offset, orig_numsamples); f1L.sanitize(); f1R.sanitize(); f2L.sanitize(); f2R.sanitize(); } - // draw meters - SET_IF_CONNECTED(clip_in) - SET_IF_CONNECTED(clip_out) - SET_IF_CONNECTED(meter_in) - SET_IF_CONNECTED(meter_out) // draw strip meter if(bypass > 0.5f) { if(params[param_gating] != NULL) { diff --git a/plugins/ladspa_effect/calf/src/modules_dist.cpp b/plugins/ladspa_effect/calf/src/modules_dist.cpp index 1592e3267..4d6a89160 100644 --- a/plugins/ladspa_effect/calf/src/modules_dist.cpp +++ b/plugins/ladspa_effect/calf/src/modules_dist.cpp @@ -137,8 +137,7 @@ uint32_t saturator_audio_module::process(uint32_t offset, uint32_t numsamples, u } ++offset; } - meters.reset(); - meters.process(params, NULL, NULL, 0, 0); + meters.bypassed(params, orig_numsamples); } else { meter_drive = 0.f; float in_avg[2] = {0.f, 0.f}; @@ -327,8 +326,7 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin } ++offset; } - meters.reset(); - meters.process(params, NULL, NULL, 0, 0); + meters.bypassed(params, orig_numsamples); // displays, too meter_drive = 0.f; } else { @@ -515,8 +513,7 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples ++offset; } // displays, too - meters.reset(); - meters.process(params, NULL, NULL, 0, 0); + meters.bypassed(params, orig_numsamples); meter_drive = 0.f; } else { meter_drive = 0.f;