[SCM] calf/master: Next portion of changes from Markus: optimized multiband limiter + other stuff.

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


The following commit has been merged in the master branch:
commit 75ad38da634f7ffd16886ee197715b01fab994ed
Author: Markus Schmidt <schmidt at boomshop.net>
Date:   Sat Jan 28 21:24:04 2012 +0000

    Next portion of changes from Markus: optimized multiband limiter + other stuff.

diff --git a/gui/gui-bassenhancer.xml b/gui/gui-bassenhancer.xml
index 302a1e1..21afc48 100644
--- a/gui/gui-bassenhancer.xml
+++ b/gui/gui-bassenhancer.xml
@@ -52,6 +52,12 @@
                 <knob param="freq" size="5" />
                 <value param="freq" />
             </vbox>
+            <vbox>
+                <label param="floor" />
+                <toggle param="floor_active" size="1" />
+                <knob param="floor" size="3" />
+                <value param="floor" width="5" />
+            </vbox>
         </hbox>
     </frame>
 </vbox>
diff --git a/gui/gui-enhancer.xml b/gui/gui-enhancer.xml
index 20695ae..799b086 100644
--- a/gui/gui-enhancer.xml
+++ b/gui/gui-enhancer.xml
@@ -35,7 +35,6 @@
                 <knob param="drive" size="5" />
                 <value param="drive" />
             </vbox>
-            
             <vbox spacing="5">
                 <label param="blend" />
                 <hscale param="blend" />
@@ -46,12 +45,17 @@
                 <label param="meter_drive" />
                 <vumeter param="meter_drive" hold="1.5" falloff="2.5" />
             </vbox>
-            
             <vbox>
                 <label param="freq" />
-                <knob param="freq" size="5" />
+                <knob param="freq" size="2" />
                 <value param="freq" />
             </vbox>
+            <vbox>
+                <label param="floor" />
+                <knob param="floor" size="3" />
+                <value param="floor" />
+                <toggle param="floor_active" />
+            </vbox>
         </hbox>
     </frame>
 </vbox>
diff --git a/gui/gui-exciter.xml b/gui/gui-exciter.xml
index 673603b..ae5e6d0 100644
--- a/gui/gui-exciter.xml
+++ b/gui/gui-exciter.xml
@@ -52,6 +52,13 @@
                 <knob param="freq" size="5" />
                 <value param="freq" />
             </vbox>
+            
+            <vbox>
+                <label param="ceil" />
+                <toggle param="ceil_active" size="1" />
+                <knob param="ceil" size="3" />
+                <value param="ceil" width="5" />
+            </vbox>
         </hbox>
     </frame>
 </vbox>
diff --git a/gui/gui-limiter.xml b/gui/gui-limiter.xml
index 2d678b2..5971a01 100644
--- a/gui/gui-limiter.xml
+++ b/gui/gui-limiter.xml
@@ -36,7 +36,7 @@
             <value param="level_out" />
         </vbox>
     </table>
-    
+
     <frame attach-x="0" attach-y="1" label="Limit" expand="0" fill="1">
         <hbox homogenous="1" spacing="25">
             <vbox>
@@ -61,14 +61,17 @@
             </vbox>
             <vbox>
                  <label param="asc"/>
-                 <align><toggle param="asc"/></align>
-                 <align><led param="asc_led" /></align>
+                 <align><toggle param="asc" /></align>
+                 <hbox>
+                    <knob param="asc_coeff" size="1" type="1" />
+                    <align><led param="asc_led" /></align>
+                </hbox>
             </vbox>
         </hbox>
     </frame>
-    
+
     <frame attach-x="0" attach-y="2" label="Attenuation" expand="1" fill="1">
         <vumeter param="att" mode="2" hold="1.5" falloff="2.5" position="2" />
     </frame>
-    
-</table>    
+
+</table>
diff --git a/gui/gui-multibandcompressor.xml b/gui/gui-multibandcompressor.xml
index e7dc6b8..e576ffa 100644
--- a/gui/gui-multibandcompressor.xml
+++ b/gui/gui-multibandcompressor.xml
@@ -1,17 +1,17 @@
 <table rows="2" cols="1">
-    <table attach-x="0" attach-y="0" expand-y="0" expand-x="1" spacing="5" rows="1" cols="11">
+    <table attach-x="0" attach-y="0" expand-y="0" expand-x="1" spacing="4" rows="1" cols="11">
         <vbox shrink-x="1" expand-x="0" fill-x="0" expand="0" fill="0" attach-x="0" attach-y="0">
             <label param="level_in" />
-            <knob param="level_in" size="4" />
+            <knob param="level_in" size="3" />
             <value param="level_in" />
         </vbox>
-        <vbox shrink-x="1" expand-x="1" fill-x="1" expand="0" fill="0" attach-x="1" attach-y="0" pad-y="24">
+        <vbox shrink-x="1" expand-x="1" fill-x="1" expand="0" fill="0" attach-x="1" attach-y="0" pad-y="12">
             <label param="meter_inL" />
             <vumeter param="meter_inL" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <vumeter param="meter_inR" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <label param="meter_inR" />
         </vbox>
-        <vbox shrink-x="1" expand-x="0" fill-x="0" expand="0" fill="0" attach-x="2" attach-y="0" pad-y="24">
+        <vbox shrink-x="1" expand-x="0" fill-x="0" expand="0" fill="0" attach-x="2" attach-y="0" pad-y="12">
             <label text="0dB" expand="0" fill="0" />
             <led param="clip_inL" expand="0" fill="0" />
             <led param="clip_inR" expand="0" fill="0" />
@@ -23,16 +23,16 @@
                     <knob param="freq0" attach-x="0" attach-y="0" border="0" expand="0" fill="0" expand-x="0" fill-x="0" />
                     <vbox attach-x="1" attach-y="0" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0">
                         <label param="freq0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
-                        <value param="freq0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
+                        <value param="freq0" width="8" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
                     </vbox>
                     <hbox  attach-x="0" attach-y="1" border="0" fill-x="0">
                         <knob param="sep0" type="1" size="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
-                        <label param="sep0" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
+                        <label param="sep0" width="5" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
                     </hbox>
                     <value param="sep0" attach-x="1" attach-y="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" width="2" align-x="0.0" />
                     <hbox  attach-x="0" attach-y="2" border="0" fill-x="0">
                         <knob param="q0" type="1" size="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
-                        <label param="q0" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
+                        <label param="q0" width="5" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
                     </hbox>
                     <value param="q0" attach-x="1" attach-y="2" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" width="2" align-x="0.0" />
                 </table>
@@ -40,16 +40,16 @@
                     <knob param="freq1" attach-x="0" attach-y="0" border="0" expand="0" fill="0" expand-x="0" fill-x="0" />
                     <vbox attach-x="1" attach-y="0" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0">
                         <label param="freq1" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
-                        <value param="freq1" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" width="2" align-x="0.0" />
+                        <value param="freq1" width="8" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
                     </vbox>
                     <hbox  attach-x="0" attach-y="1" border="0" fill-x="0">
                         <knob param="sep1" type="1" size="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
-                        <label param="sep1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
+                        <label param="sep1" width="5" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
                     </hbox>
                     <value param="sep1" attach-x="1" attach-y="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" width="2" align-x="0.0" />
                     <hbox  attach-x="0" attach-y="2" border="0" fill-x="0">
                         <knob param="q1" type="1" size="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
-                        <label param="q1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
+                        <label param="q1" width="5" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
                     </hbox>
                     <value param="q1" attach-x="1" attach-y="2" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" width="2" align-x="0.0" />
                 </table>
@@ -57,16 +57,16 @@
                     <knob param="freq2" attach-x="0" attach-y="0" border="0" expand="0" fill="0" expand-x="0" fill-x="0" />
                     <vbox attach-x="1" attach-y="0" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0">
                         <label param="freq2" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
-                        <value param="freq2" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
+                        <value param="freq2" width="8" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" align-x="0.0" />
                     </vbox>
                     <hbox  attach-x="0" attach-y="1" border="0" fill-x="0">
                         <knob param="sep2" type="1" size="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
-                        <label param="sep2" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
+                        <label param="sep2" width="5" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
                     </hbox>
                     <value param="sep2" attach-x="1" attach-y="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" width="2" align-x="0.0" />
                     <hbox  attach-x="0" attach-y="2" border="0" fill-x="0">
                         <knob param="q2" type="1" size="1" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
-                        <label param="q2" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
+                        <label param="q2" width="5" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" />
                     </hbox>
                     <value param="q2" attach-x="1" attach-y="2" border="0" expand="0" fill="0" expand-y="0" fill-y="0" expand-x="0" fill-x="0" width="2" align-x="0.0" />
                 </table>
@@ -76,13 +76,13 @@
                 <combo param="mode" />
             </hbox>
         </vbox>
-        <vbox shrink-x="1" expand-x="1" fill-x="1" expand="0" fill="0" attach-x="7" attach-y="0" pad-y="24">
+        <vbox shrink-x="1" expand-x="1" fill-x="1" expand="0" fill="0" attach-x="7" attach-y="0" pad-y="12">
             <label param="meter_outL" />
             <vumeter param="meter_outL" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <vumeter param="meter_outR" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <label param="meter_outR" />
         </vbox>
-        <vbox shrink-x="1" expand-x="0" fill-x="0" expand="0" fill="0" attach-x="8" attach-y="0" pad-y="24">
+        <vbox shrink-x="1" expand-x="0" fill-x="0" expand="0" fill="0" attach-x="8" attach-y="0" pad-y="12">
             <label text="0dB" expand="0" fill="0" />
             <led param="clip_outL" expand="0" mode="1" fill="0" />
             <led param="clip_outR" expand="0" mode="1" fill="0" />
@@ -90,254 +90,222 @@
         </vbox>
         <vbox shrink-x="1" expand-x="0" fill-x="0" expand="0" fill="0" attach-x="9" attach-y="0">
             <label param="level_out" />
-            <knob param="level_out" size="4" />
+            <knob param="level_out" size="3" />
             <value param="level_out" />
         </vbox>
-        <vbox expand="0" attach-x="10" attach-y="0" expand-x="0" fill-x="0" fill="0" pad-x="6" pad-y="21">
+        <vbox expand="0" attach-x="10" attach-y="0" expand-x="0" fill-x="0" fill="0" pad-x="6" pad-y="10">
              <label param="bypass"/>
              <align><toggle param="bypass" shrink="1"/></align>
         </vbox>
     </table>
     <table attach-x="0" attach-y="1" expand-y="1" shrink-y="1" expand-x="1" shrink-x="1" fill="1" rows="1" cols="4">
-        <frame label="Sub band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="0" attach-y="0" fill="1" pad-x="4"><vbox>
+        <frame label="Sub band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="0" attach-y="0" fill="1" pad-x="4"><vbox spacing="4">
             <if cond="directlink">
-                <line-graph refresh="1" width="220" height="220" param="compression0" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
+                <line-graph refresh="1" width="200" height="200" param="compression0" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
             </if>
+            <vumeter param="compression0" position="2" mode="2" hold="1.5" falloff="2.5" />
+            <vumeter param="output0" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <table shrink-y="1" expand-x="1" expand="0" cols="3" rows="1" fill-x="1">
                 <label param="detection0" attach-x="0" attach-y="0" shrink-x="1"/>
                 <label attach-x="1" attach-y="0" shrink-x="1" pad-x="5"/>
                 <combo param="detection0" attach-x="2" attach-y="0" fill-x="1" />
             </table>
-            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
+            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="4">
+                <vbox expand="0" attach-x="0" attach-y="0" spacing="4">
                     <label param="attack0" />
                     <knob param="attack0" />
                     <value param="attack0" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
+                <vbox expand="0" attach-x="1" attach-y="0" spacing="4">
                     <label param="release0" />
                     <knob param="release0" />
                     <value param="release0" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="0">
+                <vbox expand="0" attach-x="2" attach-y="0" spacing="4">
                     <label param="knee0" />
                     <knob param="knee0" />
                     <value param="knee0" />
                 </vbox>
-                <vbox expand="0" attach-x="0" attach-y="1">
+                <vbox expand="0" attach-x="0" attach-y="1" spacing="4">
                     <label param="threshold0" />
                     <knob param="threshold0"/>
                     <value param="threshold0" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="1">
+                <vbox expand="0" attach-x="1" attach-y="1" spacing="4">
                     <label param="ratio0" />
                     <knob param="ratio0" />
                     <value param="ratio0" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="1">
+                <vbox expand="0" attach-x="2" attach-y="1" spacing="4">
                     <label param="makeup0" />
                     <knob param="makeup0" />
                     <value param="makeup0" />
                 </vbox>
             </table>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <label param="compression0" />
-                <vumeter param="compression0" position="2" mode="2" hold="1.5" falloff="2.5" />
-            </vbox>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <vumeter param="output0" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
-                <label param="output0" />
-            </vbox>
-            <table expand-y="0" expand-x="1" cols="3" rows="1" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
-                     <label param="bypass0"/>
-                     <align><toggle size="1" param="bypass0" shrink="1"/></align>
-                </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
-                     <label param="solo0"/>
-                     <align><toggle size="1" param="solo0" shrink="1"/></align>
-                </vbox>
-            </table>
+            <label />
+            <hbox spacing="4">
+                <toggle size="1" param="bypass0" shrink="1"/>
+                <label param="bypass0"/>
+                <label />
+                <label param="solo0"/>
+                <toggle size="1" param="solo0" shrink="1"/>
+            </hbox>
         </vbox></frame>
-        <frame label="Low band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="1" attach-y="0" fill="1" pad-x="4"><vbox>
+        <frame label="Low band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="1" attach-y="0" fill="1" pad-x="4"><vbox spacing="4">
             <if cond="directlink">
-                <line-graph refresh="1" width="220" height="220" param="compression1" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
+                <line-graph refresh="1" width="200" height="200" param="compression1" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
             </if>
+            <vumeter param="compression1" position="2" mode="2" hold="1.5" falloff="2.5" />
+            <vumeter param="output1" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <table shrink-y="1" expand-x="1" expand="0" cols="3" rows="1" fill-x="1">
                 <label param="detection1" attach-x="0" attach-y="0" shrink-x="1"/>
                 <label attach-x="1" attach-y="0" shrink-x="1" pad-x="5"/>
                 <combo param="detection1" attach-x="2" attach-y="0" fill-x="1" />
             </table>
-            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
+            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="4">
+                <vbox expand="0" attach-x="0" attach-y="0" spacing="4">
                     <label param="attack1" />
                     <knob param="attack1" />
                     <value param="attack1" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
+                <vbox expand="0" attach-x="1" attach-y="0" spacing="4">
                     <label param="release1" />
                     <knob param="release1" />
                     <value param="release1" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="0">
+                <vbox expand="0" attach-x="2" attach-y="0" spacing="4">
                     <label param="knee1" />
                     <knob param="knee1" />
                     <value param="knee1" />
                 </vbox>
-                <vbox expand="0" attach-x="0" attach-y="1">
+                <vbox expand="0" attach-x="0" attach-y="1" spacing="4">
                     <label param="threshold1" />
                     <knob param="threshold1"/>
                     <value param="threshold1" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="1">
