From 380b0bfa9b00c59caf8cc2acb0a1a5392807ba32 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 31 Aug 2010 11:40:52 +0200 Subject: [PATCH] Merge branch 'calf-updates' * calf-updates: Use generic single VU meter in some dynamics plugins as well. (cherry picked from commit 50505a2d304555bb3b766c43af5cd1a27de331e2) Refactor metering code out of distortion plugins. (cherry picked from commit 84d873861da7b4ad205061b00fcc9f73c47140b6) More variable initialisation. (cherry picked from commit 40bbe048f27fc7190001383f93097127119ee667) Initialise old-state variables to prevent "stuck" graphs. (cherry picked from commit 2a795084ee9e73712a4b690b84158cc745ff1d30) (cherry picked from commit cb52114261163d2863822fb2c1797ab4325b9d48) --- plugins/ladspa_effect/calf/src/calf/modules.h | 1 - .../calf/src/calf/modules_comp.h | 13 +- .../calf/src/calf/modules_dist.h | 13 +- .../calf/src/calf/plugin_tools.h | 85 +++++++++ plugins/ladspa_effect/calf/src/calf/vumeter.h | 95 ++++++++++ .../ladspa_effect/calf/src/modules_comp.cpp | 165 ++++++------------ .../ladspa_effect/calf/src/modules_dist.cpp | 162 +++-------------- 7 files changed, 271 insertions(+), 263 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_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/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..cd497b2e9 --- /dev/null +++ b/plugins/ladspa_effect/calf/src/calf/plugin_tools.h @@ -0,0 +1,85 @@ +/* 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; + } + } + void bypassed(float *const *params, unsigned int nsamples) + { + reset(); + process(params, NULL, NULL, 0, nsamples); + } +}; + +}; + +#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_comp.cpp b/plugins/ladspa_effect/calf/src/modules_comp.cpp index 15f96a8bb..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) { @@ -512,6 +491,12 @@ 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; + meters.reset(); } void sidechaincompressor_audio_module::activate() @@ -520,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() { @@ -680,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) { @@ -690,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) { @@ -778,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) { @@ -899,6 +862,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() @@ -1129,6 +1097,7 @@ gate_audio_module::gate_audio_module() is_active = false; srate = 0; last_generation = 0; + meters.reset(); } void gate_audio_module::activate() @@ -1137,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() { @@ -1161,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) { @@ -1171,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) { @@ -1204,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) { @@ -1277,6 +1224,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 + meters.reset(); } void sidechaingate_audio_module::activate() @@ -1285,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() { @@ -1445,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) { @@ -1455,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) { @@ -1544,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) { @@ -1663,6 +1594,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() @@ -1889,6 +1827,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() diff --git a/plugins/ladspa_effect/calf/src/modules_dist.cpp b/plugins/ladspa_effect/calf/src/modules_dist.cpp index aba40fc74..4d6a89160 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,8 @@ 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.bypassed(params, orig_numsamples); } 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 +147,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 +167,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 +191,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 +200,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 +242,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 +259,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 +306,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 +326,18 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin } ++offset; } + meters.bypassed(params, orig_numsamples); // 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 +384,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 +395,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 +404,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 +415,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 +427,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 +444,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 +493,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 +513,16 @@ 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.bypassed(params, orig_numsamples); 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 +569,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 +580,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 +589,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 +600,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 +612,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; }