[SCM] calf/master: Implement Automatic Smoothing Control.

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


The following commit has been merged in the master branch:
commit 34029715279608cc5e23e903824323dc5e074a12
Author: Markus Schmidt <schmidt at boomshop.net>
Date:   Sun Dec 25 12:14:14 2011 +0000

    Implement Automatic Smoothing Control.

diff --git a/gui/gui-limiter.xml b/gui/gui-limiter.xml
index b4d3d13..2d678b2 100644
--- a/gui/gui-limiter.xml
+++ b/gui/gui-limiter.xml
@@ -17,10 +17,7 @@
             <led param="clip_inR" expand="0" fill="0" />
             <label text="0dB" expand="0" fill="0" />
         </vbox>
-        <vbox expand="0" attach-x="3" attach-y="0" expand-x="0" fill-x="0" fill="0" pad-x="2">
-             <label param="bypass"/>
-             <align><toggle param="bypass" shrink="1"/></align>
-        </vbox>
+        <label attach-x="3" attach-y="0"/>
         <vbox shrink-x="1" expand-x="1" fill-x="1" expand="0" fill="0" attach-x="4" attach-y="0">
             <label param="meter_outL" />
             <vumeter param="meter_outL" mode="0" hold="1.5" falloff="2.5" shrink-y="0" position="2" width="120" />
@@ -41,7 +38,12 @@
     </table>
     
     <frame attach-x="0" attach-y="1" label="Limit" expand="0" fill="1">
-        <hbox homogenous="1">
+        <hbox homogenous="1" spacing="25">
+            <vbox>
+                 <label param="bypass"/>
+                 <align><toggle param="bypass" shrink="1"/></align>
+                 <label />
+            </vbox>
             <vbox>
                 <label param="attack" />
                 <knob param="attack" size="3" />
@@ -57,6 +59,11 @@
                 <knob param="release" size="3" />
                 <value param="release" />
             </vbox>
+            <vbox>
+                 <label param="asc"/>
+                 <align><toggle param="asc"/></align>
+                 <align><led param="asc_led" /></align>
+            </vbox>
         </hbox>
     </frame>
     
diff --git a/gui/gui-multibandlimiter.xml b/gui/gui-multibandlimiter.xml
index d0657db..02dfb7c 100644
--- a/gui/gui-multibandlimiter.xml
+++ b/gui/gui-multibandlimiter.xml
@@ -109,20 +109,15 @@
         
         <frame label="Limit" expand="0" fill="1">
             <vbox spacing="20">
-                <vbox>
-                    <knob param="limit" size="5" type="2" />
-                    <value param="limit" />
-                </vbox>
                 <hbox>
-                    <vbox>
+                    <vbox spacing="0">
                         <label param="attack" />
                         <knob param="attack" />
                         <value param="attack" />
                     </vbox>
                     <vbox>
-                        <label param="minrel" />
-                        <toggle param="minrel" />
-                        <label/>
+                        <knob param="limit" size="5" type="2" />
+                        <value param="limit" />
                     </vbox>
                     <vbox>
                         <label param="release" />
@@ -130,6 +125,22 @@
                         <value param="release" />
                     </vbox>
                 </hbox>
+                
+                <hbox>
+                    <label />
+                    <vbox expand="0" fill="0" spacing="8">
+                        <label param="minrel" />
+                        <toggle param="minrel" />
+                        <label />
+                    </vbox>
+                    <label />
+                    <vbox expand="0" fill="0" spacing="8">
+                        <label param="asc" />
+                        <toggle param="asc" />
+                        <align><led param="asc_led" /></align>
+                    </vbox>
+                    <label />
+                </hbox>
             </vbox>
         </frame>
         
diff --git a/src/audio_fx.cpp b/src/audio_fx.cpp
index 024b207..decb839 100644
--- a/src/audio_fx.cpp
+++ b/src/audio_fx.cpp
@@ -551,10 +551,11 @@ lookahead_limiter::lookahead_limiter() {
     over_c = 1.f;
     attack = 0.005;
     __attack = -1;
-    pos_next = -1;
     use_multi = false;
     weight = 1.f;
     _sanitize = false;
+    auto_release = false;
+    asc_active = false;
 }
 
 void lookahead_limiter::activate()
@@ -607,7 +608,10 @@ void lookahead_limiter::set_params(float l, float a, float r, float w, bool ar,
 }
 
 void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