+                <vbox expand="0" attach-x="1" attach-y="1" spacing="4">
                     <label param="ratio1" />
                     <knob param="ratio1" />
                     <value param="ratio1" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="1">
+                <vbox expand="0" attach-x="2" attach-y="1" spacing="4">
                     <label param="makeup1" />
                     <knob param="makeup1" />
                     <value param="makeup1" />
                 </vbox>
             </table>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <label param="compression1" />
-                <vumeter param="compression1" position="2" mode="2" hold="1.5" falloff="2.5" />
-            </vbox>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <vumeter param="output1" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
-                <label param="output1" />
-            </vbox>
-            <table expand-y="0" expand-x="1" cols="3" rows="1" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
-                     <label param="bypass1"/>
-                     <align><toggle size="1" param="bypass1" shrink="1"/></align>
-                </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
-                     <label param="solo1"/>
-                     <align><toggle size="1" param="solo1" shrink="1"/></align>
-                </vbox>
-            </table>
+            <label />
+            <hbox spacing="4">
+                <toggle size="1" param="bypass1" shrink="1"/>
+                <label param="bypass1"/>
+                <label />
+                <label param="solo1"/>
+                <toggle size="1" param="solo1" shrink="1"/>
+            </hbox>
         </vbox></frame>
-        <frame label="Mid band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="2" attach-y="0" fill="1" pad-x="4"><vbox>
+        <frame label="Mid band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="2" attach-y="0" fill="1" pad-x="4"><vbox spacing="4">
             <if cond="directlink">
-                <line-graph refresh="1" width="220" height="220" param="compression2" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
+                <line-graph refresh="1" width="200" height="200" param="compression2" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
             </if>
+            <vumeter param="compression2" position="2" mode="2" hold="1.5" falloff="2.5" />
+            <vumeter param="output2" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <table shrink-y="1" expand-x="1" expand="0" cols="3" rows="1" fill-x="1">
                 <label param="detection2" attach-x="0" attach-y="0" shrink-x="1"/>
                 <label attach-x="1" attach-y="0" shrink-x="1" pad-x="5"/>
                 <combo param="detection2" attach-x="2" attach-y="0" fill-x="1" />
             </table>
-            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
+            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="4">
+                <vbox expand="0" attach-x="0" attach-y="0" spacing="4">
                     <label param="attack2" />
                     <knob param="attack2" />
                     <value param="attack2" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
+                <vbox expand="0" attach-x="1" attach-y="0" spacing="4">
                     <label param="release2" />
                     <knob param="release2" />
                     <value param="release2" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="0">
+                <vbox expand="0" attach-x="2" attach-y="0" spacing="4">
                     <label param="knee2" />
                     <knob param="knee2" />
                     <value param="knee2" />
                 </vbox>
-                <vbox expand="0" attach-x="0" attach-y="1">
+                <vbox expand="0" attach-x="0" attach-y="1" spacing="4">
                     <label param="threshold2" />
                     <knob param="threshold2"/>
                     <value param="threshold2" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="1">
+                <vbox expand="0" attach-x="1" attach-y="1" spacing="4">
                     <label param="ratio2" />
                     <knob param="ratio2" />
                     <value param="ratio2" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="1">
+                <vbox expand="0" attach-x="2" attach-y="1" spacing="4">
                     <label param="makeup2" />
                     <knob param="makeup2" />
                     <value param="makeup2" />
                 </vbox>
             </table>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <label param="compression2" />
-                <vumeter param="compression2" position="2" mode="2" hold="1.5" falloff="2.5" />
-            </vbox>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <vumeter param="output2" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
-                <label param="output2" />
-            </vbox>
-            <table expand-y="0" expand-x="1" cols="3" rows="1" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
-                     <label param="bypass2"/>
-                     <align><toggle size="1" param="bypass2" shrink="1"/></align>
-                </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
-                     <label param="solo2"/>
-                     <align><toggle size="1" param="solo2" shrink="1"/></align>
-                </vbox>
-            </table>
+            <label />
+            <hbox spacing="4">
+                <toggle size="1" param="bypass2" shrink="1"/>
+                <label param="bypass2"/>
+                <label />
+                <label param="solo2"/>
+                <toggle size="1" param="solo2" shrink="1"/>
+            </hbox>
         </vbox></frame>
-        <frame label="High band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="3" attach-y="0" fill="1" pad-x="4"><vbox>
+        <frame label="High band" expand-x="1" expand-y="1" shrink-x="1" shrink-y="1" attach-x="3" attach-y="0" fill="1" pad-x="4"><vbox spacing="4">
             <if cond="directlink">
-                <line-graph refresh="1" width="220" height="220" param="compression3" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
+                <line-graph refresh="1" width="200" height="200" param="compression3" expand-y="1" fill-y="1" expand-x="1" fill-x="1"/>
             </if>
+            <vumeter param="compression3" position="2" mode="2" hold="1.5" falloff="2.5" />
+            <vumeter param="output3" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
             <table shrink-y="1" expand-x="1" expand="0" cols="3" rows="1" fill-x="1">
                 <label param="detection3" attach-x="0" attach-y="0" shrink-x="1"/>
                 <label attach-x="1" attach-y="0" shrink-x="1" pad-x="5"/>
                 <combo param="detection3" attach-x="2" attach-y="0" fill-x="1"/>
             </table>
-            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
+            <table homogeneous="1" expand-y="0" expand-x="1" cols="3" rows="2" spacing="4">
+                <vbox expand="0" attach-x="0" attach-y="0" spacing="4">
                     <label param="attack3" />
                     <knob param="attack3" />
                     <value param="attack3" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
+                <vbox expand="0" attach-x="1" attach-y="0" spacing="4">
                     <label param="release3" />
                     <knob param="release3" />
                     <value param="release3" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="0">
+                <vbox expand="0" attach-x="2" attach-y="0" spacing="4">
                     <label param="knee3" />
                     <knob param="knee3" />
                     <value param="knee3" />
                 </vbox>
-                <vbox expand="0" attach-x="0" attach-y="1">
+                <vbox expand="0" attach-x="0" attach-y="1" spacing="4">
                     <label param="threshold3" />
                     <knob param="threshold3"/>
                     <value param="threshold3" />
                 </vbox>
-                <vbox expand="0" attach-x="1" attach-y="1">
+                <vbox expand="0" attach-x="1" attach-y="1" spacing="4">
                     <label param="ratio3" />
                     <knob param="ratio3" />
                     <value param="ratio3" />
                 </vbox>
-                <vbox expand="0" attach-x="2" attach-y="1">
+                <vbox expand="0" attach-x="2" attach-y="1" spacing="4">
                     <label param="makeup3" />
                     <knob param="makeup3" />
                     <value param="makeup3" />
                 </vbox>
             </table>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <label param="compression3" />
-                <vumeter param="compression3" position="2" mode="2" hold="1.5" falloff="2.5" />
-            </vbox>
-            <vbox expand-x="1" fill-x="1" expand="1" fill="1">
-                <vumeter param="output3" position="2" mode="0" hold="1.5" falloff="2.5" shrink-y="0" />
-                <label param="output3" />
-            </vbox>
-            <table expand-y="0" expand-x="1" cols="3" rows="1" spacing="5">
-                <vbox expand="0" attach-x="0" attach-y="0">
-                     <label param="bypass3"/>
-                     <align><toggle size="1" param="bypass3" shrink="1"/></align>
-                </vbox>
-                <vbox expand="0" attach-x="1" attach-y="0">
-                     <label param="solo3"/>
-                     <align><toggle size="1" param="solo3" shrink="1"/></align>
-                </vbox>
-            </table>
+            <label />
+            <hbox spacing="4">
+                <toggle size="1" param="bypass3" shrink="1"/>
+                <label param="bypass3"/>
+                <label />
+                <label param="solo3"/>
+                <toggle size="1" param="solo3" shrink="1"/>
+            </hbox>
         </vbox></frame>
     </table>
 </table>    
diff --git a/gui/gui-multibandlimiter.xml b/gui/gui-multibandlimiter.xml
index 02dfb7c..cb57936 100644
--- a/gui/gui-multibandlimiter.xml
+++ b/gui/gui-multibandlimiter.xml
@@ -39,9 +39,9 @@
             <value param="level_out" />
         </vbox>
     </table>
-    
+
     <hbox attach-x="0" attach-y="1" expand-y="1" expand-x="1" spacing="5">
-        
+
         <frame label="X-Over" expand="0" fill="1">
             <vbox>
                 <if cond="directlink">
@@ -106,7 +106,7 @@
                 </hbox>
             </vbox>
         </frame>
-        
+
         <frame label="Limit" expand="0" fill="1">
             <vbox spacing="20">
                 <hbox>
@@ -125,28 +125,30 @@
                         <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_coeff" />
+                        <knob param="asc_coeff" type="1" />
+                        <value param="asc_coeff" />
+                    </vbox>
                     <vbox expand="0" fill="0" spacing="8">
                         <label param="asc" />
                         <toggle param="asc" />
                         <align><led param="asc_led" /></align>
                     </vbox>
-                    <label />
                 </hbox>
             </vbox>
         </frame>
-        
+
         <vbox>
             <frame label="Low Band">
-            
+
                 <hbox>
                     <hbox>
                         <knob param="release0" size="2" type="1" />
@@ -260,4 +262,4 @@
             </frame>
         </vbox>
     </hbox>
-</table>    
+</table>
diff --git a/src/audio_fx.cpp b/src/audio_fx.cpp
index decb839..a5695be 100644
--- a/src/audio_fx.cpp
+++ b/src/audio_fx.cpp
@@ -15,12 +15,15 @@
  *
  * 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, 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 
 #include <calf/audio_fx.h>
 #include <calf/giface.h>
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
 
 using namespace calf_plugins;
 using namespace dsp;
@@ -37,7 +40,7 @@ simple_phaser::simple_phaser(int _max_stages, float *x1vals, float *y1vals)
     state = 0;
     cnt = 0;
     stages = 0;
-    set_stages(_max_stages);    
+    set_stages(_max_stages);
 }
 
 void simple_phaser::set_stages(int _stages)
@@ -74,7 +77,7 @@ void simple_phaser::control_step()
     v ^= sign;
     // triangle wave, range from 0 to INT_MAX
     double vf = (double)((v >> 16) * (1.0 / 16384.0) - 1);
-    
+
     float freq = base_frq * pow(2.0, vf * mod_depth / 1200.0);
     freq = dsp::clip<float>(freq, 10.0, 0.49 * sample_rate);
     stage1.set_ap_w(freq * (M_PI / 2.0) * odsr);
@@ -98,7 +101,7 @@ void simple_phaser::process(float *buf_out, float *buf_in, int nsamples)
         for (int j = 0; j < stages; j++)
             fd = stage1.process_ap(fd, x1[j], y1[j]);
         state = fd;
-        
+
         float sdry = in * gs_dry.get();
         float swet = fd * gs_wet.get();
         *buf_out++ = sdry + swet;
@@ -110,14 +113,14 @@ float simple_phaser::freq_gain(float freq, float sr) const
     typedef std::complex<double> cfloat;
     freq *= 2.0 * M_PI / sr;
     cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1
-    
+
     cfloat p = cfloat(1.0);
     cfloat stg = stage1.h_z(z);
-    
+
     for (int i = 0; i < stages; i++)
         p = p * stg;
-    
-    p = p / (cfloat(1.0) - cfloat(fb) * p);        
+
+    p = p / (cfloat(1.0) - cfloat(fb) * p);
     return std::abs(cfloat(gs_dry.get_last()) + cfloat(gs_wet.get_last()) * p);
 }
 
@@ -138,7 +141,7 @@ void biquad_filter_module::calculate_filter(float freq, float q, int mode, float
         order = mode - mode_6db_br + 1;
         left[0].set_br_rbj(freq, order * 0.1 * q, srate, gain);
     }
-    
+
     right[0].copy_coeffs(left[0]);
     for (int i = 1; i < order; i++) {
         left[i].copy_coeffs(left[0]);
@@ -168,16 +171,16 @@ int biquad_filter_module::process_channel(uint16_t channel_no, const float *in,
     case 0:
         filter = left;
         break;
-        
+
     case 1:
         filter = right;
         break;
-    
+
     default:
         assert(false);
         return 0;
     }
-    
+
     if (inmask) {
         switch(order) {
             case 1:
@@ -288,10 +291,10 @@ void reverb::update_times()
         tl[5] = 1577 << 16, tr[5] = 1881 << 16;
         break;
     }
-    
+
     float fDec=1000 + 2400.f * diffusion;
     for (int i = 0 ; i < 6; i++) {
-        ldec[i]=exp(-float(tl[i] >> 16) / fDec), 
+        ldec[i]=exp(-float(tl[i] >> 16) / fDec),
         rdec[i]=exp(-float(tr[i] >> 16) / fDec);
     }
 }
@@ -311,11 +314,11 @@ void reverb::reset()
 void reverb::process(float &left, float &right)
 {
     unsigned int ipart = phase.ipart();
-    
+
     // the interpolated LFO might be an overkill here
     int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]) >> 2;
     phase += dphase;
-    
+
     left += old_right;
     left = apL1.process_allpass_comb_lerp16(left, tl[0] - 45*lfo, ldec[0]);
     left = apL2.process_allpass_comb_lerp16(left, tl[1] + 47*lfo, ldec[1]);
@@ -337,7 +340,7 @@ void reverb::process(float &left, float &right)
     right = apR6.process_allpass_comb_lerp16(right, tr[5] - 46*lfo, rdec[5]);
     old_right = lp_right.process(right * fb);
     sanitize(old_right);
-    
+
     left = out_left, right = out_right;
 }
 
@@ -383,7 +386,7 @@ void tap_distortion::set_params(float blend, float drive)
         an = rbdr*rbdr / sq;
         imr = 2.0f * knb + D(2.0f * kna + 4.0f * an - 1.0f);
         pwrq = 2.0f / (imr + 1.0f);
-        
+
         drive_old = drive;
         blend_old = blend;
     }
@@ -550,19 +553,25 @@ lookahead_limiter::lookahead_limiter() {
     over_s = 0;
     over_c = 1.f;
     attack = 0.005;
-    __attack = -1;
     use_multi = false;
     weight = 1.f;
     _sanitize = false;
     auto_release = false;
     asc_active = false;
+    nextiter = 0;
+    nextlen = 0;
+    asc = 0.f;
+    asc_c = 0;
+    asc_pos = -1;
+    asc_changed = false;
+    asc_coeff = 1.f;
 }
 
 void lookahead_limiter::activate()
 {
     is_active = true;
     pos = 0;
-    
+
 }
 
 void lookahead_limiter::set_multi(bool set) { use_multi = set; }
@@ -587,24 +596,41 @@ void lookahead_limiter::set_sample_rate(uint32_t sr)
     buffer = (float*) calloc(overall_buffer_size, sizeof(float));
     memset(buffer, 0, overall_buffer_size * sizeof(float)); // reset buffer to zero
     pos = 0;
+
+    nextpos = (int*) calloc(overall_buffer_size, sizeof(int));
+    nextdelta = (float*) calloc(overall_buffer_size, sizeof(float));
+    memset(nextpos, -1, overall_buffer_size * sizeof(int));
 }
 
