[SCM] calf/master: Add first version of Damien Zammit's Gate plugin with my modifications.

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:40:17 UTC 2013


The following commit has been merged in the master branch:
commit ad9b219c95cbbce18310a66cd82e29c853bc5da4
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Wed May 19 23:54:33 2010 +0100

    Add first version of Damien Zammit's Gate plugin with my modifications.
    
    I've tried to improve operation in RMS mode, but the ratio control is still
    not working as expected.

diff --git a/gui/gui-gate.xml b/gui/gui-gate.xml
new file mode 100644
index 0000000..5069044
--- /dev/null
+++ b/gui/gui-gate.xml
@@ -0,0 +1,78 @@
+<table border="10" rows="4" cols="1">
+    <hbox attach-x="0" attach-y="0" shrink-y="1" expand-y="0">
+    	<vbox expand="0">
+             <label param="bypass"/>
+             <align><toggle param="bypass" shrink="1"/></align>
+        </vbox>
+    	<vbox expand="0">
+             <label param="trigger"/>
+             <align><toggle param="trigger" shrink="1"/></align>
+        </vbox>
+    	<vbox expand="0">
+             <label param="detection"/>
+             <combo param="detection"/>
+        </vbox>
+    	<vbox expand="0">
+             <label param="stereo_link"/>
+             <combo param="stereo_link"/>
+        </vbox>
+    	<vbox expand="0">
+             <label param="aweighting"/>
+             <combo param="aweighting"/>
+        </vbox>
+    </hbox>
+    <if cond="directlink">
+        <line-graph attach-x="0" attach-y="1" refresh="1" width="384" height="384" param="gating" square="1" expand-y="1" fill-y="1"/>
+    </if>
+    <table attach-x="0" attach-y="2" expand-y="0" expand-x="1" spacing="10" rows="1" cols="3">
+        <vbox expand-x="1" fill-x="1" expand="1" fill="1" attach-x="0" attach-y="0">
+            <label param="gating" />
+            <vumeter param="gating" mode="2" />
+        </vbox>
+        <vbox shrink-x="1" expand-x="0" fill-x="0" expand="0" fill="0" attach-x="1" attach-y="0">
+            <label param="clip" expand="0" fill="0" />
+            <led param="clip" expand="0" fill="0" />
+        </vbox>
+        <vbox expand-x="1" fill-x="1" expand="1" fill="1" attach-x="2" attach-y="0">
+            <label param="peak" />
+            <vumeter param="peak" mode="0" shrink-y="0" />
+        </vbox>
+    </table>
+    <hbox attach-x="0" attach-y="3" expand-y="0">
+        <vbox border="10" expand="0">
+            <label param="attack" />
+            <knob param="attack" />
+            <value param="attack" />
+        </vbox>
+        <vbox border="10" expand="0">
+            <label param="release" />
+            <knob param="release" />
+            <value param="release" />
+        </vbox>
+        <vbox border="10" expand="0">
+            <label param="threshold" />
+            <knob param="threshold"/>
+            <value param="threshold" />
+        </vbox>
+        <vbox border="10" expand="0">
+            <label param="ratio" />
+            <knob param="ratio" />
+            <value param="ratio" />
+        </vbox>
+	<vbox border="10" expand="0">
+	    <label param="range" />
+	    <knob param="range" />
+	    <value param="range" />
+	</vbox>
+        <vbox border="10" expand="0">
+            <label param="makeup" />
+            <knob param="makeup" />
+            <value param="makeup" />
+        </vbox>
+        <vbox border="10" expand="0">
+            <label param="knee" />
+            <knob param="knee" />
+            <value param="knee" />
+        </vbox>
+    </hbox>
+</table>
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index 27b675c..6e3f94c 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -294,6 +294,16 @@ struct bassenhancer_metadata: public plugin_metadata<bassenhancer_metadata>
            param_freq, param_listen, param_count };
     PLUGIN_NAME_ID_LABEL("bassenhancer", "bassenhancer", "Bass Enhancer")
 };