-{   
+{
+    // PROTIP: harming paying customers enough to make them develop a competing
+    // product may be considered an example of a less than sound business practice.
+
     // write left and right to buffer
     buffer[pos] = 0.f;
     buffer[pos + 1] = 0.f;
@@ -629,7 +633,6 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
         _delta = ((limit * multi_coeff * weight) / peak - att) / (buffer_size / channels - channels);
         if(_delta < delta) {
             delta = _delta;
-            pos_next = pos;
         }
     }
     
@@ -643,21 +646,19 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
     // output peak - impact in left or right channel?
     peak = fabs(left) > fabs(right) ? fabs(left) : fabs(right);
     
-    // we need  "and (pos == pos_next or pos_next < 0)" in the next if
-    // but that fucks up delta = release
-    // (because this screws the CPU)
-    
     // output is over the limit?
     // then we have to search for new delta.
     // the idea is to calculate a delta for every peak and always use the
     // lowest. this produces a soft transition between limiting targets without
     // passing values above limit
     
+    asc_active = false;
     if(peak > limit * multi_coeff * weight) {
         // default is to do a release
-        delta = (1.0f - att) / (srate * release);
-        pos_next = -1;
+        delta = (1.f - att) / (srate * release);
         unsigned int j;
+        float b_sum = 0.f;
+        unsigned int b_sum_c = 0;
         for(unsigned int i = channels; i < buffer_size; i += channels) {
             // iterate over buffer (except input and output pointer positions)
             // and search for maximum slope
@@ -670,12 +671,22 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
                 // if slope is steeper, use it, fucker.
                 if(_delta < delta) {
                     delta = _delta;
-                    pos_next = j;
                 }
+                b_sum += _peak;
+                b_sum_c ++;
             }
         }
+        if(auto_release) {
+            // This is Auto-Smoothness-Control (wink wink, nudge nudge)
+            // check if releasing to average level of peaks is steeper than
+            // releasing to 1.f
+            _delta = ((limit * weight) / (float)(b_sum / b_sum_c) - att) / (srate * release);
+            asc_active = _delta < delta ? true : false;
+            delta = _delta < delta ? _delta : delta;
+        } else {
+            asc_active = false;
+        }
     }
-    
     // change the attenuation level
     att += delta;
     // ...and calculate outpout from it
@@ -725,3 +736,7 @@ void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
     pos = (pos + channels) % buffer_size;
     if(pos == 0) _sanitize = false;
 }
+
+bool lookahead_limiter::get_arc() {
+    return asc_active;
+}
diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index 5d23849..33c3ebf 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -567,7 +567,6 @@ public:
 
 
 /// Lookahead Limiter by Markus Schmidt and Christian Holschuh
-
 class lookahead_limiter {
 private:
 public:
@@ -582,6 +581,7 @@ public:
     bool is_active;
     bool debug;
     bool auto_release;
+    bool asc_active;
     float *buffer;
     int channels;
     float delta;
@@ -589,7 +589,6 @@ public:
     float peak;
     unsigned int over_s;
     float over_c;
-    int pos_next;
     bool use_multi;
     unsigned int id;
     bool _sanitize;
@@ -597,6 +596,7 @@ public:
 	    *f += 1e-18;
 	    *f -= 1e-18;
     }
+    bool get_arc();
     lookahead_limiter();
     void set_multi(bool set);
     void process(float &left, float &right, float *multi_buffer);
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index 85eff76..5ffcea6 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -239,6 +239,7 @@ struct limiter_metadata: public plugin_metadata<limiter_metadata>
            STEREO_VU_METER_PARAMS,
            param_limit, param_attack, param_release,
            param_att,
+           param_asc, param_asc_led,
            param_count };
     PLUGIN_NAME_ID_LABEL("limiter", "limiter", "Limiter")
 };
@@ -258,7 +259,8 @@ struct multibandlimiter_metadata: public plugin_metadata<multibandlimiter_metada
            param_weight0, param_weight1, param_weight2, param_weight3, 
            param_release0, param_release1, param_release2, param_release3,
            param_solo0, param_solo1, param_solo2, param_solo3,
-           param_effrelease0, param_effrelease1, param_effrelease2, param_effrelease3, 
+           param_effrelease0, param_effrelease1, param_effrelease2, param_effrelease3,
+           param_asc, param_asc_led,
            param_count };
     PLUGIN_NAME_ID_LABEL("multiband_limiter", "multibandlimiter", "Multiband Limiter")
 };
