[SCM] calf/master: Add first version of Markus' saturation and enhancer plugins.
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:40:08 UTC 2013
The following commit has been merged in the master branch:
commit 13afbdb179e5f4c7c0aaeba079ec17f1591f69e3
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Mon May 3 19:40:00 2010 +0100
Add first version of Markus' saturation and enhancer plugins.
I'm probably not up-to-date with Markus' code, but this is good start
at least (and at last). It still lacks GUI files.
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index 22d9f22..85d8984 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -428,6 +428,26 @@ struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
PLUGIN_NAME_ID_LABEL("wavetable", "wavetable", "Wavetable")
};
+/// Markus's Saturator - metadata
+struct saturator_metadata: public plugin_metadata<saturator_metadata>
+{
+ enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true };
+ enum { param_bypass, param_level_in, param_level_out, param_mix, param_meter_in,
+ param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive,
+ param_lp_pre_freq, param_hp_pre_freq, param_lp_post_freq, param_hp_post_freq,
+ param_p_freq, param_p_level, param_p_q, param_count };
+ PLUGIN_NAME_ID_LABEL("saturator", "saturator", "Saturator")
+};
+/// Markus's Enhancer - metadata
+struct enhancer_metadata: public plugin_metadata<enhancer_metadata>
+{
+ enum { in_count = 2, out_count = 2, ins_optional = 1, outs_optional = 1, support_midi = false, require_midi = false, rt_capable = true };
+ enum { param_bypass, param_level_in, param_level_out, param_amount, param_meter_in,
+ param_meter_out, param_clip_in, param_clip_out, param_drive, param_blend, param_meter_drive,
+ param_freq, param_listen, param_count };
+ PLUGIN_NAME_ID_LABEL("enhancer", "enhancer", "Enhancer")
+};
+
};
#endif
diff --git a/src/calf/modulelist.h b/src/calf/modulelist.h
index dabd2c3..0184237 100644
--- a/src/calf/modulelist.h
+++ b/src/calf/modulelist.h
@@ -17,6 +17,8 @@
PER_MODULE_ITEM(equalizer5band, false, "eq5")
PER_MODULE_ITEM(equalizer8band, false, "eq8")
PER_MODULE_ITEM(equalizer12band, false, "eq12")
+ PER_MODULE_ITEM(saturator, false, "saturator")
+ PER_MODULE_ITEM(enhancer, false, "enhancer")
#ifdef ENABLE_EXPERIMENTAL
PER_MODULE_ITEM(fluidsynth, true, "fluidsynth")
PER_MODULE_ITEM(wavetable, true, "wavetable")
diff --git a/src/calf/modules.h b/src/calf/modules.h
index 0fbca1e..730b28c 100644
--- a/src/calf/modules.h
+++ b/src/calf/modules.h
@@ -634,6 +634,48 @@ private:
void adjust_gain_according_to_filter_mode(int velocity);
};
+/// Saturator by Markus Schmidt (based on Krzysztof's filters and Tom Szilagyi's distortion algorithm)
+class saturator_audio_module: public audio_module<saturator_metadata> {
+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;
+ biquad_d2<float> lp[2][4], hp[2][4];
+ biquad_d2<float> p[2];
+ tap_distortion dist[2];
+public:
+ uint32_t srate;
+ bool is_active;
+ saturator_audio_module();
+ void activate();
+ void deactivate();
+ void params_changed();
+ void set_sample_rate(uint32_t sr);
+ uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+};
+
+/// Enhancer by Markus Schmidt (based on Krzysztof's filters and Tom Szilagyi's distortion algorithm)
+class enhancer_audio_module: public audio_module<enhancer_metadata> {
+private:
+ float freq_old;
+ uint32_t clip_in, clip_out;
+ float meter_in, meter_out, meter_drive;
+ biquad_d2<float> hp[2][4];
+ tap_distortion dist[2];
+public:
+ uint32_t srate;
+ bool is_active;
+ enhancer_audio_module();
+ void activate();
+ void deactivate();
+ void params_changed();
+ void set_sample_rate(uint32_t sr);
+ uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+};
+
+
};
#include "modules_synths.h"
diff --git a/src/modules.cpp b/src/modules.cpp
index b074e89..71e6bcc 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -885,6 +885,61 @@ CALF_PORT_PROPS(wavetable) = {
////////////////////////////////////////////////////////////////////////////
+CALF_PORT_NAMES(saturator) = {"In L", "In R", "Out L", "Out R"};
+
+CALF_PORT_PROPS(saturator) = {
+ { 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", "Gain" },
+ { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "level_out", "Master" },
+ { 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "mix", "Mix" },
+ { 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_in", "Input" },
+ { 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_out", "Output" },
+ { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
+ { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
+
+ { 2, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Drive" },
+ { 10, -10, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend" },
+ { 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_drive", "Drive" },
+
+ { 20000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_pre_freq", "Lowpass" },
+ { 10, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_pre_freq", "Highpass" },
+
+ { 20000, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lp_post_freq", "Lowpass" },
+ { 10, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "hp_post_freq", "Highpass" },
+
+ { 2000, 80, 8000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p_freq", "Tone" },
+ { 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p_level", "Amount" },
+ { 1, 0.1, 10, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p_q", "Gradient" },
+};
+
+CALF_PLUGIN_INFO(saturator) = { 0x8519, "Saturator", "Calf Saturator", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
+
+////////////////////////////////////////////////////////////////////////////
+
+CALF_PORT_NAMES(enhancer) = {"In L", "In R", "Out L", "Out R"};
+
+CALF_PORT_PROPS(enhancer) = {
+ { 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" },
+ { 1, 0, 64, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" },
+ { 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_in", "Input" },
+ { 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_out", "Output" },
+ { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB" },
+ { 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_out", "0dB" },
+
+ { 8.5, 0.1, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Harmonics" },
+ { 0, -10, 10, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_COEF, NULL, "blend", "Blend harmonics" },
+ { 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_drive", "Harmonics level" },
+
+ { 6000, 2000, 12000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Scope" },
+ { 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "listen", "Listen" },
+};
+
+CALF_PLUGIN_INFO(enhancer) = { 0x851A, "Enhancer", "Calf Enhancer", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
+
+////////////////////////////////////////////////////////////////////////////
+
calf_plugins::plugin_registry::plugin_registry()
{
#define PER_MODULE_ITEM(name, isSynth, jackname) plugins.push_back((new name##_metadata));
diff --git a/src/modules_dsp.cpp b/src/modules_dsp.cpp
index 5b8268c..c334682 100644
--- a/src/modules_dsp.cpp
+++ b/src/modules_dsp.cpp
@@ -2881,3 +2881,484 @@ bool pulsator_audio_module::get_gridline(int index, int subindex, float &pos, bo
}
return false;
}
+
+
+/// Saturator Band by Markus Schmidt
+///
+/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
+/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+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;
+}
+
+void saturator_audio_module::activate()
+{
+ is_active = true;
+ // set all filters
+ params_changed();
+}
+void saturator_audio_module::deactivate()
+{
+ is_active = false;
+}
+
+void saturator_audio_module::params_changed()
+{
+ // set the params of all filters
+ if(*params[param_lp_pre_freq] != lp_pre_freq_old) {
+ lp[0][0].set_lp_rbj(*params[param_lp_pre_freq], 0.707, (float)srate);
+ if(in_count > 1 && out_count > 1)
+ lp[1][0].copy_coeffs(lp[0][0]);
+ lp[0][1].copy_coeffs(lp[0][0]);
+ if(in_count > 1 && out_count > 1)
+ lp[1][1].copy_coeffs(lp[0][0]);
+ lp_pre_freq_old = *params[param_lp_pre_freq];
+ }
+ if(*params[param_hp_pre_freq] != hp_pre_freq_old) {
+ hp[0][0].set_hp_rbj(*params[param_hp_pre_freq], 0.707, (float)srate);
+ if(in_count > 1 && out_count > 1)
+ hp[1][0].copy_coeffs(hp[0][0]);
+ hp[0][1].copy_coeffs(hp[0][0]);
+ if(in_count > 1 && out_count > 1)
+ hp[1][1].copy_coeffs(hp[0][0]);
+ hp_pre_freq_old = *params[param_hp_pre_freq];
+ }
+ if(*params[param_lp_post_freq] != lp_post_freq_old) {
+ lp[0][2].set_lp_rbj(*params[param_lp_post_freq], 0.707, (float)srate);
+ if(in_count > 1 && out_count > 1)
+ lp[1][2].copy_coeffs(lp[0][2]);
+ lp[0][3].copy_coeffs(lp[0][2]);
+ if(in_count > 1 && out_count > 1)
+ lp[1][3].copy_coeffs(lp[0][2]);
+ lp_post_freq_old = *params[param_lp_post_freq];
+ }
+ if(*params[param_hp_post_freq] != hp_post_freq_old) {
+ hp[0][2].set_hp_rbj(*params[param_hp_post_freq], 0.707, (float)srate);
+ if(in_count > 1 && out_count > 1)
+ hp[1][2].copy_coeffs(hp[0][2]);
+ hp[0][3].copy_coeffs(hp[0][2]);
+ if(in_count > 1 && out_count > 1)
+ hp[1][3].copy_coeffs(hp[0][2]);
+ hp_post_freq_old = *params[param_hp_post_freq];
+ }
+ if(*params[param_p_freq] != p_freq_old or *params[param_p_level] != p_level_old or *params[param_p_q] != p_q_old) {
+ p[0].set_peakeq_rbj((float)*params[param_p_freq], (float)*params[param_p_q], (float)*params[param_p_level], (float)srate);
+ if(in_count > 1 && out_count > 1)
+ p[1].copy_coeffs(p[0]);
+ p_freq_old = *params[param_p_freq];
+ p_level_old = *params[param_p_level];
+ p_q_old = *params[param_p_q];
+ }
+ // set distortion
+ dist[0].set_params(*params[param_blend], *params[param_drive]);
+ if(in_count > 1 && out_count > 1)
+ dist[1].set_params(*params[param_blend], *params[param_drive]);
+}
+
+void saturator_audio_module::set_sample_rate(uint32_t sr)
+{
+ srate = sr;
+ dist[0].set_sample_rate(sr);
+ if(in_count > 1 && out_count > 1)
+ dist[1].set_sample_rate(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;
+ numsamples += offset;
+ if(bypass) {
+ // everything bypassed
+ while(offset < numsamples) {
+ if(in_count > 1 && out_count > 1) {
+ outs[0][offset] = ins[0][offset];
+ outs[1][offset] = ins[1][offset];
+ } else if(in_count > 1) {
+ outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
+ } else if(out_count > 1) {
+ outs[0][offset] = ins[0][offset];
+ outs[1][offset] = ins[0][offset];
+ } else {
+ outs[0][offset] = ins[0][offset];
+ }
+ ++offset;
+ }
+ // 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;
+ int c = 0;
+
+ if(in_count > 1 && out_count > 1) {
+ // stereo in/stereo out
+ // handle full stereo
+ in[0] = ins[0][offset];
+ in[0] *= *params[param_level_in];
+ in[1] = ins[1][offset];
+ in[1] *= *params[param_level_in];
+ c = 2;
+ } else {
+ // in and/or out mono
+ // handle mono
+ in[0] = ins[0][offset];
+ in[0] *= *params[param_level_in];
+ in[1] = in[0];
+ c = 1;
+ }
+
+ float proc[2];
+ proc[0] = in[0];
+ proc[1] = in[1];
+
+ for (int i = 0; i < c; ++i) {
+ // all pre filters in chain
+ proc[i] = lp[i][1].process(lp[i][0].process(proc[i]));
+ proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
+
+ // saturate
+ proc[i] = dist[i].process(proc[i]);
+
+ // tone control
+ proc[i] = p[i].process(proc[i]);
+
+ // all post filters in chain
+ proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
+ proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
+ }
+
+ if(in_count > 1 && out_count > 1) {
+ // full 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] = ((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]));
+ maxDrive = std::max(dist[0].get_distortion_level(), dist[1].get_distortion_level());
+ } 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]);
+ maxDrive = dist[0].get_distortion_level();
+ } 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]);
+ maxDrive = dist[0].get_distortion_level();
+ }
+
+ 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;
+ }
+
+ // next sample
+ ++offset;
+ } // cycle trough samples
+ // clean up
+ lp[0][0].sanitize();
+ lp[1][0].sanitize();
+ lp[0][1].sanitize();
+ lp[1][1].sanitize();
+ lp[0][2].sanitize();
+ lp[1][2].sanitize();
+ lp[0][3].sanitize();
+ lp[1][3].sanitize();
+ hp[0][0].sanitize();
+ hp[1][0].sanitize();
+ hp[0][1].sanitize();
+ hp[1][1].sanitize();
+ hp[0][2].sanitize();
+ hp[1][2].sanitize();
+ hp[0][3].sanitize();
+ hp[1][3].sanitize();
+ p[0].sanitize();
+ 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;
+ }
+ // whatever has to be returned x)
+ return outputs_mask;
+}
+
+/// Enhancer Band by Markus Schmidt
+///
+/// This module is based on Krzysztof's filters and Tom Szilagyi's distortion routine.
+/// It provides a blendable saturation stage followed by a highpass, a lowpass and a peak filter
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+enhancer_audio_module::enhancer_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;
+}
+
+void enhancer_audio_module::activate()
+{
+ is_active = true;
+ // set all filters
+ params_changed();
+}
+void enhancer_audio_module::deactivate()
+{
+ is_active = false;
+}
+
+void enhancer_audio_module::params_changed()
+{
+ // set the params of all filters
+ if(*params[param_freq] != freq_old) {
+ hp[0][0].set_hp_rbj(*params[param_freq], 0.707, (float)srate);
+ hp[0][1].copy_coeffs(hp[0][0]);
+ hp[0][2].copy_coeffs(hp[0][0]);
+ hp[0][3].copy_coeffs(hp[0][0]);
+ if(in_count > 1 && out_count > 1) {
+ hp[1][0].copy_coeffs(hp[0][0]);
+ hp[1][1].copy_coeffs(hp[0][0]);
+ hp[1][2].copy_coeffs(hp[0][0]);
+ hp[1][3].copy_coeffs(hp[0][0]);
+ }
+ freq_old = *params[param_freq];
+ }
+ // set distortion
+ dist[0].set_params(*params[param_blend], *params[param_drive]);
+ if(in_count > 1 && out_count > 1)
+ dist[1].set_params(*params[param_blend], *params[param_drive]);
+}
+
+void enhancer_audio_module::set_sample_rate(uint32_t sr)
+{
+ srate = sr;
+ dist[0].set_sample_rate(sr);
+ if(in_count > 1 && out_count > 1)
+ dist[1].set_sample_rate(sr);
+}
+
+uint32_t enhancer_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+ bool bypass = *params[param_bypass] > 0.5f;
+ numsamples += offset;
+ if(bypass) {
+ // everything bypassed
+ while(offset < numsamples) {
+ if(in_count > 1 && out_count > 1) {
+ outs[0][offset] = ins[0][offset];
+ outs[1][offset] = ins[1][offset];
+ } else if(in_count > 1) {
+ outs[0][offset] = (ins[0][offset] + ins[1][offset]) / 2;
+ } else if(out_count > 1) {
+ outs[0][offset] = ins[0][offset];
+ outs[1][offset] = ins[0][offset];
+ } else {
+ outs[0][offset] = ins[0][offset];
+ }
+ ++offset;
+ }
+ // 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;
+ int c = 0;
+
+ if(in_count > 1 && out_count > 1) {
+ // stereo in/stereo out
+ // handle full stereo
+ in[0] = ins[0][offset];
+ in[0] *= *params[param_level_in];
+ in[1] = ins[1][offset];
+ in[1] *= *params[param_level_in];
+ c = 2;
+ } else {
+ // in and/or out mono
+ // handle mono
+ in[0] = ins[0][offset];
+ in[0] *= *params[param_level_in];
+ in[1] = in[0];
+ c = 1;
+ }
+
+ float proc[2];
+ proc[0] = in[0];
+ proc[1] = in[1];
+
+ for (int i = 0; i < c; ++i) {
+ // all pre filters in chain
+ proc[i] = hp[i][1].process(hp[i][0].process(proc[i]));
+
+ // saturate
+ proc[i] = dist[i].process(proc[i]);
+
+ // all post filters in chain
+ proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
+ }
+
+ if(in_count > 1 && out_count > 1) {
+ // full stereo
+ if(*params[param_listen] > 0.f)
+ out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+ else
+ out[0] = (proc[0] * *params[param_amount] + in[0]) * *params[param_level_out];
+ outs[0][offset] = out[0];
+ if(*params[param_listen] > 0.f)
+ out[1] = proc[1] * *params[param_amount] * *params[param_level_out];
+ 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) {
+ // mono -> pseudo stereo
+ if(*params[param_listen] > 0.f)
+ out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+ else
+ out[0] = (proc[0] * *params[param_amount] + in[0]) * *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]);
+ maxDrive = dist[0].get_distortion_level() * *params[param_amount];
+ } else {
+ // stereo -> mono
+ // or full mono
+ if(*params[param_listen] > 0.f)
+ out[0] = proc[0] * *params[param_amount] * *params[param_level_out];
+ 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;
+ }
+
+ // next sample
+ ++offset;
+ } // cycle trough samples
+ // clean up
+ hp[0][0].sanitize();
+ hp[1][0].sanitize();
+ hp[0][1].sanitize();
+ hp[1][1].sanitize();
+ hp[0][2].sanitize();
+ hp[1][2].sanitize();
+ hp[0][3].sanitize();
+ 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;
+ }
+ // whatever has to be returned x)
+ return outputs_mask;
+}
+
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list