+
+/// Damien's gate - metadata
+struct gate_metadata: public plugin_metadata<gate_metadata>
+{
+    enum { in_count = 3, out_count = 2, ins_optional = 1, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
+    enum { param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_aweighting, param_gating, param_peak, param_clip, param_bypass, param_range, param_mono, param_trigger, // param_freq, param_bw,
+        param_count };
+    PLUGIN_NAME_ID_LABEL("gate", "gate", "Gate")
+};
+
 /// Organ - enums for parameter IDs etc. (this mess is caused by organ split between plugin and generic class - which was
 /// a bad design decision and should be sorted out some day) XXXKF @todo
 struct organ_enums
diff --git a/src/calf/modulelist.h b/src/calf/modulelist.h
index 76cb551..baaa5d9 100644
--- a/src/calf/modulelist.h
+++ b/src/calf/modulelist.h
@@ -20,6 +20,7 @@
     PER_MODULE_ITEM(saturator, false, "saturator")
     PER_MODULE_ITEM(exciter, false, "exciter")
     PER_MODULE_ITEM(bassenhancer, false, "bassenhancer")
+    PER_MODULE_ITEM(gate, false, "gate")
 #ifdef ENABLE_EXPERIMENTAL
     PER_MODULE_ITEM(fluidsynth, true, "fluidsynth")
     PER_MODULE_ITEM(wavetable, true, "wavetable")
diff --git a/src/calf/modules_comp.h b/src/calf/modules_comp.h
index 8ab3ac8..1c85820 100644
--- a/src/calf/modules_comp.h
+++ b/src/calf/modules_comp.h
@@ -27,6 +27,7 @@
 #include "inertia.h"
 #include "audio_fx.h"
 #include "giface.h"
+#include "loudness.h"
 #include "metadata.h"
 
 namespace calf_plugins {
@@ -189,6 +190,60 @@ public:
     int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
 };
 
+
+class gate_audio_module: public audio_module<gate_metadata>, public line_graph_iface {
+private:
+    float linSlope, peak, detected, kneeSqrt, kneeStart, linKneeStart, kneeStop, linKneeStop, threshold, ratio, knee, makeup, compressedKneeStop, adjKneeStart, range;
+    mutable float old_threshold, old_ratio, old_knee, old_makeup, old_bypass, old_range, old_trigger, old_mono;
+    mutable volatile int last_generation;
+    uint32_t clip;
+    dsp::aweighter awL, awR;
+    dsp::biquad_d2<float> bpL, bpR;
+public:
+    uint32_t srate;
+    bool is_active;
+    gate_audio_module();
+    void activate();
+    void deactivate();
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+
+    inline float output_level(float slope) const {
+        bool rms = *params[param_detection] == 0;
+        return slope * output_gain(rms ? slope*slope : slope, rms) * makeup;
+    }
+
+    inline float output_gain(float linSlope, bool rms) const {
+        if(linSlope < linKneeStop) {
+            float slope = log(linSlope);
+
+            //float tratio = rms ? sqrt(ratio) : ratio;
+            float tratio = ratio;
+            float gain = 0.f;
+            float delta = 0.f;
+	    if(IS_FAKE_INFINITY(ratio))
+	        tratio = 1000.f;
+            gain = (slope-threshold) * tratio + threshold;
+            delta = tratio;
+
+            if(knee > 1.f && slope > kneeStart ) {
+		gain = dsp::hermite_interpolation(slope, kneeStart, kneeStop, ((kneeStart - threshold) * tratio  + threshold), kneeStop, delta,1.f);
+	    }
+	    return std::max(range, expf(gain-slope));
+	}
+
+
+        return 1.f;
+    }
+
+    void set_sample_rate(uint32_t sr);
+
+    virtual bool get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const;
+    virtual bool get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const;
+    virtual bool get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const;
+    virtual int  get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
+};
+
+
 };
 
 #endif