diff --git a/src/calf/modules_limit.h b/src/calf/modules_limit.h
index 3c6c3f6..74bfe19 100644
--- a/src/calf/modules_limit.h
+++ b/src/calf/modules_limit.h
@@ -36,7 +36,7 @@ namespace calf_plugins {
 class limiter_audio_module: public audio_module<limiter_metadata>, public line_graph_iface {
 private:
     typedef limiter_audio_module AM;
-    uint32_t clip_inL, clip_inR, clip_outL, clip_outR;
+    uint32_t clip_inL, clip_inR, clip_outL, clip_outR, asc_led;
     int mode, mode_old;
     float meter_inL, meter_inR, meter_outL, meter_outR;
     dsp::lookahead_limiter limiter;
@@ -56,7 +56,7 @@ class multibandlimiter_audio_module: public audio_module<multibandlimiter_metada
 private:
     typedef multibandlimiter_audio_module AM;
     static const int strips = 4;
-    uint32_t clip_inL, clip_inR, clip_outL, clip_outR;
+    uint32_t clip_inL, clip_inR, clip_outL, clip_outR, asc_led;
     int mode, mode_old;
     bool solo[strips];
     bool no_solo;
diff --git a/src/metadata.cpp b/src/metadata.cpp
index 42d3c22..b7172fb 100644
--- a/src/metadata.cpp
+++ b/src/metadata.cpp
@@ -514,6 +514,10 @@ CALF_PORT_PROPS(limiter) = {
     
     { 1,           0.125,     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, "att", "Attenuation" },
     
+    { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "asc", "ASC" },
+    
+    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "asc_led", "asc active" },
+    
     {}
 };
 
@@ -580,6 +584,11 @@ CALF_PORT_PROPS(multibandlimiter) = {
     { 1,         0.f,        1000,  0,  PF_FLOAT | PF_UNIT_MSEC | PF_PROP_OUTPUT, NULL, "effrelease1", "Effectively Release 2" },
     { 1,         0.f,        1000,  0,  PF_FLOAT | PF_UNIT_MSEC | PF_PROP_OUTPUT, NULL, "effrelease2", "Effectively Release 3" },
     { 1,         0.f,        1000,  0,  PF_FLOAT | PF_UNIT_MSEC | PF_PROP_OUTPUT, NULL, "effrelease3", "Effectively Release 4" },
+    
+    { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "asc", "ASC" },
+    
+    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "asc_led", "asc active" },
+    
     {}
 };
 
diff --git a/src/modules_limit.cpp b/src/modules_limit.cpp
index 9126cee..05f2176 100644
--- a/src/modules_limit.cpp
+++ b/src/modules_limit.cpp
@@ -47,6 +47,7 @@ limiter_audio_module::limiter_audio_module()
     meter_inR  = 0.f;
     meter_outL = 0.f;
     meter_outR = 0.f;
+    asc_led    = 0.f;
 }
 
 void limiter_audio_module::activate()
@@ -65,7 +66,7 @@ void limiter_audio_module::deactivate()
 
 void limiter_audio_module::params_changed()
 {
-    limiter.set_params(*params[param_limit], *params[param_attack], *params[param_release], 1.f, true, true);
+    limiter.set_params(*params[param_limit], *params[param_attack], *params[param_release], 1.f, *params[param_asc], true);
 }
 
 void limiter_audio_module::set_sample_rate(uint32_t sr)
@@ -94,6 +95,7 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
         meter_inR  = 0.f;
         meter_outL = 0.f;
         meter_outR = 0.f;