-void lookahead_limiter::set_params(float l, float a, float r, float w, bool ar, bool d)
+void lookahead_limiter::set_params(float l, float a, float r, float w, bool ar, float arc, bool d)
 {
     limit = l;
     attack = a / 1000.f;
     release = r / 1000.f;
     auto_release = ar;
+    asc_coeff = arc;
     debug = d;
     weight = w;
-    //if(debug) printf("%.5f\n", release);
-    if( attack != __attack) {
-        int bs = (int)(srate * attack * channels);
-        buffer_size = bs - bs % channels; // buffer size attack rate
-        __attack = attack;
-        _sanitize = true;
-        pos = 0;
-    }
+}
+
+void lookahead_limiter::reset() {
+    int bs = (int)(srate * attack * channels);
+    buffer_size = bs - bs % channels; // buffer size attack rate
+    _sanitize = true;
+    pos = 0;
+    nextpos[0] = -1;
+    nextlen = 0;
+    nextiter = 0;
+    delta = 0.f;
+    att = 1.f;
+    reset_asc();
+}
+
+void lookahead_limiter::reset_asc() {
+    asc = 0.f;
+    asc_c = 0;
+    asc_pos = pos;
+    asc_changed = true;
 }
 
 void lookahead_limiter::process(float &left, float &right, float * multi_buffer)