diff --git a/src/metadata.cpp b/src/metadata.cpp
index 5dff436..8129506 100644
--- a/src/metadata.cpp
+++ b/src/metadata.cpp
@@ -592,6 +592,37 @@ CALF_PORT_PROPS(bassenhancer) = {
 
 CALF_PLUGIN_INFO(bassenhancer) = { 0x8532, "BassEnhancer", "Calf Bass Enhancer", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
 
+
+////////////////////////////////////////////////////////////////////////////
+
+CALF_PORT_NAMES(gate) = {"In L", "In R", "In Trigger", "Out L", "Out R"};
+
+const char *gate_detection_names[] = { "RMS", "Peak" };
+const char *gate_stereo_link_names[] = { "Average", "Maximum" };
+const char *gate_weighting_names[] = { "Normal", "A-weighted", "Deesser (low)", "Deesser (med)", "Deesser (high)" };
+
+CALF_PORT_PROPS(gate) = {
+    { 0.125,      0.000976563, 1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold", "Threshold" },
+    { 2,      1, 20,  21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio", "Ratio" },
+    { 20,     1, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Attack" },
+    { 250,    1, 2000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" },
+    { 1,      1, 64,   0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup", "Makeup Gain" },
+    { 2.828427125,      1,  8,   0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee", "Knee" },
+    { 0,      0,  1,   0, PF_ENUM | PF_CTL_COMBO, gate_detection_names, "detection", "Detection" },
+    { 0,      0,  1,   0, PF_ENUM | PF_CTL_COMBO, gate_stereo_link_names, "stereo_link", "Stereo Link" },
+    { 0,      0,  4,   0, PF_ENUM | PF_CTL_COMBO, gate_weighting_names, "aweighting", "Weighting" },
+    { 0, 0.03125, 1,    0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "gating", "Gating" },
+    { 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, "peak", "Peak Output" },
+    { 0,      0,  1,    0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip", "0dBFS" },
+    { 0,      0,  1,    0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" },
+    { 0.01,   0.000015849, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "range", "Max Gain Reduction" },
+    { 0,      0,  1,    0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mono", "Mono (L only)" },
+    { 0,      0,  1,    0, PF_BOOL | PF_CTL_TOGGLE, NULL, "trigger", "Sidechain (Mono In)" },
+
+};
+
+CALF_PLUGIN_INFO(gate) = { 0x8503, "Gate", "Calf Gate", "Damien Zammit / Thor Harald Johansen", calf_plugins::calf_copyright_info, "ExpanderPlugin" };
+
 ////////////////////////////////////////////////////////////////////////////
 
 CALF_PORT_NAMES(monosynth) = {
diff --git a/src/modules_comp.cpp b/src/modules_comp.cpp
index f96d698..a5d58e2 100644
--- a/src/modules_comp.cpp
+++ b/src/modules_comp.cpp
@@ -1343,3 +1343,250 @@ int gain_reduction_audio_module::get_changed_offsets(int generation, int &subind
     return last_generation;
 }
 
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+gate_audio_module::gate_audio_module()
+{
+    is_active = false;
+    srate = 0;
+    last_generation = 0;
+}
+
+void gate_audio_module::activate()
+{
+    is_active = true;
+    linSlope = 0.f;
+    peak = 0.f;
+    clip = 0.f;
+}
+
+void gate_audio_module::deactivate()
+{
+    is_active = false;
+}
+
+void gate_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+    awL.set(sr);
+    awR.set(sr);
+}
+
+bool gate_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    if (subindex > 1) // 1
+        return false;
+    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);
+    }
+    if (subindex == (*params[param_bypass] > 0.f ? 1 : 0))
+        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(1.5);
+    }
+    return true;
+}
+
+bool gate_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
+{
+    if (!is_active)
+        return false;
+    if (!subindex)
+    {
+        bool rms = *params[param_detection] == 0;
+        float det = rms ? sqrt(detected) : detected;
+        x = 0.5 + 0.5 * dB_grid(det);
+        y = dB_grid(*params[param_bypass] > 0.f ? det : output_level(det));
+        return *params[param_bypass] > 0.f ? false : true;
+    }
+    return false;
+}
+
+bool gate_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{
+    bool tmp;
+    vertical = (subindex & 1) != 0;
+    bool result = get_freq_gridline(subindex >> 1, pos, tmp, legend, context, false);
+    if (result && vertical) {
+        if ((subindex & 4) && !legend.empty()) {
+            legend = "";
+        }
+        else {
+            size_t pos = legend.find(" dB");
+            if (pos != std::string::npos)
+                legend.erase(pos);
+        }
+        pos = 0.5 + 0.5 * pos;
+    }
+    return result;
+}
+
+uint32_t gate_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
+{
+    bool bypass = *params[param_bypass] > 0.f;
+
+    if(bypass) {
+        int count = numsamples * sizeof(float);
+        memcpy(outs[0], ins[0], count);
+        memcpy(outs[1], ins[1], count);
+
+        if(params[param_gating] != NULL) {
+            *params[param_gating] = 1.f;
+        }
+
+        if(params[param_clip] != NULL) {
+            *params[param_clip] = 0.f;
+        }
+
+        if(params[param_peak] != NULL) {
+            *params[param_peak] = 0.f;
+        }
+
+        return inputs_mask;
+    }
+
+    bool rms = *params[param_detection] == 0;
+    bool average = *params[param_stereo_link] == 0;
+    int aweighting = fastf2i_drm(*params[param_aweighting]);
+    float linThreshold = *params[param_threshold];
+    if (rms)
+        linThreshold = linThreshold * linThreshold;
+    ratio = *params[param_ratio];
+    float attack = *params[param_attack];
+    float attack_coeff = std::min(1.f, 1.f / (attack * srate / 4000.f));
+    float release = *params[param_release];
+    float release_coeff = std::min(1.f, 1.f / (release * srate / 4000.f));
+    makeup = *params[param_makeup];
+    knee = *params[param_knee];
+
+    range = *params[param_range];
+
+    float linKneeSqrt = sqrt(knee);
+    linKneeStart = linThreshold / linKneeSqrt;
+    adjKneeStart = linKneeStart*linKneeStart;
+    linKneeStop = linThreshold * linKneeSqrt;
+
+    threshold = log(linThreshold);
+    kneeStart = log(linKneeStart);
+    kneeStop = log(linKneeStop);
+    compressedKneeStop = (kneeStop - threshold) / ratio + threshold;
+
+    if (aweighting >= 2)
+    {
+        bpL.set_highshelf_rbj(5000, 0.707, 10 << (aweighting - 2), srate);
+        bpR.copy_coeffs(bpL);
+        bpL.sanitize();
+        bpR.sanitize();
+    }
+
+    numsamples += offset;
+
+    float gating = 1.f;
+
+    peak -= peak * 5.f * numsamples / srate;
+
+    clip -= std::min(clip, numsamples);
+    float left;
+    float right;
+
+    while(offset < numsamples) {
+        if(*params[param_trigger]) {
+	    left = ins[2][offset];  // Use sidechain to trigger input
+	    right = left;           // (mono sidechain)
+	} else {
+	    left = ins[0][offset];
+            right = ins[1][offset];
+        }
+
+        if(aweighting == 1) {
+            left = awL.process(left);
+            right = awR.process(right);
+        }
+        else if(aweighting >= 2) {
+            left = bpL.process(left);
+            right = bpR.process(right);
+        }
+
+        float absample = average ? (fabs(left) + fabs(right)) * 0.5f : std::max(fabs(left), fabs(right));
+        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);
+        }
+
+        gating = gain;
+        gain *= makeup;
+
+        float outL = ins[0][offset] * gain;
+        float outR = ins[1][offset] * gain;
+
+        outs[0][offset] = outL;
+        outs[1][offset] = outR;
+
+        ++offset;
+
+        float maxLR = std::max(fabs(outL), fabs(outR));
+
+        if(maxLR > 1.f) clip = srate >> 3; /* blink clip LED for 125 ms */
+
+        if(maxLR > peak) {
+            peak = maxLR;
+        }
+    }
+
+    detected = linSlope;
+
+    if(params[param_gating] != NULL) {
+        *params[param_gating] = gating;
+    }
+
+    if(params[param_clip] != NULL) {
+        *params[param_clip] = clip;
+    }
+
+    if(params[param_peak] != NULL) {
+        *params[param_peak] = peak;
+    }
+
+    return inputs_mask;
+}
+
+int gate_audio_module::get_changed_offsets(int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const
+{
+    subindex_graph = 0;
+    subindex_dot = 0;
+    subindex_gridline = generation ? INT_MAX : 0;
+
+    if (fabs(range-old_range) + fabs(threshold-old_threshold) + fabs(ratio - old_ratio) + fabs(knee - old_knee) + fabs( makeup - old_makeup) + fabs( *params[param_bypass] - old_bypass) > 0.01f)
+    {
+        old_range = range;
+        old_threshold = threshold;
+        old_ratio = ratio;
+        old_knee = knee;
+        old_makeup = makeup;
+        old_bypass = *params[param_bypass];
+        old_trigger = *params[param_trigger];
+        old_mono = *params[param_mono];
+        last_generation++;
+    }
+        old_trigger = *params[param_trigger];
+
+    if (generation == last_generation)
+        subindex_graph = 2;
+    return last_generation;
+}

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list