+        asc_led    = 0.f;
     } else {
         // let meters fall a bit
         clip_inL    -= std::min(clip_inL,  numsamples);
@@ -104,6 +106,8 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
         meter_inR = 0.f;
         meter_outL = 0.f;
         meter_outR = 0.f;
+        asc_led   -= std::min(asc_led, numsamples);
+        
         while(offset < numsamples) {
             // cycle through samples
             float inL = ins[0][offset];
@@ -118,6 +122,8 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
             // process gain reduction
             float fickdich[0];
             limiter.process(outL, outR, fickdich);
+            if(limiter.get_arc())
+                asc_led = srate >> 3;
             
             // autolevel
             outL /= *params[param_limit];
@@ -173,6 +179,8 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
     SET_IF_CONNECTED(meter_outL);
     SET_IF_CONNECTED(meter_outR);
     
+    if (params[param_asc_led] != NULL) *params[param_asc_led] = asc_led;
+     
     if (*params[param_att]) {
         if(bypass)
             *params[param_att] = 1.f;
@@ -205,6 +213,7 @@ multibandlimiter_audio_module::multibandlimiter_audio_module()
     meter_inR  = 0.f;
     meter_outL = 0.f;
     meter_outR = 0.f;
+    asc_led    = 0.f;
     __attack = -1.f;
     channels = 2;
     buffer_size = 0;
@@ -320,24 +329,24 @@ void multibandlimiter_audio_module::params_changed()
     rel = *params[param_release] *  pow(0.25, *params[param_release0] * -1);
     rel = (*params[param_minrel] > 0.5) ? std::max(2500 * (1.f / 30), rel) : rel;
     weight[0] = pow(0.25, *params[param_weight0] * -1);
-    strip[0].set_params(*params[param_limit], *params[param_attack], rel, weight[0], true, true);
+    strip[0].set_params(*params[param_limit], *params[param_attack], rel, weight[0], *params[param_asc], true);
     *params[param_effrelease0] = rel;
     rel = *params[param_release] *  pow(0.25, *params[param_release1] * -1);
     rel = (*params[param_minrel] > 0.5) ? std::max(2500 * (1.f / *params[param_freq0]), rel) : rel;
     weight[1] = pow(0.25, *params[param_weight1] * -1);
-    strip[1].set_params(*params[param_limit], *params[param_attack], rel, weight[1], true);
+    strip[1].set_params(*params[param_limit], *params[param_attack], rel, weight[1], *params[param_asc]);
     *params[param_effrelease1] = rel;
     rel = *params[param_release] *  pow(0.25, *params[param_release2] * -1);
     rel = (*params[param_minrel] > 0.5) ? std::max(2500 * (1.f / *params[param_freq1]), rel) : rel;
     weight[2] = pow(0.25, *params[param_weight2] * -1);
-    strip[2].set_params(*params[param_limit], *params[param_attack], rel, weight[2], true);
+    strip[2].set_params(*params[param_limit], *params[param_attack], rel, weight[2], *params[param_asc]);
     *params[param_effrelease2] = rel;
     rel = *params[param_release] *  pow(0.25, *params[param_release3] * -1);
     rel = (*params[param_minrel] > 0.5) ? std::max(2500 * (1.f / *params[param_freq2]), rel) : rel;
     weight[3] = pow(0.25, *params[param_weight3] * -1);
-    strip[3].set_params(*params[param_limit], *params[param_attack], rel, weight[3], true);
+    strip[3].set_params(*params[param_limit], *params[param_attack], rel, weight[3], *params[param_asc]);
     *params[param_effrelease3] = rel;
-    broadband.set_params(*params[param_limit], *params[param_attack], rel, 1.f);
+    broadband.set_params(*params[param_limit], *params[param_attack], rel, 1.f, *params[param_asc]);
     // rebuild multiband buffer
     if( *params[param_attack] != __attack) {
         int bs = (int)(srate * (*params[param_attack] / 1000.f) * channels);
@@ -392,6 +401,7 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
         meter_inR  = 0.f;
         meter_outL = 0.f;
         meter_outR = 0.f;
+        asc_led    = 0.f;
     } else {
         // process all strips
         
@@ -400,6 +410,7 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
         clip_inR    -= std::min(clip_inR,  numsamples);
         clip_outL   -= std::min(clip_outL, numsamples);
         clip_outR   -= std::min(clip_outR, numsamples);
+        asc_led     -= std::min(asc_led, numsamples);
         meter_inL = 0.f;
         meter_inR = 0.f;
         meter_outL = 0.f;
@@ -437,6 +448,7 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
             float right;
             float sum_left = 0.f;
             float sum_right = 0.f;
+            bool asc_active = false;
             for (int i = 0; i < strips; i++) {
                 left  = inL;
                 right = inR;
@@ -489,6 +501,7 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
                     outL += _tmpL[i];
                     outR += _tmpR[i];
                 }
+                asc_active = asc_active || strip[i].get_arc();
             } // process single strip again for limiter
             float fickdich[0];
             broadband.process(outL, outR, fickdich);
@@ -532,6 +545,9 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
             if(outR > meter_outR) {
                 meter_outR = outR;
             }
+            if(asc_active)  {
+                asc_led = srate >> 3;
+            }
             // next sample
             ++offset;
             pos = (pos + channels) % buffer_size;
@@ -549,6 +565,9 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
     SET_IF_CONNECTED(meter_inR);
     SET_IF_CONNECTED(meter_outL);
     SET_IF_CONNECTED(meter_outR);
+    
+    if (params[param_asc_led] != NULL) *params[param_asc_led] = asc_led;
+    
     // draw strip meters
     if(bypass > 0.5f) {
         if(params[param_att0] != NULL) *params[param_att0] = 1.0;

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list