@@ -612,131 +638,192 @@ 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;
-    if(!_sanitize) {
+    // fill lookahead buffer
+    if(_sanitize) {
+        // if we're sanitizing (zeroing) the buffer on attack time change,
+        // don't write the samples to the buffer
+        buffer[pos] = 0.f;
+        buffer[pos + 1] = 0.f;
+    } else {
         buffer[pos] = left;
         buffer[pos + 1] = right;
     }
-    
-    // are we using multiband? get the multiband coefficient
+
+    // are we using multiband? get the multiband coefficient or use 1.f
     float multi_coeff = (use_multi) ? multi_buffer[pos] : 1.f;
-    //if(debug and pos%10 == 0) printf("%03d: %.5f\n", pos, multi_buffer[pos]);
-    
-    // input peak - impact in left or right channel?
+
+    // input peak - impact higher in left or right channel?
     peak = fabs(left) > fabs(right) ? fabs(left) : fabs(right);
-    
-    // if we have a peak in input over our limit, check if delta to reach is
-    // more important than actual delta
-    if(peak > limit * multi_coeff * weight or multi_coeff < 1.f) {
-        _delta = ((limit * multi_coeff * weight) / peak - att) / (buffer_size / channels - channels);
+
+    // calc the real limit including weight and multi coeff
+    float _limit = limit * multi_coeff * weight;
+
+    // add an eventually appearing peak to the asc fake buffer if asc active
+    if(auto_release and peak > _limit) {
+        asc += peak;
+        asc_c ++;
+    }
+
+    if(peak > _limit or multi_coeff < 1.0) {
+        float _multi_coeff = 1.f;
+        float _peak;
+
+        // calc the attenuation needed to reduce incoming peak
+        float _att = std::min(_limit / peak, 1.f);
+
+
+        // calc a release delta from this attenuation
+        float _rdelta = (1.0 - _att) / (srate * release);
+        if(auto_release and asc_c > 0) {
+            // check if releasing to average level of peaks is steeper than
+            // releasing to 1.f
+            float _delta = std::max((limit * weight) / (asc_coeff * asc) * (float)asc_c - _att, 0.000001f) / (srate * release);
+            if(_delta < _rdelta) {
+                asc_active = true;
+                _rdelta = _delta;
+            }
+        }
+
+        // calc the delta for walking to incoming peak attenuation
+        float _delta = (_limit / peak - att) / buffer_size * channels;
+
         if(_delta < delta) {
+            // is the delta more important than the actual one?
+            // if so, we can forget about all stored deltas (because they can't
+            // be more important - we already checked that earlier) and use this
+            // delta now. and we have to create a release delta in nextpos buffer
+            nextpos[0] = pos;
+            nextpos[1] = -1;
+            nextdelta[0] = _rdelta;
+            nextlen = 1;
+            nextiter = 0;
             delta = _delta;
+        } else {
+            // we have a peak on input its delta is less important than the
+            // actual delta. But what about the stored deltas we're following?
+            bool _found = false;
+            int i = 0;
+            for(i = nextiter; i < nextiter + nextlen; i++) {
+                // walk through our nextpos buffer
+                int j = i % buffer_size;
+                // calculate a delta for the next stored peak
+                // are we using multiband? then get the multi_coeff for the
+                // stored position
+                _multi_coeff = (use_multi) ? multi_buffer[nextpos[j]] : 1.f;
+                // is the left or the right channel on this position more
+                // important?
+                _peak = fabs(buffer[nextpos[j]]) > fabs(buffer[nextpos[j] + 1]) ? fabs(buffer[nextpos[j]]) : fabs(buffer[nextpos[j] + 1]);
+                // calc a delta to use to reach our incoming peak from the
+                // stored position
+                _delta = (_limit / peak - (limit * _multi_coeff * weight) / _peak) / (((buffer_size - nextpos[j] + pos) % buffer_size) / channels);
+                if(_delta < nextdelta[j]) {
+                    // if the buffered delta is more important than the delta
+                    // used to reach our peak from the stored position, store
+                    // the new delta at that position and stop the loop
+                    nextdelta[j] = _delta;
+                    _found = true;
+                    break;
+                }
+            }
+            if(_found) {
+                // there was something more important in the next-buffer.
+                // throw away any position and delta after the important
+                // position and add a new release delta
+                nextlen = i - nextiter + 1;
+                nextpos[(nextiter + nextlen) % buffer_size] = pos;
+                nextdelta[(nextiter + nextlen) % buffer_size] = _rdelta;
+                // set the next following position value to -1 (cleaning up the
+                // nextpos buffer)
+                nextpos[(nextiter + nextlen + 1) % buffer_size] = -1;
+                // and raise the length of our nextpos buffer for keeping the
+                // release value
+                nextlen ++;
+            }
         }
     }
-    
-    // switch left and right pointers to output
+
+    // switch left and right pointers in buffer to output position
     left = buffer[(pos + channels) % buffer_size];
     right = buffer[(pos + channels + 1) % buffer_size];
-    
-    // check multiband coefficient again for output pointer
-    multi_coeff = (use_multi) ? multi_buffer[(pos + channels) % buffer_size] : 1.f;
-    
-    // output peak - impact in left or right channel?
-    peak = fabs(left) > fabs(right) ? fabs(left) : fabs(right);
-    
-    // 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.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
-            j = (i + pos + channels) % buffer_size;
-            float _multi_coeff = (use_multi) ? multi_buffer[j] : 1.f;
-            float _peak = fabs(buffer[j]) > fabs(buffer[j + 1]) ? fabs(buffer[j]) : fabs(buffer[j + 1]);
-            // calculate steepness of slope
-            if(_peak > limit * _multi_coeff * weight) {
-                _delta = ((limit * _multi_coeff * weight) / _peak - att) / (i / channels);
-                // if slope is steeper, use it, fucker.
-                if(_delta < delta) {
-                    delta = _delta;
-                }
-                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;
-        }
+
+    // if a peak leaves the buffer, remove it from asc fake buffer
+    // but only if we're not sanitizing asc buffer
+    float _peak = fabs(left) > fabs(right) ? fabs(left) : fabs(right);
+    float _multi_coeff = (use_multi) ? multi_buffer[(pos + channels) % buffer_size] : 1.f;
+    if(pos == asc_pos and !asc_changed) {
+        asc_pos = -1;
+    }
+    if(auto_release and asc_pos == -1 and _peak > (limit * weight * _multi_coeff)) {
+        asc -= _peak;
+        asc_c --;
     }
+
     // change the attenuation level
     att += delta;
+
     // ...and calculate outpout from it
     left *= att;
     right *= att;
-    
+
+    if((pos + channels) % buffer_size == nextpos[nextiter]) {
+        // if we reach a buffered position, change the actual delta and erase
+        // this (the first) element from nextpos and nextdelta buffer
+        delta = nextdelta[nextiter];
+        nextlen = (nextlen - 1) % buffer_size;
+        nextpos[nextiter] = -1;
+        nextiter = (nextiter + 1) % buffer_size;
+    }
+
+    if (att > 1.0f) {
+        // release time seems over, reset attenuation and delta
+        att = 1.0f;
+        delta = 0.0f;
+    }
+
+    // main limiting party is over, let's cleanup the puke
+
     if(_sanitize) {
+        // we're sanitizing? then send 0.f as output
         left = 0.f;
-       right = 0.f;
+        right = 0.f;
     }
-    
-    // release time seems over
-    if (att > 1.0f) {
-	    att = 1.0f;
-	    delta = 0.0f;
-	}
 
     // security personnel pawing your values
-	if(att < 0.f) {
-	    // if this happens we're doomed!!
-	    // may happen on manually lowering attack
-	    att = 0.0000000001;
-	    delta = (1.0f - att) / (srate * release);
-	}
-	
-	if(att != 1.f and 1 - att < 0.0000000000001) {
-	    // denormalize att
-	    att = 1.f;
-	}
-	
-	if(delta != 0.f and fabs(delta) < 0.00000000000001) {
+    if(att <= 0.f) {
+        // if this happens we're doomed!!
+        // may happen on manually lowering attack
+        att = 0.0000000000001;
+        delta = (1.0f - att) / (srate * release);
+    }
+
+    if(att != 1.f and 1 - att < 0.0000000000001) {
+        // denormalize att
+        att = 1.f;
+    }
+
+    if(delta != 0.f and fabs(delta) < 0.00000000000001) {
         // denormalize delta
-	    delta = 0.f;
-	}
-	
+        delta = 0.f;
+    }
+
     // post treatment (denormal, limit)
     denormal(&left);
     denormal(&right);
-    
-    left = std::max(left, -limit * multi_coeff * weight);
-    left = std::min(left, limit * multi_coeff * weight);
-    right = std::max(right, -limit * multi_coeff * weight);
-    right = std::min(right, limit * multi_coeff * weight);
-    
-    att_max = (att < att_max) ? att : att_max; // store max atten for meter output
-    
+
+    // store max attenuation for meter output
+    att_max = (att < att_max) ? att : att_max;
+
+    // step forward in our sample ring buffer
     pos = (pos + channels) % buffer_size;
-    if(pos == 0) _sanitize = false;
+
+    // sanitizing is always done after a full cycle through the lookahead buffer
+    if(_sanitize and pos == 0) _sanitize = false;
+
+    asc_changed = false;
 }
 
-bool lookahead_limiter::get_arc() {
-    return asc_active;
+bool lookahead_limiter::get_asc() {
+    if(!asc_active) return false;
+    asc_active = false;
+    return true;
 }
diff --git a/src/calf/audio_fx.h b/src/calf/audio_fx.h
index 33c3ebf..b4db50f 100644
--- a/src/calf/audio_fx.h
+++ b/src/calf/audio_fx.h
@@ -15,7 +15,7 @@
  *
  * 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, 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 #ifndef CALF_AUDIOFX_H
@@ -60,7 +60,7 @@ public:
     }
     void set_rate(float rate) {
         this->rate = rate;
-        dphase = rate/sample_rate*4096;        
+        dphase = rate/sample_rate*4096;
     }
     float get_wet() const {
         return wet;
@@ -118,21 +118,21 @@ public:
         return stages;
     }
     void set_stages(int _stages);
-    
+
     float get_mod_depth() const {
         return mod_depth;
     }
     void set_mod_depth(float _mod_depth) {
         mod_depth = _mod_depth;
     }
-    
+
     float get_fb() const {
         return fb;
     }
     void set_fb(float fb) {
         this->fb = fb;
     }
-    
+
     virtual void setup(int sample_rate) {
         modulation_effect::setup(sample_rate);
         reset();
@@ -181,7 +181,7 @@ class simple_chorus: public chorus_base
 {
 protected:
     simple_delay<MaxDelay,T> delay;
-public:    
+public:
     simple_chorus() {
         rate = 0.63f;
         dry = 0.5f;
@@ -206,7 +206,7 @@ public:
         for (int i=0; i<nsamples; i++) {
             phase += dphase;
             unsigned int ipart = phase.ipart();
-            
+
             float in = *buf_in++;
             int lfo = phase.lerp_by_fract_int<int, 14, int>(sine.data[ipart], sine.data[ipart+1]);
             int v = mds + (mdepth * lfo >> 6);
@@ -265,16 +265,16 @@ public:
         unsigned int ipart = this->phase.ipart();
         int lfo = phase.lerp_by_fract_int<int, 14, int>(this->sine.data[ipart], this->sine.data[ipart+1]);
         delay_pos = mds + (mdepth * lfo >> 6);
-        
+
         if (delay_pos != last_delay_pos || ramp_pos < 1024)
         {
             if (delay_pos != last_delay_pos) {
-                // we need to ramp from what the delay tap length actually was, 
+                // we need to ramp from what the delay tap length actually was,
                 // not from old (ramp_delay_pos) or desired (delay_pos) tap length
                 ramp_delay_pos = last_actual_delay_pos;
                 ramp_pos = 0;
             }
-            
+
             int64_t dp = 0;
             for (int i=0; i<nsamples; i++) {
                 float in = *buf_in++;
@@ -321,7 +321,7 @@ public:
         typedef std::complex<double> cfloat;
         freq *= 2.0 * M_PI / sr;
         cfloat z = 1.0 / exp(cfloat(0.0, freq)); // z^-1
-        
+
         float ldp = last_delay_pos / 65536.0;
         float fldp = floor(ldp);
         cfloat zn = std::pow(z, fldp); // z^-N
@@ -352,7 +352,7 @@ class reverb: public audio_effect
     float time, fb, cutoff, diffusion;
     int tl[6], tr[6];
     float ldec[6], rdec[6];
-    
+
     int sr;
 public:
     reverb()
@@ -443,17 +443,17 @@ class biquad_filter_module: public filter_module_iface
 private:
     dsp::biquad_d1<float> left[3], right[3];
     int order;
-    
-public:    
+
+public:
     uint32_t srate;
-    
-    enum { mode_12db_lp = 0, mode_24db_lp = 1, mode_36db_lp = 2, 
+
+    enum { mode_12db_lp = 0, mode_24db_lp = 1, mode_36db_lp = 2,
            mode_12db_hp = 3, mode_24db_hp = 4, mode_36db_hp = 5,
            mode_6db_bp  = 6, mode_12db_bp = 7, mode_18db_bp = 8,
            mode_6db_br  = 9, mode_12db_br = 10, mode_18db_br = 11,
            mode_count
     };
-    
+
 public:
     biquad_filter_module()
     : order(0) {}
@@ -481,14 +481,14 @@ public:
         lowcut.reset();
         highcut.reset();
     }
-    
+
     inline float process(float v)
     {
         v = dsp::lerp(lowcut.process_hp(v), v, low_gain);
         v = dsp::lerp(highcut.process_lp(v), v, high_gain);
         return v;
     }
-    
+
     inline void copy_coeffs(const two_band_eq &src)
     {
         lowcut.copy_coeffs(src.lowcut);
@@ -496,13 +496,13 @@ public:
         low_gain = src.low_gain;
         high_gain = src.high_gain;
     }
-    
+
     void sanitize()
     {
         lowcut.sanitize();
         highcut.sanitize();
     }
-    
+
     void set(float _low_freq, float _low_gain, float _high_freq, float _high_gain, float sr)
     {
         lowcut.set_hp(_low_freq, sr);
@@ -571,11 +571,10 @@ class lookahead_limiter {
 private:
 public:
     float limit, attack, release, weight;
-    float __attack;
     uint32_t srate;
-    float att;
-    float att_max;
-    unsigned int pos;
+    float att; // a coefficient the output is multiplied with
+    float att_max; // a memory for the highest attenuation - used for display
+    unsigned int pos; // where we are actually in our sample buffer
     unsigned int buffer_size;
     unsigned int overall_buffer_size;
     bool is_active;
@@ -592,16 +591,27 @@ public:
     bool use_multi;
     unsigned int id;
     bool _sanitize;
+    int nextiter;
+    int nextlen;
+    int * nextpos;
+    float * nextdelta;
+    int asc_c;
+    float asc;
+    int asc_pos;
+    bool asc_changed;
+    float asc_coeff;
     static inline void denormal(volatile float *f) {
 	    *f += 1e-18;
 	    *f -= 1e-18;
     }
-    bool get_arc();
+    void reset();
+    void reset_asc();
+    bool get_asc();
     lookahead_limiter();
     void set_multi(bool set);
     void process(float &left, float &right, float *multi_buffer);
     void set_sample_rate(uint32_t sr);
-    void set_params(float l, float a, float r, float weight = 1.f, bool ar = false, bool d = false);
+    void set_params(float l, float a, float r, float weight = 1.f, bool ar = false, float arc = 1.f, bool d = false);
     float get_attenuation();
     void activate();
     void deactivate();
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index 5ffcea6..ecfd0f2 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -16,7 +16,7 @@
  *
  * 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, 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02111-1307, USA.
  */
 
@@ -89,7 +89,7 @@ public:
 /// A multitap stereo chorus thing - metadata
 struct multichorus_metadata: public plugin_metadata<multichorus_metadata>
 {
-public:    
+public:
     enum { par_delay, par_depth, par_rate, par_stereo, par_voices, par_vphase, par_amount, par_dryamount, par_freq, par_freq2, par_q, par_overlap, param_count };
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, rt_capable = true, support_midi = false, require_midi = false };
     PLUGIN_NAME_ID_LABEL("multichorus", "multichorus", "Multi Chorus")
@@ -106,12 +106,12 @@ struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
 {
     enum { wave_saw, wave_sqr, wave_pulse, wave_sine, wave_triangle, wave_varistep, wave_skewsaw, wave_skewsqr, wave_test1, wave_test2, wave_test3, wave_test4, wave_test5, wave_test6, wave_test7, wave_test8, wave_count };
     enum { flt_lp12, flt_lp24, flt_2lp12, flt_hp12, flt_lpbr, flt_hpbr, flt_bp6, flt_2bp6 };
-    enum { par_wave1, par_wave2, par_pw1, par_pw2, par_detune, par_osc2xpose, par_oscmode, par_oscmix, par_filtertype, par_cutoff, par_resonance, par_cutoffsep, par_env1tocutoff, par_env1tores, par_env1toamp, 
-        par_env1attack, par_env1decay, par_env1sustain, par_env1fade, par_env1release, 
-        par_keyfollow, par_legato, par_portamento, par_vel2filter, par_vel2amp, par_master, par_pwhlrange, 
+    enum { par_wave1, par_wave2, par_pw1, par_pw2, par_detune, par_osc2xpose, par_oscmode, par_oscmix, par_filtertype, par_cutoff, par_resonance, par_cutoffsep, par_env1tocutoff, par_env1tores, par_env1toamp,
+        par_env1attack, par_env1decay, par_env1sustain, par_env1fade, par_env1release,
+        par_keyfollow, par_legato, par_portamento, par_vel2filter, par_vel2amp, par_master, par_pwhlrange,
         par_lforate, par_lfodelay, par_lfofilter, par_lfopitch, par_lfopw, par_mwhl_lfo, par_scaledetune,
-        par_env2tocutoff, par_env2tores, par_env2toamp, 
-        par_env2attack, par_env2decay, par_env2sustain, par_env2fade, par_env2release, 
+        par_env2tocutoff, par_env2tores, par_env2toamp,
+        par_env2attack, par_env2decay, par_env2sustain, par_env2fade, par_env2release,
         par_stretch1, par_window1,
         par_lfo1trig, par_lfo2trig,
         par_lfo2rate, par_lfo2delay,
@@ -144,9 +144,9 @@ struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
         moddest_count,
     };
     PLUGIN_NAME_ID_LABEL("monosynth", "monosynth", "Monosynth")
-    
+
     mod_matrix_metadata mm_metadata;
-    
+
     monosynth_metadata();
     /// Lookup of table edit interface
     virtual const table_metadata_iface *get_table_metadata_iface(const char *key) const { if (!strcmp(key, "mod_matrix")) return &mm_metadata; else return NULL; }
@@ -159,7 +159,7 @@ struct compressor_metadata: public plugin_metadata<compressor_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
     enum { param_bypass, param_level_in, MONO_VU_METER_PARAMS,
-           param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression, 
+           param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression,
            param_count };
     PLUGIN_NAME_ID_LABEL("compressor", "compressor", "Compressor")
 };
@@ -169,7 +169,7 @@ struct sidechaincompressor_metadata: public plugin_metadata<sidechaincompressor_
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
     enum { param_bypass, param_level_in, MONO_VU_METER_PARAMS,
-           param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression, 
+           param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_compression,
            param_sc_mode, param_f1_freq, param_f2_freq, param_f1_level, param_f2_level,
            param_sc_listen, param_f1_active, param_f2_active, param_count };
     PLUGIN_NAME_ID_LABEL("sidechaincompressor", "sidechaincompressor", "Sidechain Compressor")
@@ -179,7 +179,7 @@ struct sidechaincompressor_metadata: public plugin_metadata<sidechaincompressor_
 struct multibandcompressor_metadata: public plugin_metadata<multibandcompressor_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
-    enum { param_bypass, param_level_in, param_level_out, 
+    enum { param_bypass, param_level_in, param_level_out,
            STEREO_VU_METER_PARAMS,
            param_freq0, param_freq1, param_freq2,
            param_sep0, param_sep1, param_sep2,
@@ -215,7 +215,7 @@ struct gate_metadata: public plugin_metadata<gate_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
     enum { param_bypass, param_level_in, MONO_VU_METER_PARAMS,
-           param_range, param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_gating, 
+           param_range, param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_gating,
            param_count };
     PLUGIN_NAME_ID_LABEL("gate", "gate", "Gate")
 };
@@ -225,21 +225,43 @@ struct sidechaingate_metadata: public plugin_metadata<sidechaingate_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
     enum { param_bypass, param_level_in, MONO_VU_METER_PARAMS,
-           param_range, param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_gating, 
+           param_range, param_threshold, param_ratio, param_attack, param_release, param_makeup, param_knee, param_detection, param_stereo_link, param_gating,
            param_sc_mode, param_f1_freq, param_f2_freq, param_f1_level, param_f2_level,
            param_sc_listen, param_f1_active, param_f2_active, param_count };
     PLUGIN_NAME_ID_LABEL("sidechaingate", "sidechaingate", "Sidechain Gate")
 };
 
+/// Markus's multiband gate - metadata
+struct multibandgate_metadata: public plugin_metadata<multibandgate_metadata>
+{
+    enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
+    enum { param_bypass, param_level_in, param_level_out,
+           STEREO_VU_METER_PARAMS,
+           param_freq0, param_freq1, param_freq2,
+           param_sep0, param_sep1, param_sep2,
+           param_q0, param_q1, param_q2,
+           param_mode,
+           param_range0, param_threshold0, param_ratio0, param_attack0, param_release0, param_makeup0, param_knee0,
+           param_detection0, param_gating0, param_output0, param_bypass0, param_solo0,
+           param_range1, param_threshold1, param_ratio1, param_attack1, param_release1, param_makeup1, param_knee1,
+           param_detection1, param_gating1, param_output1, param_bypass1, param_solo1,
+           param_range2, param_threshold2, param_ratio2, param_attack2, param_release2, param_makeup2, param_knee2,
+           param_detection2, param_gating2, param_output2, param_bypass2, param_solo2,
+           param_range3, param_threshold3, param_ratio3, param_attack3, param_release3, param_makeup3, param_knee3,
+           param_detection3, param_gating3, param_output3, param_bypass3, param_solo3,
+           param_count };
+    PLUGIN_NAME_ID_LABEL("multiband_gate", "multibandgate", "Multiband Gate")
+};
+
 /// Markus's limiter - metadata
 struct limiter_metadata: public plugin_metadata<limiter_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
-    enum { param_bypass, param_level_in, param_level_out, 
+    enum { param_bypass, param_level_in, param_level_out,
            STEREO_VU_METER_PARAMS,
            param_limit, param_attack, param_release,
            param_att,
-           param_asc, param_asc_led,
+           param_asc, param_asc_led, param_asc_coeff,
            param_count };
     PLUGIN_NAME_ID_LABEL("limiter", "limiter", "Limiter")
 };
@@ -248,7 +270,7 @@ struct limiter_metadata: public plugin_metadata<limiter_metadata>
 struct multibandlimiter_metadata: public plugin_metadata<multibandlimiter_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
-    enum { param_bypass, param_level_in, param_level_out, 
+    enum { param_bypass, param_level_in, param_level_out,
            STEREO_VU_METER_PARAMS,
            param_freq0, param_freq1, param_freq2,
            param_sep0, param_sep1, param_sep2,
@@ -256,11 +278,11 @@ struct multibandlimiter_metadata: public plugin_metadata<multibandlimiter_metada
            param_mode,
            param_limit, param_attack, param_release, param_minrel,
            param_att0, param_att1, param_att2, param_att3,
-           param_weight0, param_weight1, param_weight2, param_weight3, 
+           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_asc, param_asc_led,
+           param_asc, param_asc_led, param_asc_coeff,
            param_count };
     PLUGIN_NAME_ID_LABEL("multiband_limiter", "multibandlimiter", "Multiband Limiter")
 };
@@ -286,7 +308,7 @@ struct equalizer5band_metadata: public plugin_metadata<equalizer5band_metadata>
 struct equalizer8band_metadata: public plugin_metadata<equalizer8band_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
-    enum { param_bypass, param_level_in, param_level_out, 
+    enum { param_bypass, param_level_in, param_level_out,
            STEREO_VU_METER_PARAMS,
            param_hp_active, param_hp_freq, param_hp_mode,
            param_lp_active, param_lp_freq, param_lp_mode,
@@ -304,7 +326,7 @@ struct equalizer8band_metadata: public plugin_metadata<equalizer8band_metadata>
 struct equalizer12band_metadata: public plugin_metadata<equalizer12band_metadata>
 {
     enum { in_count = 2, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = false, require_midi = false, rt_capable = true };
-    enum { param_bypass, param_level_in, param_level_out, 
+    enum { param_bypass, param_level_in, param_level_out,
            STEREO_VU_METER_PARAMS,
            param_hp_active, param_hp_freq, param_hp_mode,
            param_lp_active, param_lp_freq, param_lp_mode,
@@ -346,7 +368,7 @@ struct exciter_metadata: public plugin_metadata<exciter_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, MONO_VU_METER_PARAMS, param_drive, param_blend, param_meter_drive,
-           param_freq, param_listen, param_count };
+           param_freq, param_listen, param_ceil_active, param_ceil, param_count };
     PLUGIN_NAME_ID_LABEL("exciter", "exciter", "Exciter")
 };
 /// Markus's Bass Enhancer - metadata
@@ -354,15 +376,15 @@ struct bassenhancer_metadata: public plugin_metadata<bassenhancer_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, MONO_VU_METER_PARAMS, param_drive, param_blend, param_meter_drive,
-           param_freq, param_listen, param_count };
+           param_freq, param_listen, param_floor_active, param_floor, param_count };
     PLUGIN_NAME_ID_LABEL("bassenhancer", "bassenhancer", "Bass Enhancer")
 };
 /// Markus's Mono Module - metadata
 struct stereo_metadata: public plugin_metadata<stereo_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, 
-           STEREO_VU_METER_PARAMS, param_balance_in, param_balance_out, param_softclip, 
+    enum { param_bypass, param_level_in, param_level_out,
+           STEREO_VU_METER_PARAMS, param_balance_in, param_balance_out, param_softclip,
            param_mute_l, param_mute_r, param_phase_l, param_phase_r,
            param_mode, param_slev, param_sbal, param_mlev, param_mpan,
            param_widener, param_delay,
@@ -374,9 +396,9 @@ struct stereo_metadata: public plugin_metadata<stereo_metadata>
 struct mono_metadata: public plugin_metadata<mono_metadata>
 {
     enum { in_count = 1, 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, 
+    enum { param_bypass, param_level_in, param_level_out,
            param_meter_in, param_meter_outL, param_meter_outR, param_clip_in,param_clip_outL, param_clip_outR,
-           param_balance_out, param_softclip, 
+           param_balance_out, param_softclip,
            param_mute_l, param_mute_r, param_phase_l, param_phase_r,
            param_delay,
            param_count };
@@ -387,26 +409,26 @@ struct mono_metadata: public plugin_metadata<mono_metadata>
 /// a bad design decision and should be sorted out some day) XXXKF @todo
 struct organ_enums
 {
-    enum { 
-        par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9, 
-        par_frequency1, par_frequency2, par_frequency3, par_frequency4, par_frequency5, par_frequency6, par_frequency7, par_frequency8, par_frequency9, 
-        par_waveform1, par_waveform2, par_waveform3, par_waveform4, par_waveform5, par_waveform6, par_waveform7, par_waveform8, par_waveform9, 
-        par_detune1, par_detune2, par_detune3, par_detune4, par_detune5, par_detune6, par_detune7, par_detune8, par_detune9, 
-        par_phase1, par_phase2, par_phase3, par_phase4, par_phase5, par_phase6, par_phase7, par_phase8, par_phase9, 
-        par_pan1, par_pan2, par_pan3, par_pan4, par_pan5, par_pan6, par_pan7, par_pan8, par_pan9, 
-        par_routing1, par_routing2, par_routing3, par_routing4, par_routing5, par_routing6, par_routing7, par_routing8, par_routing9, 
+    enum {
+        par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9,
+        par_frequency1, par_frequency2, par_frequency3, par_frequency4, par_frequency5, par_frequency6, par_frequency7, par_frequency8, par_frequency9,
+        par_waveform1, par_waveform2, par_waveform3, par_waveform4, par_waveform5, par_waveform6, par_waveform7, par_waveform8, par_waveform9,
+        par_detune1, par_detune2, par_detune3, par_detune4, par_detune5, par_detune6, par_detune7, par_detune8, par_detune9,
+        par_phase1, par_phase2, par_phase3, par_phase4, par_phase5, par_phase6, par_phase7, par_phase8, par_phase9,
+        par_pan1, par_pan2, par_pan3, par_pan4, par_pan5, par_pan6, par_pan7, par_pan8, par_pan9,
+        par_routing1, par_routing2, par_routing3, par_routing4, par_routing5, par_routing6, par_routing7, par_routing8, par_routing9,
         par_foldover,
         par_percdecay, par_perclevel, par_percwave, par_percharm, par_percvel2amp,
         par_percfmdecay, par_percfmdepth, par_percfmwave, par_percfmharm, par_percvel2fm,
         par_perctrigger, par_percstereo,
         par_filterchain,
         par_filter1type,
-        par_master, 
+        par_master,
         par_f1cutoff, par_f1res, par_f1env1, par_f1env2, par_f1env3, par_f1keyf,
         par_f2cutoff, par_f2res, par_f2env1, par_f2env2, par_f2env3, par_f2keyf,
-        par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1release, par_eg1velscl, par_eg1ampctl, 
-        par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2release, par_eg2velscl, par_eg2ampctl, 
-        par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3release, par_eg3velscl, par_eg3ampctl, 
+        par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1release, par_eg1velscl, par_eg1ampctl,
+        par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2release, par_eg2velscl, par_eg2ampctl,
+        par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3release, par_eg3velscl, par_eg3ampctl,
         par_lforate, par_lfoamt, par_lfowet, par_lfophase, par_lfomode, par_lfotype,
         par_transpose, par_detune,
         par_polyphony,
@@ -418,8 +440,8 @@ struct organ_enums
         par_treblegain,
         param_count
     };
-    enum organ_waveform { 
-        wave_sine, 
+    enum organ_waveform {
+        wave_sine,
         wave_sinepl1, wave_sinepl2, wave_sinepl3,
         wave_ssaw, wave_ssqr, wave_spls, wave_saw, wave_sqr, wave_pulse, wave_sinepl05, wave_sqr05, wave_halfsin, wave_clvg, wave_bell, wave_bell2,
         wave_w1, wave_w2, wave_w3, wave_w4, wave_w5, wave_w6, wave_w7, wave_w8, wave_w9,
@@ -444,7 +466,7 @@ struct organ_enums
         ampctl_all,
         ampctl_count
     };
-    enum { 
+    enum {
         lfotype_allpass = 0,
         lfotype_cv1,
         lfotype_cv2,
@@ -452,7 +474,7 @@ struct organ_enums
         lfotype_cvfull,
         lfotype_count
     };
-    enum { 
+    enum {
         lfomode_off = 0,
         lfomode_direct,
         lfomode_filter1,
@@ -475,7 +497,7 @@ struct organ_metadata: public organ_enums, public plugin_metadata<organ_metadata
 {
     enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true };
     PLUGIN_NAME_ID_LABEL("organ", "organ", "Organ")
-    
+
 public:
     plugin_command_info *get_commands();
     const char *const *get_configure_vars() const;
@@ -491,7 +513,7 @@ struct fluidsynth_metadata: public plugin_metadata<fluidsynth_metadata>
 public:
     const char *const *get_configure_vars() const;
 };
-    
+
 /// Wavetable - metadata
 struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
 {
@@ -549,25 +571,25 @@ struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
         moddest_o2detune,
         moddest_count,
     };
-    enum { 
+    enum {
         par_o1wave, par_o1offset, par_o1transpose, par_o1detune, par_o1level,
         par_o2wave, par_o2offset, par_o2transpose, par_o2detune, par_o2level,
         par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1fade, par_eg1release, par_eg1velscl,
         par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2fade, par_eg2release, par_eg2velscl,
         par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3fade, par_eg3release, par_eg3velscl,
-        par_pwhlrange, 
+        par_pwhlrange,
         param_count };
     enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true };
     enum { mod_matrix_slots = 10 };
     enum { step_size = 64 };
     PLUGIN_NAME_ID_LABEL("wavetable", "wavetable", "Wavetable")
     mod_matrix_metadata mm_metadata;
-    
+
     wavetable_metadata();
     /// Lookup of table edit interface
     virtual const table_metadata_iface *get_table_metadata_iface(const char *key) const { if (!strcmp(key, "mod_matrix")) return &mm_metadata; else return NULL; }
 };
-    
+
 };
 
 #endif
diff --git a/src/calf/modulelist.h b/src/calf/modulelist.h
index 3e6d6f7..8425794 100644
--- a/src/calf/modulelist.h
+++ b/src/calf/modulelist.h
@@ -15,6 +15,7 @@
     PER_MODULE_ITEM(deesser, false, "deesser")
     PER_MODULE_ITEM(gate, false, "gate")
     PER_MODULE_ITEM(sidechaingate, false, "sidechaingate")
+    PER_MODULE_ITEM(multibandgate, false, "multibandgate")
     PER_MODULE_ITEM(limiter, false, "limiter")
     PER_MODULE_ITEM(multibandlimiter, false, "multibandlimiter")
     PER_MODULE_ITEM(pulsator, false, "pulsator")
diff --git a/src/calf/modules_comp.h b/src/calf/modules_comp.h
index 538e18b..0dbe882 100644
--- a/src/calf/modules_comp.h
+++ b/src/calf/modules_comp.h
@@ -85,6 +85,7 @@ public:
     void process(float &left, float &right, const float *det_left = NULL, const float *det_right = NULL);
     void activate();
     void deactivate();
+    int id;
     void set_sample_rate(uint32_t sr);
     float get_output_level();
     float get_expander_level();
@@ -189,7 +190,7 @@ public:
     virtual int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
 };
 
-/// Deesser by Markus Schmidt (based on Thor's compressor and Krzysztof's filters)
+/// Deesser by Markus Schmidt (based on Thor's compressor and Krzyexpander_audio_modulesztof's filters)
 class deesser_audio_module: public audio_module<deesser_metadata>, public frequency_response_line_graph  {
 private:
     enum CalfDeessModes {
@@ -288,6 +289,36 @@ public:
     int  get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
 };
 
+
+/// Multibandgate by Markus Schmidt (based on Damiens's gate and Krzysztof's filters)
+class multibandgate_audio_module: public audio_module<multibandgate_metadata>, public line_graph_iface {
+private:
+    typedef multibandgate_audio_module AM;
+    static const int strips = 4;
+    bool solo[strips];
+    bool no_solo;
+    uint32_t clip_inL, clip_inR, clip_outL, clip_outR;
+    float meter_inL, meter_inR, meter_outL, meter_outR;
+    expander_audio_module gate[strips];
+    dsp::biquad_d2<float> lpL[strips - 1][3], lpR[strips - 1][3], hpL[strips - 1][3], hpR[strips - 1][3];
+    float freq_old[strips - 1], sep_old[strips - 1], q_old[strips - 1];
+    int mode, mode_old;
+public:
+    uint32_t srate;
+    bool is_active;
+    multibandgate_audio_module();
+    void activate();
+    void deactivate();
+    void params_changed();
+    uint32_t process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask);
+    void set_sample_rate(uint32_t sr);
+    const expander_audio_module *get_strip_by_param_index(int index) const;
+    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 index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const;
+};
+
 };
 
 #endif
diff --git a/src/calf/modules_dist.h b/src/calf/modules_dist.h
index d7be7dd..2c46caa 100644
--- a/src/calf/modules_dist.h
+++ b/src/calf/modules_dist.h
@@ -57,10 +57,12 @@ public:
 /// Exciter by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
 class exciter_audio_module: public audio_module<exciter_metadata> {
 private:
-    float freq_old;
+    float freq_old, ceil_old;
+    bool ceil_active_old;
     stereo_in_out_metering<exciter_metadata> meters;
     float meter_drive;
     dsp::biquad_d2<float> hp[2][4];
+    dsp::biquad_d2<float> lp[2][2];
     dsp::tap_distortion dist[2];
 public:
     uint32_t srate;
@@ -76,10 +78,12 @@ public:
 /// Bass Enhancer by Markus Schmidt (based on Krzysztof's filters and Tom's distortion algorythm)
 class bassenhancer_audio_module: public audio_module<bassenhancer_metadata> {
 private:
-    float freq_old;
+    float freq_old, floor_old;
+    bool floor_active_old;
     stereo_in_out_metering<exciter_metadata> meters;
     float meter_drive;
     dsp::biquad_d2<float> lp[2][4];
+    dsp::biquad_d2<float> hp[2][2];
     dsp::tap_distortion dist[2];
 public:
     uint32_t srate;
diff --git a/src/calf/modules_limit.h b/src/calf/modules_limit.h
index 74bfe19..d5d4b9a 100644
--- a/src/calf/modules_limit.h
+++ b/src/calf/modules_limit.h
@@ -15,7 +15,7 @@
  *
  * 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, 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02111-1307, USA.
  */
 #ifndef CALF_MODULES_LIMIT_H
@@ -43,6 +43,9 @@ private:
 public:
     uint32_t srate;
     bool is_active;
+    float limit_old;
+    bool asc_old;
+    float attack_old;
     limiter_audio_module();
     void activate();
     void deactivate();
@@ -68,11 +71,14 @@ private:
     unsigned int pos;
     unsigned int buffer_size;
     unsigned int overall_buffer_size;
-    float __attack;
     float *buffer;
     int channels;
     float striprel[strips];
     float weight[strips];
+    float weight_old[strips];
+    float limit_old;
+    bool asc_old;
+    float attack_old;
     bool _sanitize;
 public:
     uint32_t srate;
diff --git a/src/metadata.cpp b/src/metadata.cpp
index b7172fb..9c82aff 100644
--- a/src/metadata.cpp
+++ b/src/metadata.cpp
@@ -15,7 +15,7 @@
  *
  * 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, 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 #include <config.h>
@@ -127,8 +127,8 @@ CALF_PORT_NAMES(filterclavier) = {"In L", "In R", "Out L", "Out R"};
 CALF_PORT_PROPS(filterclavier) = {
     { 0,        -48,   48, 48*2+1, PF_INT   | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "transpose", "Transpose" },
     { 0,       -100,  100,      0, PF_INT   | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune", "Detune" },
-    { 32,     0.707,   32,      0, PF_FLOAT | PF_SCALE_GAIN   | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "maxres", "Max. Resonance" },    
-    { biquad_filter_module::mode_6db_bp, 
+    { 32,     0.707,   32,      0, PF_FLOAT | PF_SCALE_GAIN   | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "maxres", "Max. Resonance" },
+    { biquad_filter_module::mode_6db_bp,
       biquad_filter_module::mode_12db_lp,
       biquad_filter_module::mode_count - 1,
                                 1, PF_ENUM  | PF_CTL_COMBO | PF_PROP_GRAPH, filter_choices, "mode", "Mode" },
@@ -311,21 +311,21 @@ CALF_PORT_PROPS(multibandcompressor) = {
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
-    
+
     { 120,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" },
     { 1000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" },
     { 6000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Split 3/4" },
-    
+
     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S1" },
     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep1", "S2" },
     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep2", "S3" },
-    
+
     { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q0", "Q1" },
     { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q1", "Q2" },
     { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q2", "Q3" },
-    
+
     { 1,      0,  1,    0, PF_ENUM | PF_CTL_COMBO, multibandcompressor_filter_choices, "mode", "Filter Mode" },
-    
+
     { 0.25,      0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold0", "Threshold 1" },
     { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio0", "Ratio 1" },
     { 150,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack0", "Attack 1" },
@@ -337,8 +337,8 @@ CALF_PORT_PROPS(multibandcompressor) = {
     { 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, "output0", "Output 1" },
     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass0", "Bypass 1" },
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo0", "Solo 1" },
-    
-    
+
+
     { 0.125,     0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold1", "Threshold 2" },
     { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio1", "Ratio 2" },
     { 100,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack1", "Attack 2" },
@@ -350,8 +350,8 @@ CALF_PORT_PROPS(multibandcompressor) = {
     { 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, "output1", "Output 2" },
     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass1", "Bypass 2" },
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo1", "Solo 2" },
-    
-    
+
+
     { 0.0625,    0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold2", "Threshold 3" },
     { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio2", "Ratio 3" },
     { 50,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack2", "Attack 3" },
@@ -363,8 +363,8 @@ CALF_PORT_PROPS(multibandcompressor) = {
     { 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, "output2", "Output 3" },
     { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass2", "Bypass 3" },
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo2", "Solo 3" },
-    
-    
+
+
     { 0.03125,   0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold3", "Threshold 4" },
     { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio3", "Ratio 4" },
     { 25,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack3", "Attack 4" },
@@ -493,6 +493,96 @@ CALF_PLUGIN_INFO(sidechaingate) = { 0x8504, "Sidechaingate", "Calf Sidechain Gat
 
 ////////////////////////////////////////////////////////////////////////////
 
+CALF_PORT_NAMES(multibandgate) = {"In L", "In R", "Out L", "Out R"};
+
+const char *multibandgate_detection_names[] = { "RMS", "Peak" };
+const char *multibandgate_filter_choices[] = { "12dB", "36dB"};
+
+CALF_PORT_PROPS(multibandgate) = {
+    { 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" },
+    { 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_inL", "Input L" },
+    { 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_inR", "Input R" },
+    { 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_outL", "Output L" },
+    { 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_outR", "Output R" },
+    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inL", "0dB-InL" },
+    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
+    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
+    { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
+
+    { 120,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" },
+    { 1000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" },
+    { 6000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Split 3/4" },
+
+    { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S1" },
+    { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep1", "S2" },
+    { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep2", "S3" },
+
+    { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q0", "Q1" },
+    { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q1", "Q2" },
+    { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q2", "Q3" },
+
+    { 1,      0,  1,    0, PF_ENUM | PF_CTL_COMBO, multibandgate_filter_choices, "mode", "Filter Mode" },
+
+    { 0.06125,   0.000015849, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "range0", "Reduction 1" },
+    { 0.25,      0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold0", "Threshold 1" },
+    { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio0", "Ratio 1" },
+    { 150,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack0", "Attack 1" },
+    { 300,         0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release0", "Release 1" },
+    { 1,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup0", "Makeup 1" },
+    { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee0", "Knee 1" },
+    { 0,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection0", "Detection 1" },
+    { 1,           0.0625,     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, "gating0", "Gating 1" },
+    { 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, "output0", "Output 1" },
+    { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass0", "Bypass 1" },
+    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo0", "Solo 1" },
+
+    { 0.06125,   0.000015849, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "range1", "Reduction 2" },
+    { 0.125,     0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold1", "Threshold 2" },
+    { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio1", "Ratio 2" },
+    { 100,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack1", "Attack 2" },
+    { 200,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release1", "Release 2" },
+    { 1,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup1", "Makeup 2" },
+    { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee1", "Knee 2" },
+    { 0,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection1", "Detection 2" },
+    { 1,           0.0625,     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, "gating1", "Gating 2" },
+    { 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, "output1", "Output 2" },
+    { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass1", "Bypass 2" },
+    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo1", "Solo 2" },
+
+    { 0.06125,   0.000015849, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "range2", "Reduction 3" },
+    { 0.0625,    0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold2", "Threshold 3" },
+    { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio2", "Ratio 3" },
+    { 50,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack2", "Attack 3" },
+    { 100,          0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release2", "Release 3" },
+    { 1,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup2", "Makeup 3" },
+    { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee2", "Knee 3" },
+    { 0,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection2", "Detection 3" },
+    { 1,           0.0625,     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, "gating2", "Gating 3" },
+    { 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, "output2", "Output 3" },
+    { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass2", "Bypass 3" },
+    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo2", "Solo 3" },
+
+    { 0.06125,   0.000015849, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "range3", "Reduction 4" },
+    { 0.03125,   0.000976563, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "threshold3", "Threshold 4" },
+    { 2,           1,           20,    21, PF_FLOAT | PF_SCALE_LOG_INF | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "ratio3", "Ratio 4" },
+    { 25,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack3", "Attack 4" },
+    { 50,        0.01,        2000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release3", "Release 4" },
+    { 1,           1,           64,    0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "makeup3", "Makeup 4" },
+    { 2.828427125, 1,           8,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "knee3", "Knee 4" },
+    { 0,           0,           1,     0,  PF_ENUM | PF_CTL_COMBO, multibandcompressor_detection_names, "detection3", "Detection 4" },
+    { 1,           0.0625,     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, "gating3", "Gating 4" },
+    { 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, "output3", "Output 4" },
+    { 1,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass3", "Bypass 4" },
+    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo3", "Solo 4" },
+    {}
+};
+
+CALF_PLUGIN_INFO(multibandgate) = { 0x8505, "Multibandgate", "Calf Multiband Gate", "Markus Schmidt / Damien Zammit / Thor Harald Johansen", calf_plugins::calf_copyright_info, "ExpanderPlugin" };
+
+////////////////////////////////////////////////////////////////////////////
+
 CALF_PORT_NAMES(limiter) = {"In L", "In R", "Out L", "Out R"};
 
 CALF_PORT_PROPS(limiter) = {
@@ -507,17 +597,19 @@ CALF_PORT_PROPS(limiter) = {
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
-    
+
     { 1,      0.0625, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "limit", "Limit" },
     { 5,         0.1,        10,  0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Lookahead" },
     { 50,         1,        1000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" },
-    
+
     { 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" },
-    
+
+    { 0.5f,      0.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "asc_coeff", "ASC Level" },
+
     {}
 };
 
@@ -540,62 +632,64 @@ CALF_PORT_PROPS(multibandlimiter) = {
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
-    
+
     { 100,         10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq0", "Split 1/2" },
     { 750,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq1", "Split 2/3" },
     { 5000,        10,          20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ | PF_PROP_GRAPH, NULL, "freq2", "Split 3/4" },
-    
+
     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep0", "S1" },
     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep1", "S2" },
     { -0.17,      -0.5,         0.5,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sep2", "S3" },
-    
+
     { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q0", "Q1" },
     { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q1", "Q2" },
     { 0.7762471166286917,    0.25,        4,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB | PF_PROP_GRAPH, NULL, "q2", "Q3" },
-    
+
     { 1,      0,  1,    0, PF_ENUM | PF_CTL_COMBO, multibandlimiter_filter_choices, "mode", "Filter Mode" },
-    
+
     { 1,      0.0625, 1,     0,  PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "limit", "Limit" },
     { 4,         0.1,        10,  0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "attack", "Lookahead" },
     { 30,         1,        1000,  0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "release", "Release" },
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "minrel", "Min Release" },
-    
+
     { 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, "att0", "Low" },
     { 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, "att1", "LMid" },
     { 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, "att2", "HMid" },
     { 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, "att3", "Hi" },
-    
-    { 0.2f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight0", "Weight 1" },
-    { -0.2f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight1", "Weight 2" },
-    { 0.2f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight2", "Weight 3" },
-    { -0.2f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight3", "Weight 4" },
-    
+
+    { 0.f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight0", "Weight 1" },
+    { 0.f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight1", "Weight 2" },
+    { 0.f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight2", "Weight 3" },
+    { 0.f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "weight3", "Weight 4" },
+
     { 0.5f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "release0", "Release 1" },
     { 0.2f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "release1", "Release 2" },
     { -0.2f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "release2", "Release 3" },
     { -0.5f,      -1.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "release3", "Release 4" },
-    
+
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo0", "Solo 1" },
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo1", "Solo 2" },
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo2", "Solo 3" },
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "solo3", "Solo 4" },
-    
+
     { 1,         0.f,        1000,  0,  PF_FLOAT | PF_UNIT_MSEC | PF_PROP_OUTPUT, NULL, "effrelease0", "Effectively Release 1" },
     { 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" },
-    
+
+    { 0.5f,      0.f,         1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "asc_coeff", "ASC Level" },
+
     {}
 };
 
 CALF_PLUGIN_INFO(multibandlimiter) = { 0x8520, "Multibandlimiter", "Calf Multiband Limiter", "Markus Schmidt / Christian Holschuh", calf_plugins::calf_copyright_info, "LimiterPlugin" };
 
 ////////////////////////////////////////////////////////////////////////////
-// A few macros to make 
+// A few macros to make
 
 #define BYPASS_AND_LEVEL_PARAMS \
     { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass", "Bypass" }, \
@@ -725,17 +819,17 @@ CALF_PORT_PROPS(saturator) = {
     { 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" },
-    
+
     { 5,           0.1,         10,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "drive", "Saturation" },
     { 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" },
@@ -757,13 +851,15 @@ CALF_PORT_PROPS(exciter) = {
     { 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" },
+    { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "ceil_active", "Ceiling active" },
+    { 16000,      10000,        20000, 0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "ceil", "Ceiling" },
     {}
 };
 
@@ -782,13 +878,15 @@ CALF_PORT_PROPS(bassenhancer) = {
     { 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" },
-    
+
     { 120,        10,           250,   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" },
+    { 0,           0,           1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "floor_active", "Floor active" },
+    { 30,         10,           120,   0,  PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "floor", "Floor" },
     {}
 };
 
@@ -807,15 +905,15 @@ CALF_PORT_PROPS(mono) = {
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_in", "0dB-In" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
-    
+
     { 0.f,      -1.f,           1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "balance_out", "Balance" },
-    
+
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "softclip", "Softclip" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mutel", "Mute L" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "muter", "Mute R" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "phasel", "Phase L" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "phaser", "Phase R" },
-    
+
     { 0.f,         -20.f,        20.f,  0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "delay", "Delay" },
     {}
 };
@@ -839,28 +937,28 @@ CALF_PORT_PROPS(stereo) = {
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_inR", "0dB-InR" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outL", "0dB-OutL" },
     { 0,           0,           1,     0,  PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "clip_outR", "0dB-OutR" },
-    
+
     { 0.f,      -1.f,           1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "balance_in", "Balance In" },
     { 0.f,      -1.f,           1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "balance_out", "Balance Out" },
-    
+
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "softclip", "Softclip" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "mutel", "Mute L" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "muter", "Mute R" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "phasel", "Phase L" },
     { 0,          0,            1,     0,  PF_BOOL | PF_CTL_TOGGLE, NULL, "phaser", "Phase R" },
-    
+
     { 0,           0,           6,     0,  PF_ENUM | PF_CTL_COMBO, stereo_mode_names, "mode", "Mode" },
-    
+
     { 0.f,      -1.f,            1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "slev", "S Level" },
     { 0.f,      -1.f,            1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "sbal", "S Balance" },
     { 0.f,      -1.f,            1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "mlev", "M Level" },
     { 0.f,      -1.f,            1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_GRAPH, NULL, "mpan", "M Panorama" },
-    
+
     { 0,           0,           1,    0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "widener", "Widener" },
     { 0.f,         -20.f,        20.f,  0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "delay", "Delay" },
-    
+
     { 0.f,      0.f,           1.f,   0,  PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_COEF | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_phase", "Phase Correlation" },
-    
+
     {}
 };
 
@@ -870,10 +968,10 @@ CALF_PLUGIN_INFO(stereo) = { 0x8588, "StereoTools", "Calf Stereo Tools", "Markus
 ////////////////////////////////////////////////////////////////////////////
 
 CALF_PORT_NAMES(monosynth) = {
-    "Out L", "Out R", 
+    "Out L", "Out R",
 };
 
-const char *monosynth_waveform_names[] = { "Sawtooth", "Square", "Pulse", "Sine", "Triangle", "Varistep", "Skewed Saw", "Skewed Square", 
+const char *monosynth_waveform_names[] = { "Sawtooth", "Square", "Pulse", "Sine", "Triangle", "Varistep", "Skewed Saw", "Skewed Square",
     "Smooth Brass", "Bass", "Dark FM", "Multiwave", "Bell FM", "Dark Pad", "DCO Saw", "DCO Maze" };
 const char *monosynth_mode_names[] = { "0\xC2\xB0 : 0\xC2\xB0", "0\xC2\xB0 : 180\xC2\xB0", "0\xC2\xB0 : 90\xC2\xB0", "90\xC2\xB0 : 90\xC2\xB0", "90\xC2\xB0 : 270\xC2\xB0", "Random" };
 const char *monosynth_legato_names[] = { "Retrig", "Legato", "Fng Retrig", "Fng Legato" };
@@ -895,10 +993,10 @@ CALF_PLUGIN_INFO(monosynth) = { 0x8480, "Monosynth", "Calf Monosynth", "Krzyszto
 CALF_PORT_PROPS(monosynth) = {
     { monosynth_metadata::wave_saw,         0, monosynth_metadata::wave_count - 1, 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_waveform_names, "o1_wave", "Osc1 Wave" },
     { monosynth_metadata::wave_sqr,         0, monosynth_metadata::wave_count - 1, 1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, monosynth_waveform_names, "o2_wave", "Osc2 Wave" },
-    
+
     { 0,         -1,    1,  0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "o1_pw", "Osc1 PW" },
     { 0,         -1,    1,  0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "o2_pw", "Osc2 PW" },
-    
+
     { 10,         0,  100,    0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "o12_detune", "O1<>2 Detune" },
     { 12,       -24,   24,    0, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_SEMITONES, NULL, "o2_xpose", "Osc 2 transpose" },
     { 0,          0,    5,    0, PF_ENUM | PF_CTL_COMBO, monosynth_mode_names, "phase_mode", "Phase mode" },
@@ -910,17 +1008,17 @@ CALF_PORT_PROPS(monosynth) = {
     { 8000,  -10800,10800,    0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "env2cutoff", "Env->Cutoff" },
     { 1,          0,    1,    0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "env2res", "Env->Res" },
     { 0,          0,    1,    0, PF_BOOL | PF_CTL_TOGGLE, NULL, "env2amp", "Env->Amp" },
-    
+
     { 1,          1,20000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_a", "EG1 Attack" },
     { 350,       10,20000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_d", "EG1 Decay" },
     { 0.5,        0,    1,    0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr_s", "EG1 Sustain" },
     { 0,     -10000,10000,   21, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_f", "EG1 Fade" },
     { 100,       10,20000,     0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr_r", "EG1 Release" },
-    
+
     { 0,          0,    2,    0, PF_FLOAT | PF_SCALE_PERC, NULL, "key_follow", "Key Follow" },
     { 0,          0,    3,    0, PF_ENUM | PF_CTL_COMBO, monosynth_legato_names, "legato", "Legato Mode" },
     { 1,          1, 2000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "portamento", "Portamento" },
-    
+
     { 0.5,        0,    1,  0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "vel2filter", "Vel->Filter" },
     { 0,          0,    1,  0.1, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "vel2amp", "Vel->Amp" },
 
@@ -940,7 +1038,7 @@ CALF_PORT_PROPS(monosynth) = {
     { 0,  -10800,10800,    0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "adsr2_cutoff", "EG2->Cutoff" },
     { 0.3,        0,    1,    0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB, NULL, "adsr2_res", "EG2->Res" },
     { 1,          0,    1,    0, PF_BOOL | PF_CTL_TOGGLE, NULL, "adsr2_amp", "EG2->Amp" },
-    
+
     { 1,          1,20000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr2_a", "EG2 Attack" },
     { 100,       10,20000,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_FADER | PF_UNIT_MSEC, NULL, "adsr2_d", "EG2 Decay" },
     { 0.5,        0,    1,    0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr2_s", "EG2 Sustain" },
@@ -958,7 +1056,7 @@ CALF_PORT_PROPS(monosynth) = {
 };
 
 static const char *monosynth_mod_src_names[] = {
-    "None", 
+    "None",
     "Velocity",
     "Pressure",
     "ModWheel",
@@ -1010,13 +1108,13 @@ CALF_PORT_NAMES(organ) = {"Out L", "Out R"};
 
 const char *organ_percussion_trigger_names[] = { "First note", "Each note", "Each, no retrig", "Polyphonic" };
 
-const char *organ_wave_names[] = { 
-    "Sin", 
-    "S0", "S00", "S000", 
-    "SSaw", "SSqr", "SPls", 
-    "Saw", "Sqr", "Pls", 
-    "S(", "Sq(", "S+", "Clvg", 
-    "Bell", "Bell2", 
+const char *organ_wave_names[] = {
+    "Sin",
+    "S0", "S00", "S000",
+    "SSaw", "SSqr", "SPls",
+    "Saw", "Sqr", "Pls",
+    "S(", "Sq(", "S+", "Clvg",
+    "Bell", "Bell2",
     "W1", "W2", "W3", "W4", "W5", "W6", "W7", "W8", "W9",
     "DSaw", "DSqr", "DPls",
     "P:SynStr","P:WideStr","P:Sine","P:Bell","P:Space","P:Voice","P:Hiss","P:Chant",
@@ -1108,26 +1206,26 @@ CALF_PORT_PROPS(organ) = {
     { 0,       0,  2, 0, PF_ENUM | PF_SCALE_LINEAR | PF_CTL_COMBO, organ_routing_names, "routing9", "Routing 9" },
 
     { 96 + 12,      0,  127, 128, PF_INT | PF_CTL_KNOB | PF_UNIT_NOTE, NULL, "foldnote", "Foldover" },
-    
+
     { 200,         10,  3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_decay", "P: Carrier Decay" },
     { 0.25,      0,  1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB, NULL, "perc_level", "P: Level" },
     { 0,         0,  organ_enums::wave_count_small - 1, 1, PF_ENUM | PF_CTL_COMBO, organ_wave_names, "perc_waveform", "P: Carrier Wave" },
     { 6,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "perc_harmonic", "P: Carrier Frq" },
     { 0,          0,    1,    0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_vel2amp", "P: Vel->Amp" },
-    
+
     { 200,         10,  3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_fm_decay", "P: Modulator Decay" },
     { 0,          0,    4,    0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_fm_depth", "P: FM Depth" },
     { 0,         0,  organ_enums::wave_count_small - 1, 1, PF_ENUM | PF_CTL_COMBO, organ_wave_names, "perc_fm_waveform", "P: Modulator Wave" },
     { 6,      1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "perc_fm_harmonic", "P: Modulator Frq" },
     { 0,          0,    1,    0, PF_FLOAT | PF_SCALE_PERC, NULL, "perc_vel2fm", "P: Vel->FM" },
-    
+
     { 0,         0,  organ_enums::perctrig_count - 1, 0, PF_ENUM | PF_CTL_COMBO, organ_percussion_trigger_names, "perc_trigger", "P: Trigger" },
     { 90,      0,360, 361, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_DEG, NULL, "perc_stereo", "P: Stereo Phase" },
 
     { 0,         0,  1, 0, PF_ENUM | PF_CTL_COMBO, organ_filter_send_names, "filter_chain", "Filter 1 To" },
     { 0,         0,  1, 0, PF_ENUM | PF_CTL_COMBO, organ_filter_type_names, "filter1_type", "Filter 1 Type" },
     { 0.1,         0,  1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_PROP_OUTPUT_GAIN | PF_PROP_GRAPH, NULL, "master", "Volume" },
-    
+
     { 2000,   20, 20000, 100, PF_FLOAT | PF_SCALE_LOG | PF_UNIT_HZ | PF_CTL_KNOB, NULL, "f1_cutoff", "F1 Cutoff" },
     { 2,        0.7,    8,    0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB, NULL, "f1_res", "F1 Res" },
     { 8000,  -10800,10800,    0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "f1_env1", "F1 Env1" },
@@ -1179,11 +1277,11 @@ CALF_PORT_PROPS(organ) = {
     { 0,       -100,  100,  201, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "detune", "Detune" },
 
     { 16,         1,   32,   32, PF_INT | PF_SCALE_LINEAR | PF_CTL_KNOB, NULL, "polyphony", "Polyphony" },
-    
+
     { 1,          0,    1,    0, PF_BOOL | PF_CTL_TOGGLE, NULL, "quad_env", "Quadratic AmpEnv" },
 
     { 200,        0, 2400,   25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" },
-    
+
     { 80,       20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "bass_freq", "Bass Freq" },
     { 1,        0.1, 10,     0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "bass_gain", "Bass Gain" },
     { 12000,     20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "treble_freq", "Treble Freq" },
@@ -1204,7 +1302,7 @@ const char *fluidsynth_init_presetkeyset = "";
 const char *fluidsynth_interpolation_names[] = { "None (zero-hold)", "Linear", "Cubic", "7-point" };
 
 CALF_PORT_NAMES(fluidsynth) = {
-    "Out L", "Out R", 
+    "Out L", "Out R",
 };
 
 CALF_PLUGIN_INFO(fluidsynth) = { 0x8700, "Fluidsynth", "Calf Fluidsynth", "FluidSynth Team / Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" };
@@ -1224,7 +1322,7 @@ const char *const *fluidsynth_metadata::get_configure_vars() const
 
 ////////////////////////////////////////////////////////////////////////////
 
-const char *wavetable_names[] = { 
+const char *wavetable_names[] = {
     "Shiny1",
     "Shiny2",
     "Rezo",
@@ -1257,7 +1355,7 @@ const char *wavetable_names[] = {
 };
 
 static const char *wavetable_mod_src_names[] = {
-    "None", 
+    "None",
     "Velocity",
     "Pressure",
     "ModWheel",
@@ -1281,7 +1379,7 @@ static const char *wavetable_mod_dest_names[] = {
 };
 
 CALF_PORT_NAMES(wavetable) = {
-    "Out L", "Out R", 
+    "Out L", "Out R",
 };
 
 CALF_PLUGIN_INFO(wavetable) = { 0x8701, "Wavetable", "Calf Wavetable", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" };
@@ -1336,4 +1434,3 @@ calf_plugins::plugin_registry::plugin_registry()
     #define PER_MODULE_ITEM(name, isSynth, jackname) plugins.push_back((new name##_metadata));
     #include <calf/modulelist.h>
 }
-
diff --git a/src/modules_comp.cpp b/src/modules_comp.cpp
index 0ee6842..1f16a02 100644
--- a/src/modules_comp.cpp
+++ b/src/modules_comp.cpp
@@ -969,7 +969,7 @@ uint32_t deesser_audio_module::process(uint32_t offset, uint32_t numsamples, uin
     bool bypass = *params[param_bypass] > 0.5f;
     numsamples += offset;
     if(bypass) {
-        // everything bypassed
+        // everything bypassed81e8da266
         while(offset < numsamples) {
             outs[0][offset] = ins[0][offset];
             outs[1][offset] = ins[1][offset];
@@ -1634,6 +1634,369 @@ int sidechaingate_audio_module::get_changed_offsets(int index, int generation, i
     return false;
 }
 
+
+/// Multiband Compressor by Markus Schmidt
+///
+/// This module splits the signal in four different bands
+/// and sends them through multiple filters (implemented by
+/// Krzysztof). They are processed by a compressing routine
+/// (implemented by Thor) afterwards and summed up to the
+/// final output again.
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+multibandgate_audio_module::multibandgate_audio_module()
+{
+    is_active = false;
+    srate = 0;
+    // zero all displays
+    clip_inL    = 0.f;
+    clip_inR    = 0.f;
+    clip_outL   = 0.f;
+    clip_outR   = 0.f;
+    meter_inL  = 0.f;
+    meter_inR  = 0.f;
+    meter_outL = 0.f;
+    meter_outR = 0.f;
+    for(int i = 0; i < strips - 1; i ++) {
+        freq_old[i] = -1;
+        sep_old[i] = -1;
+        q_old[i] = -1;
+    }
+    mode_old = -1;
+}
+
+void multibandgate_audio_module::activate()
+{
+    is_active = true;
+    // set all filters and strips
+    params_changed();
+    // activate all strips
+    for (int j = 0; j < strips; j ++) {
+        gate[j].activate();
+        gate[j].id = j;
+    }
+}
+
+void multibandgate_audio_module::deactivate()
+{
+    is_active = false;
+    // deactivate all strips
+    for (int j = 0; j < strips; j ++) {
+        gate[j].deactivate();
+    }
+}
+
+void multibandgate_audio_module::params_changed()
+{
+    // determine mute/solo states
+    solo[0] = *params[param_solo0] > 0.f ? true : false;
+    solo[1] = *params[param_solo1] > 0.f ? true : false;
+    solo[2] = *params[param_solo2] > 0.f ? true : false;
+    solo[3] = *params[param_solo3] > 0.f ? true : false;
+    no_solo = (*params[param_solo0] > 0.f ||
+            *params[param_solo1] > 0.f ||
+            *params[param_solo2] > 0.f ||
+            *params[param_solo3] > 0.f) ? false : true;
+    int i;
+    int j1;
+    switch(mode) {
+        case 0:
+        default:
+            j1 = 0;
+            break;
+        case 1:
+            j1 = 2;
+            break;
+    }
+    // set the params of all filters
+    if(*params[param_freq0] != freq_old[0] or *params[param_sep0] != sep_old[0] or *params[param_q0] != q_old[0] or *params[param_mode] != mode_old) {
+        lpL[0][0].set_lp_rbj((float)(*params[param_freq0] * (1 - *params[param_sep0])), *params[param_q0], (float)srate);
+        hpL[0][0].set_hp_rbj((float)(*params[param_freq0] * (1 + *params[param_sep0])), *params[param_q0], (float)srate);
+        lpR[0][0].copy_coeffs(lpL[0][0]);
+        hpR[0][0].copy_coeffs(hpL[0][0]);
+        for(i = 1; i <= j1; i++) {
+            lpL[0][i].copy_coeffs(lpL[0][0]);
+            hpL[0][i].copy_coeffs(hpL[0][0]);
+            lpR[0][i].copy_coeffs(lpL[0][0]);
+            hpR[0][i].copy_coeffs(hpL[0][0]);
+        }
+        freq_old[0] = *params[param_freq0];
+        sep_old[0]  = *params[param_sep0];
+        q_old[0]    = *params[param_q0];
+    }
+    if(*params[param_freq1] != freq_old[1] or *params[param_sep1] != sep_old[1] or *params[param_q1] != q_old[1] or *params[param_mode] != mode_old) {
+        lpL[1][0].set_lp_rbj((float)(*params[param_freq1] * (1 - *params[param_sep1])), *params[param_q1], (float)srate);
+        hpL[1][0].set_hp_rbj((float)(*params[param_freq1] * (1 + *params[param_sep1])), *params[param_q1], (float)srate);
+        lpR[1][0].copy_coeffs(lpL[1][0]);
+        hpR[1][0].copy_coeffs(hpL[1][0]);
+        for(i = 1; i <= j1; i++) {
+            lpL[1][i].copy_coeffs(lpL[1][0]);
+            hpL[1][i].copy_coeffs(hpL[1][0]);
+            lpR[1][i].copy_coeffs(lpL[1][0]);
+            hpR[1][i].copy_coeffs(hpL[1][0]);
+        }
+        freq_old[1] = *params[param_freq1];
+        sep_old[1]  = *params[param_sep1];
+        q_old[1]    = *params[param_q1];
+    }
+    if(*params[param_freq2] != freq_old[2] or *params[param_sep2] != sep_old[2] or *params[param_q2] != q_old[2] or *params[param_mode] != mode_old) {
+        lpL[2][0].set_lp_rbj((float)(*params[param_freq2] * (1 - *params[param_sep2])), *params[param_q2], (float)srate);
+        hpL[2][0].set_hp_rbj((float)(*params[param_freq2] * (1 + *params[param_sep2])), *params[param_q2], (float)srate);
+        lpR[2][0].copy_coeffs(lpL[2][0]);
+        hpR[2][0].copy_coeffs(hpL[2][0]);
+        for(i = 1; i <= j1; i++) {
+            lpL[2][i].copy_coeffs(lpL[2][0]);
+            hpL[2][i].copy_coeffs(hpL[2][0]);
+            lpR[2][i].copy_coeffs(lpL[2][0]);
+            hpR[2][i].copy_coeffs(hpL[2][0]);
+        }
+        freq_old[2] = *params[param_freq2];
+        sep_old[2]  = *params[param_sep2];
+        q_old[2]    = *params[param_q2];
+    }
+    // set the params of all strips
+    gate[0].set_params(*params[param_attack0], *params[param_release0], *params[param_threshold0], *params[param_ratio0], *params[param_knee0], *params[param_makeup0], *params[param_detection0], 1.f, *params[param_bypass0], !(solo[0] || no_solo), *params[param_range0]);
+    gate[1].set_params(*params[param_attack1], *params[param_release1], *params[param_threshold1], *params[param_ratio1], *params[param_knee1], *params[param_makeup1], *params[param_detection1], 1.f, *params[param_bypass1], !(solo[1] || no_solo), *params[param_range1]);
+    gate[2].set_params(*params[param_attack2], *params[param_release2], *params[param_threshold2], *params[param_ratio2], *params[param_knee2], *params[param_makeup2], *params[param_detection2], 1.f, *params[param_bypass2], !(solo[2] || no_solo), *params[param_range2]);
+    gate[3].set_params(*params[param_attack3], *params[param_release3], *params[param_threshold3], *params[param_ratio3], *params[param_knee3], *params[param_makeup3], *params[param_detection3], 1.f, *params[param_bypass3], !(solo[3] || no_solo), *params[param_range3]);
+}
+
+void multibandgate_audio_module::set_sample_rate(uint32_t sr)
+{
+    srate = sr;
+    // set srate of all strips
+    for (int j = 0; j < strips; j ++) {
+        gate[j].set_sample_rate(srate);
+    }
+}
+
+#define BYPASSED_GATING(index) \
+    if(params[param_gating##index] != NULL) \
+        *params[param_gating##index] = 1.0; \
+    if(params[param_output##index] != NULL) \
+        *params[param_output##index] = 0.0; 
+
+#define ACTIVE_GATING(index) \
+    if(params[param_gating##index] != NULL) \
+        *params[param_gating##index] = gate[index].get_expander_level(); \
+    if(params[param_output##index] != NULL) \
+        *params[param_output##index] = gate[index].get_output_level();
+
+uint32_t multibandgate_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;
+    for (int i = 0; i < strips; i++)
+        gate[i].update_curve();
+    if(bypass) {
+        // everything bypassed
+        while(offset < numsamples) {
+            outs[0][offset] = ins[0][offset];
+            outs[1][offset] = ins[1][offset];
+            ++offset;
+        }
+        // displays, too
+        clip_inL    = 0.f;
+        clip_inR    = 0.f;
+        clip_outL   = 0.f;
+        clip_outR   = 0.f;
+        meter_inL  = 0.f;
+        meter_inR  = 0.f;
+        meter_outL = 0.f;
+        meter_outR = 0.f;
+    } else {
+        // process all strips
+        
+        // let meters fall a bit
+        clip_inL    -= std::min(clip_inL,  numsamples);
+        clip_inR    -= std::min(clip_inR,  numsamples);
+        clip_outL   -= std::min(clip_outL, numsamples);
+        clip_outR   -= std::min(clip_outR, numsamples);
+        meter_inL = 0.f;
+        meter_inR = 0.f;
+        meter_outL = 0.f;
+        meter_outR = 0.f;
+        while(offset < numsamples) {
+            // cycle through samples
+            float inL = ins[0][offset];
+            float inR = ins[1][offset];
+            // in level
+            inR *= *params[param_level_in];
+            inL *= *params[param_level_in];
+            // out vars
+            float outL = 0.f;
+            float outR = 0.f;
+            int j1;
+            for (int i = 0; i < strips; i ++) {
+                // cycle trough strips
+                if (solo[i] || no_solo) {
+                    // strip unmuted
+                    float left  = inL;
+                    float right = inR;
+                    // send trough filters
+                    switch(mode) {
+                        case 0:
+                        default:
+                            j1 = 0;
+                            break;
+                        case 1:
+                            j1 = 2;
+                            break;
+                    }
+                    for (int j = 0; j <= j1; j++){
+                        if(i + 1 < strips) {
+                            left  = lpL[i][j].process(left);
+                            right = lpR[i][j].process(right);
+                            lpL[i][j].sanitize();
+                            lpR[i][j].sanitize();
+                        }
+                        if(i - 1 >= 0) {
+                            left  = hpL[i - 1][j].process(left);
+                            right = hpR[i - 1][j].process(right);
+                            hpL[i - 1][j].sanitize();
+                            hpR[i - 1][j].sanitize();
+                        }
+                    }
+                    // process gain reduction
+                    gate[i].process(left, right);
+                    // sum up output
+                    outL += left;
+                    outR += right;
+                } else {
+                    // strip muted
+                    
+                }
+                
+                
+            } // process single strip
+            
+            // even out filters gain reduction
+            // 3dB - levelled manually (based on default sep and q settings)
+            switch(mode) {
+                case 0:
+                    outL *= 1.414213562;
+                    outR *= 1.414213562;
+                    break;
+                case 1:
+                    outL *= 0.88;
+                    outR *= 0.88;
+                    break;
+            }
+            
+            // out level
+            outL *= *params[param_level_out];
+            outR *= *params[param_level_out];
+            
+            // send to output
+            outs[0][offset] = outL;
+            outs[1][offset] = outR;
+            
+            // clip LED's
+            if(inL > 1.f) {
+                clip_inL  = srate >> 3;
+            }
+            if(inR > 1.f) {
+                clip_inR  = srate >> 3;
+            }
+            if(outL > 1.f) {
+                clip_outL = srate >> 3;
+            }
+            if(outR > 1.f) {
+                clip_outR = srate >> 3;
+            }
+            // set up in / out meters
+            if(inL > meter_inL) {
+                meter_inL = inL;
+            }
+            if(inR > meter_inR) {
+                meter_inR = inR;
+            }
+            if(outL > meter_outL) {
+                meter_outL = outL;
+            }
+            if(outR > meter_outR) {
+                meter_outR = outR;
+            }
+            // next sample
+            ++offset;
+        } // cycle trough samples
+        
+    } // process all strips (no bypass)
+    
+    // draw meters
+    SET_IF_CONNECTED(clip_inL);
+    SET_IF_CONNECTED(clip_inR);
+    SET_IF_CONNECTED(clip_outL);
+    SET_IF_CONNECTED(clip_outR);
+    SET_IF_CONNECTED(meter_inL);
+    SET_IF_CONNECTED(meter_inR);
+    SET_IF_CONNECTED(meter_outL);
+    SET_IF_CONNECTED(meter_outR);
+    // draw strip meters
+    if(bypass > 0.5f) {
+        BYPASSED_GATING(0)
+        BYPASSED_GATING(1)
+        BYPASSED_GATING(2)
+        BYPASSED_GATING(3)
+    } else {
+        ACTIVE_GATING(0)
+        ACTIVE_GATING(1)
+        ACTIVE_GATING(2)
+        ACTIVE_GATING(3)
+    }
+    // whatever has to be returned x)
+    return outputs_mask;
+}
+
+const expander_audio_module *multibandgate_audio_module::get_strip_by_param_index(int index) const
+{
+    // let's handle by the corresponding strip
+    switch (index) {
+        case param_gating0:
+            return &gate[0];
+        case param_gating1:
+            return &gate[1];
+        case param_gating2:
+            return &gate[2];
+        case param_gating3:
+            return &gate[3];
+    }
+    return NULL;
+}
+
+bool multibandgate_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context) const
+{
+    const expander_audio_module *m = get_strip_by_param_index(index);
+    if (m)
+        return m->get_graph(subindex, data, points, context);
+    return false;
+}
+
+bool multibandgate_audio_module::get_dot(int index, int subindex, float &x, float &y, int &size, cairo_iface *context) const
+{
+    const expander_audio_module *m = get_strip_by_param_index(index);
+    if (m)
+        return m->get_dot(subindex, x, y, size, context);
+    return false;
+}
+
+bool multibandgate_audio_module::get_gridline(int index, int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context) const
+{ 
+    const expander_audio_module *m = get_strip_by_param_index(index);
+    if (m)
+        return m->get_gridline(subindex, pos, vertical, legend, context);
+    return false;
+}
+
+int multibandgate_audio_module::get_changed_offsets(int index, int generation, int &subindex_graph, int &subindex_dot, int &subindex_gridline) const
+{
+    const expander_audio_module *m = get_strip_by_param_index(index);
+    if (m)
+        return m->get_changed_offsets(generation, subindex_graph, subindex_dot, subindex_gridline);
+    return 0;
+}
+
+
 /// Gain reduction module by Thor
 /// All functions of this module are originally written
 /// by Thor, while some features have been stripped (mainly stereo linking
diff --git a/src/modules_dist.cpp b/src/modules_dist.cpp
index 559e785..ddc147d 100644
--- a/src/modules_dist.cpp
+++ b/src/modules_dist.cpp
@@ -295,6 +295,15 @@ void exciter_audio_module::params_changed()
         }
         freq_old = *params[param_freq];
     }
+    // set the params of all filters
+    if(*params[param_ceil] != ceil_old or *params[param_ceil_active] != ceil_active_old) {
+        lp[0][0].set_lp_rbj(*params[param_ceil], 0.707, (float)srate);
+        lp[0][1].copy_coeffs(lp[0][0]);
+        lp[1][0].copy_coeffs(lp[0][0]);
+        lp[1][1].copy_coeffs(lp[0][0]);
+        ceil_old = *params[param_ceil];
+        ceil_active_old = *params[param_ceil_active];
+    }
     // set distortion
     dist[0].set_params(*params[param_blend], *params[param_drive]);
     if(in_count > 1 && out_count > 1)
@@ -378,6 +387,12 @@ uint32_t exciter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
 
                 // all post filters in chain
                 proc[i] = hp[i][2].process(hp[i][3].process(proc[i]));
+                
+                if(*params[param_ceil_active] > 0.5f) {
+                    // all H/P post filters in chain
+                    proc[i] = lp[i][0].process(lp[i][1].process(proc[i]));
+                    
+                }
             }
             maxDrive = dist[0].get_distortion_level() * *params[param_amount];
             
@@ -469,6 +484,15 @@ void bassenhancer_audio_module::params_changed()
         }
         freq_old = *params[param_freq];
     }
+    // set the params of all filters
+    if(*params[param_floor] != floor_old or *params[param_floor_active] != floor_active_old) {
+        hp[0][0].set_hp_rbj(*params[param_floor], 0.707, (float)srate);
+        hp[0][1].copy_coeffs(hp[0][0]);
+        hp[1][0].copy_coeffs(hp[0][0]);
+        hp[1][1].copy_coeffs(hp[0][0]);
+        floor_old = *params[param_floor];
+        floor_active_old = *params[param_floor_active];
+    }
     // set distortion
     dist[0].set_params(*params[param_blend], *params[param_drive]);
     if(in_count > 1 && out_count > 1)
@@ -549,6 +573,12 @@ uint32_t bassenhancer_audio_module::process(uint32_t offset, uint32_t numsamples
 
                 // all post filters in chain
                 proc[i] = lp[i][2].process(lp[i][3].process(proc[i]));
+                
+                if(*params[param_floor_active] > 0.5f) {
+                    // all H/P post filters in chain
+                    proc[i] = hp[i][0].process(hp[i][1].process(proc[i]));
+                    
+                }
             }
             
             if(in_count > 1 && out_count > 1) {
diff --git a/src/modules_limit.cpp b/src/modules_limit.cpp
index 05f2176..f7fb6fc 100644
--- a/src/modules_limit.cpp
+++ b/src/modules_limit.cpp
@@ -15,7 +15,7 @@
  *
  * 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, 
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301  USA
  */
 #include <limits.h>
@@ -48,6 +48,9 @@ limiter_audio_module::limiter_audio_module()
     meter_outL = 0.f;
     meter_outR = 0.f;
     asc_led    = 0.f;
+    attack_old = -1.f;
+    limit_old = -1.f;
+    asc_old = true;
 }
 
 void limiter_audio_module::activate()
@@ -66,7 +69,16 @@ 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, *params[param_asc], true);
+    limiter.set_params(*params[param_limit], *params[param_attack], *params[param_release], 1.f, *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1), true);
+    if( *params[param_attack] != attack_old) {
+        attack_old = *params[param_attack];
+        limiter.reset();
+    }
+    if(*params[param_limit] != limit_old or *params[param_asc] != asc_old) {
+        asc_old = *params[param_asc];
+        limit_old = *params[param_limit];
+        limiter.reset_asc();
+    }
 }
 
 void limiter_audio_module::set_sample_rate(uint32_t sr)
@@ -107,7 +119,7 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
         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,25 +130,32 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
             // out vars
             float outL = inL;
             float outR = inR;
-            
+
             // process gain reduction
             float fickdich[0];
             limiter.process(outL, outR, fickdich);
-            if(limiter.get_arc())
+            if(limiter.get_asc())
                 asc_led = srate >> 3;
-            
+
+            // should never be used. but hackers are paranoid by default.
+            // so we make shure NOTHING is above limit
+            outL = std::max(outL, -*params[param_limit]);
+            outL = std::min(outL, *params[param_limit]);
+            outR = std::max(outR, -*params[param_limit]);
+            outR = std::min(outR, *params[param_limit]);
+
             // autolevel
             outL /= *params[param_limit];
             outR /= *params[param_limit];
-            
+
             // out level
             outL *= *params[param_level_out];
             outR *= *params[param_level_out];
-            
+
             // send to output
             outs[0][offset] = outL;
             outs[1][offset] = outR;
-            
+
             // clip LED's
             if(inL > 1.f) {
                 clip_inL  = srate >> 3;
@@ -166,9 +185,9 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
             // next sample
             ++offset;
         } // cycle trough samples
-        
+
     } // process (no bypass)
-    
+
     // draw meters
     SET_IF_CONNECTED(clip_inL);
     SET_IF_CONNECTED(clip_inR);
@@ -178,16 +197,16 @@ uint32_t limiter_audio_module::process(uint32_t offset, uint32_t numsamples, uin
     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;
-     
+
     if (*params[param_att]) {
         if(bypass)
             *params[param_att] = 1.f;
         else
             *params[param_att] = limiter.get_attenuation();
     }
-    
+
     // whatever has to be returned x)
     return outputs_mask;
 }
@@ -214,7 +233,7 @@ multibandlimiter_audio_module::multibandlimiter_audio_module()
     meter_outL = 0.f;
     meter_outR = 0.f;
     asc_led    = 0.f;
-    __attack = -1.f;
+    attack_old = -1.f;
     channels = 2;
     buffer_size = 0;
     overall_buffer_size = 0;
@@ -225,6 +244,12 @@ multibandlimiter_audio_module::multibandlimiter_audio_module()
         q_old[i] = -1;
     }
     mode_old = 0;
+    for(int i = 0; i < strips; i ++) {
+        weight_old[i] = -1.f;
+    }
+    attack_old = -1.f;
+    limit_old = -1.f;
+    asc_old = true;
 }
 
 void multibandlimiter_audio_module::activate()
@@ -263,7 +288,7 @@ void multibandlimiter_audio_module::params_changed()
             *params[param_solo1] > 0.f ||
             *params[param_solo2] > 0.f ||
             *params[param_solo3] > 0.f) ? false : true;
-            
+
     mode_old = mode;
     mode = *params[param_mode];
     int i;
@@ -325,35 +350,51 @@ void multibandlimiter_audio_module::params_changed()
     }
     // set the params of all strips
     float rel;
-    
+
     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], *params[param_asc], true);
+    strip[0].set_params(*params[param_limit], *params[param_attack], rel, weight[0], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1), 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], *params[param_asc]);
+    strip[1].set_params(*params[param_limit], *params[param_attack], rel, weight[1], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1));
     *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], *params[param_asc]);
+    strip[2].set_params(*params[param_limit], *params[param_attack], rel, weight[2], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1));
     *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], *params[param_asc]);
+    strip[3].set_params(*params[param_limit], *params[param_attack], rel, weight[3], *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1));
     *params[param_effrelease3] = rel;
-    broadband.set_params(*params[param_limit], *params[param_attack], rel, 1.f, *params[param_asc]);
+    broadband.set_params(*params[param_limit], *params[param_attack], rel, 1.f, *params[param_asc], pow(0.5, (*params[param_asc_coeff] - 0.5) * 2 * -1));
     // rebuild multiband buffer
-    if( *params[param_attack] != __attack) {
+    if( *params[param_attack] != attack_old) {
         int bs = (int)(srate * (*params[param_attack] / 1000.f) * channels);
         buffer_size = bs - bs % channels; // buffer size attack rate
-        __attack = *params[param_attack];
+        attack_old = *params[param_attack];
         _sanitize = true;
         pos = 0;
+        for (int j = 0; j < strips; j ++) {
+            strip[j].reset();
+        }
+        broadband.reset();
+    }
+    if(*params[param_limit] != limit_old or *params[param_asc] != asc_old or *params[param_weight0] != weight_old[0] or *params[param_weight1] != weight_old[1] or *params[param_weight2] != weight_old[2] or *params[param_weight3] != weight_old[3] ) {
+        asc_old = *params[param_asc];
+        limit_old = *params[param_limit];
+        weight_old[0] = *params[param_weight0];
+        weight_old[1] = *params[param_weight1];
+        weight_old[2] = *params[param_weight2];
+        weight_old[3] = *params[param_weight3];
+        for (int j = 0; j < strips; j ++) {
+            strip[j].reset_asc();
+        }
+        broadband.reset_asc();
     }
 }
 
@@ -379,7 +420,7 @@ void multibandlimiter_audio_module::set_sample_rate(uint32_t sr)
 #define ACTIVE_COMPRESSION(index) \
     if(params[param_att##index] != NULL) \
         *params[param_att##index] = strip[index].get_attenuation(); \
-        
+
 uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsamples, uint32_t inputs_mask, uint32_t outputs_mask)
 {
     bool bypass = *params[param_bypass] > 0.5f;
@@ -404,7 +445,7 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
         asc_led    = 0.f;
     } else {
         // process all strips
-        
+
         // let meters fall a bit
         clip_inL    -= std::min(clip_inL,  numsamples);
         clip_inR    -= std::min(clip_inR,  numsamples);
@@ -479,20 +520,20 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
                         hpR[i - 1][j].sanitize();
                     }
                 }
-                
+
                 // remember filtered values for limiting
                 // (we need multiband_coeff before we can call the limiter bands)
                 _tmpL[i] = left;
                 _tmpR[i] = right;
-                
+
                 // sum up for multiband coefficient
                 sum_left += ((fabs(left) > *params[param_limit]) ? *params[param_limit] * (fabs(left) / left) : left) * weight[i];
                 sum_right += ((fabs(right) > *params[param_limit]) ? *params[param_limit] * (fabs(right) / right) : right) * weight[i];
             } // process single strip with filter
-            
+
             // write multiband coefficient to buffer
             buffer[pos] = std::min(*params[param_limit] / std::max(fabs(sum_left), fabs(sum_right)), 1.0);
-            
+
             for (int i = 0; i < strips; i++) {
                 // process gain reduction
                 strip[i].process(_tmpL[i], _tmpR[i], buffer);
@@ -501,24 +542,33 @@ 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();
+                asc_active = asc_active || strip[i].get_asc();
             } // process single strip again for limiter
             float fickdich[0];
             broadband.process(outL, outR, fickdich);
+            asc_active = asc_active || broadband.get_asc();
+
+            // should never be used. but hackers are paranoid by default.
+            // so we make shure NOTHING is above limit
+            outL = std::max(outL, -*params[param_limit]);
+            outL = std::min(outL, *params[param_limit]);
+            outR = std::max(outR, -*params[param_limit]);
+            outR = std::min(outR, *params[param_limit]);
+
             batt = broadband.get_attenuation();
-            
+
             // autolevel
             outL /= *params[param_limit];
             outR /= *params[param_limit];
-            
+
             // out level
             outL *= *params[param_level_out];
             outR *= *params[param_level_out];
-            
+
             // send to output
             outs[0][offset] = outL;
             outs[1][offset] = outR;
-            
+
             // clip LED's
             if(ins[0][offset] * *params[param_level_in] > 1.f) {
                 clip_inL  = srate >> 3;
@@ -553,9 +603,9 @@ uint32_t multibandlimiter_audio_module::process(uint32_t offset, uint32_t numsam
             pos = (pos + channels) % buffer_size;
             if(pos == 0) _sanitize = false;
         } // cycle trough samples
-        
+
     } // process all strips (no bypass)
-    
+
     // draw meters
     SET_IF_CONNECTED(clip_inL);
     SET_IF_CONNECTED(clip_inR);
@@ -565,16 +615,16 @@ 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;
         if(params[param_att1] != NULL) *params[param_att1] = 1.0;
         if(params[param_att2] != NULL) *params[param_att2] = 1.0;
         if(params[param_att3] != NULL) *params[param_att3] = 1.0;
-           
+
     } else {
         if(params[param_att0] != NULL) *params[param_att0] = strip[0].get_attenuation() * batt;
         if(params[param_att1] != NULL) *params[param_att1] = strip[1].get_attenuation() * batt;
@@ -643,4 +693,3 @@ bool multibandlimiter_audio_module::get_gridline(int index, int subindex, float
         return get_freq_gridline(subindex, pos, vertical, legend, context);
     }
 }
-

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list