diff --git a/Makefile b/Makefile index a13b536..35d2db4 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ SLUG = Bidoo -VERSION = 0.5.18 +VERSION = 0.5.19 FLAGS = -I./pffft -DPFFFT_SIMD_DISABLE -SOURCES = $(wildcard src/*.cpp src/dep/audiofile/*cpp src/dep/pffft/*c) +SOURCES = $(wildcard src/*.cpp src/dep/audiofile/*cpp src/dep/pffft/*c src/dep/filters/*cpp) DISTRIBUTABLES += $(wildcard LICENSE*) res diff --git a/README.md b/README.md index 2b22f1d..f861803 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Bidoo's plugins for [VCVRack](https://vcvrack.com) -![Version](https://img.shields.io/badge/version-0.5.18-green.svg?style=flat-square) +![Version](https://img.shields.io/badge/version-0.5.19-green.svg?style=flat-square) ![License](https://img.shields.io/badge/license-BSD3-blue.svg?style=flat-square) ![Language](https://img.shields.io/badge/language-C++-yellow.svg?style=flat-square) @@ -13,11 +13,16 @@ You can find information on that plugins pack in the [wiki](https://github.com/s ## Last changes -0.5.18 +0.5.19 -lIMbO +lIMbO the 4th order ladder filter has a second mode i.e. "non linear". In that mode the GAIN control is no more a gain on the output but a gain on the tanh() that introduces non linearity. + +pErCO is a step in my journey across filters. To achieve the next plugin I needed a BP filter so I tried this approach. The result is a very simple 1st order LP, BP, HP filter. + +ziNC is the plugin I wanted to do with filters. It is a 16 band vocoder. I started this plugin with pErCO's BP but I needed more selective filters so I finally used 4 poles BP. +If you are interested in filter design and more generally in dsp I recommend that website http://www.earlevel.com. +Controls are gains for the 16 bands. Attack and Decay for the envelop follower and gain stages for MODulator, CARRier and OUTput. -lIMbO is a ladder LPF. Based on Will Pirkle's courses & Vadim Zavalishin's book. ## License diff --git a/images/pack.png b/images/pack.png index 9bf74ce..1006e70 100644 Binary files a/images/pack.png and b/images/pack.png differ diff --git a/res/LIMBO.svg b/res/LIMBO.svg index e5e2020..e419258 100644 --- a/res/LIMBO.svg +++ b/res/LIMBO.svg @@ -78,7 +78,7 @@ + style="opacity:0.08;fill:#000000;stroke-width:0.17951877" /> @@ -90,23 +90,23 @@ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:125%;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" aria-label="bId°°"> @@ -115,23 +115,23 @@ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:125%;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" aria-label="lIMbO"> @@ -148,15 +148,15 @@ transform="rotate(-179.84442)" aria-label="OUT"> @@ -174,11 +174,11 @@ transform="rotate(-179.84442)" aria-label="IN"> @@ -188,138 +188,194 @@ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;line-height:125%;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" aria-label="FREQ"> + id="path914" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 6.6290871,35.181533 q 0.107487,0.02756 0.1832791,0.10473 0.075792,0.07579 0.1887912,0.304547 l 0.2797417,0.562239 H 6.9818649 l -0.2452908,-0.51952 q -0.106109,-0.221864 -0.1915473,-0.285254 -0.08406,-0.06477 -0.2204862,-0.06477 H 6.0585793 v 0.869542 H 5.7788375 v -2.057411 h 0.5732639 q 0.3389974,0 0.5195204,0.152963 0.180523,0.152962 0.180523,0.44235 0,0.20395 -0.1116211,0.333485 -0.110243,0.128158 -0.3114366,0.157097 z m -0.5705078,-0.85714 v 0.73036 h 0.3045464 q 0.1998155,0 0.2976563,-0.08957 0.097841,-0.08957 0.097841,-0.27423 0,-0.177767 -0.1047309,-0.271474 -0.1033529,-0.09508 -0.3017904,-0.09508 z" /> + id="path916" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 7.5509946,34.095638 h 1.2209419 v 0.234267 H 7.8293583 v 0.609093 h 0.901237 v 0.234266 h -0.901237 v 0.745519 h 0.9687609 v 0.234266 H 7.5509946 Z" /> + id="path918" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 10.371839,34.165918 v 0.282498 q -0.12678,-0.0813 -0.254937,-0.122645 -0.1267798,-0.04134 -0.2563153,-0.04134 -0.1970595,0 -0.3114367,0.09233 -0.1143772,0.09095 -0.1143772,0.246669 0,0.136426 0.074414,0.208084 0.075792,0.07166 0.2811198,0.119889 l 0.1460721,0.03307 q 0.2893883,0.06752 0.4216793,0.212218 0.132292,0.144694 0.132292,0.394119 0,0.293522 -0.181901,0.447862 -0.181901,0.154341 -0.5291667,0.154341 -0.144694,0 -0.2907661,-0.03169 -0.146072,-0.03032 -0.2935221,-0.09233 v -0.296278 q 0.1584744,0.100597 0.2990343,0.14745 0.1419379,0.04685 0.2852539,0.04685 0.2108398,0 0.3279727,-0.09371 0.117134,-0.09509 0.117134,-0.264584 0,-0.15434 -0.08131,-0.235644 -0.07993,-0.0813 -0.2797414,-0.125402 L 9.7145095,35.213225 Q 9.4278776,35.148455 9.298342,35.017544 9.1688064,34.88663 9.1688064,34.666144 q 0,-0.275607 0.1846571,-0.440972 0.1860352,-0.166743 0.4933377,-0.166743 0.1185113,0 0.2494248,0.02756 0.130914,0.02618 0.275608,0.07993 z" /> + id="path921" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 22.029788,35.983555 q -0.111621,0.103352 -0.252181,0.157096 -0.139181,0.05237 -0.30179,0.05237 -0.391363,0 -0.609093,-0.279741 -0.21773,-0.28112 -0.21773,-0.78686 0,-0.504362 0.220486,-0.785482 0.220486,-0.282498 0.613227,-0.282498 0.129536,0 0.248047,0.03721 0.118511,0.03583 0.228755,0.110243 v 0.285254 q -0.111622,-0.106109 -0.228755,-0.155718 -0.117133,-0.05099 -0.248047,-0.05099 -0.271473,0 -0.407899,0.21084 -0.135048,0.209462 -0.135048,0.631142 0,0.42857 0.130914,0.635275 0.132292,0.205328 0.405143,0.205328 0.09233,0 0.161231,-0.02067 0.07028,-0.02205 0.126779,-0.06752 V 35.32623 h -0.299034 v -0.228754 h 0.564995 z" /> + id="path923" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 23.055049,34.340933 -0.293522,1.052821 h 0.587044 z m -0.168121,-0.245291 h 0.33762 l 0.629763,2.057411 h -0.28801 l -0.151584,-0.536057 h -0.720714 l -0.148828,0.536057 h -0.28801 z" /> + id="path925" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="M 24.180906,34.095642 H 25.3233 v 0.234267 h -0.431326 v 1.588878 H 25.3233 v 0.234266 h -1.142394 v -0.234266 h 0.431326 v -1.588878 h -0.431326 z" /> + id="path927" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 25.793211,34.095642 h 0.352778 l 0.694531,1.693609 v -1.693609 h 0.268717 v 2.057411 H 26.75646 l -0.694532,-1.693609 v 1.693609 h -0.268717 z" /> + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;line-height:125%;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + aria-label="F.MOD"> + id="path930" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 4.1375941,51.445732 h 1.2112955 v 0.234267 H 4.4173358 v 0.606337 h 0.8447374 v 0.234266 H 4.4173358 v 0.982541 H 4.1375941 Z" /> + id="path932" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 6.1881149,53.082842 h 0.3472656 v 0.420301 H 6.1881149 Z" /> + id="path934" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 7.3305086,51.445732 h 0.3720703 l 0.3555338,1.047309 0.35829,-1.047309 H 8.789851 v 2.057411 H 8.5321579 V 51.685511 L 8.1655997,52.770027 H 7.9547599 L 7.5868237,51.685511 v 1.817632 H 7.3305086 Z" /> + id="path936" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px" + d="m 10.156865,52.476505 q 0,-0.453375 -0.09371,-0.647678 -0.092328,-0.194303 -0.304546,-0.194303 -0.2108399,0 -0.3045465,0.194303 -0.092329,0.194303 -0.092329,0.647678 0,0.451996 0.092329,0.6463 0.093707,0.194303 0.3045465,0.194303 0.2122179,0 0.304546,-0.192925 0.09371,-0.194304 0.09371,-0.647678 z m 0.290766,0 q 0,0.537435 -0.170877,0.802018 -0.169498,0.264583 -0.518142,0.264583 -0.3486437,0 -0.5181424,-0.263205 -0.1694987,-0.263205 -0.1694987,-0.803396 0,-0.538813 0.1694987,-0.803396 0.1708768,-0.264584 0.5181424,-0.264584 0.348644,0 0.518142,0.264584 0.170877,0.264583 0.170877,0.803396 z" /> + + d="m 3.3642882,70.513237 h 1.2112955 v 0.234267 H 3.6440299 v 0.606336 h 0.8447374 v 0.234267 H 3.6440299 v 0.982541 H 3.3642882 Z" /> + d="m 5.7882574,71.599131 q 0.1074869,0.02756 0.183279,0.104731 0.075792,0.07579 0.1887913,0.304547 l 0.2797417,0.562239 H 6.1410351 L 5.8957443,72.051128 Q 5.7896354,71.829264 5.704197,71.765874 5.6201367,71.701106 5.4837109,71.701106 H 5.2177495 v 0.869542 H 4.9380078 v -2.057411 h 0.5732639 q 0.3389974,0 0.5195204,0.152962 0.180523,0.152963 0.180523,0.442351 0,0.203949 -0.1116211,0.333485 -0.1102431,0.128157 -0.3114366,0.157096 z M 5.2177495,70.741992 v 0.73036 H 5.522296 q 0.1998155,0 0.2976562,-0.08957 0.097841,-0.08957 0.097841,-0.274229 0,-0.177767 -0.1047309,-0.271474 -0.1033528,-0.09508 -0.3017903,-0.09508 z" /> + d="m 6.7101649,70.513237 h 1.2209418 v 0.234267 H 6.9885286 v 0.609093 h 0.901237 v 0.234266 h -0.901237 v 0.745519 h 0.9687609 v 0.234266 H 6.7101649 Z" /> + d="m 9.0390496,72.607855 q -0.00965,0 -0.027561,0.0014 -0.017914,0.0014 -0.028939,0.0014 -0.3445095,0 -0.5153863,-0.264583 Q 8.297665,72.081445 8.297665,71.54401 q 0,-0.538813 0.1694987,-0.803397 0.1708768,-0.264583 0.5181424,-0.264583 0.3486437,0 0.5181423,0.264583 0.1708768,0.264584 0.1708768,0.803397 0,0.405143 -0.095085,0.65319 -0.093707,0.246669 -0.285254,0.345887 l 0.2756077,0.261828 -0.2080838,0.137804 z M 9.3835591,71.54401 q 0,-0.453375 -0.093707,-0.647678 -0.092329,-0.194304 -0.3045464,-0.194304 -0.2108399,0 -0.3045465,0.194304 -0.092329,0.194303 -0.092329,0.647678 0,0.451996 0.092329,0.6463 0.093707,0.194303 0.3045465,0.194303 0.2122179,0 0.3045464,-0.192925 0.093707,-0.194304 0.093707,-0.647678 z" /> + d="m 14.032844,71.765185 q 0.107487,0.02756 0.183279,0.104731 0.07579,0.07579 0.188791,0.304546 l 0.279742,0.56224 h -0.299035 l -0.24529,-0.51952 q -0.106109,-0.221865 -0.191548,-0.285254 -0.08406,-0.06477 -0.220486,-0.06477 H 13.462336 V 72.7367 h -0.279742 v -2.057411 h 0.573264 q 0.338997,0 0.51952,0.152962 0.180523,0.152962 0.180523,0.44235 0,0.20395 -0.111621,0.333486 -0.110243,0.128157 -0.311436,0.157096 z m -0.570508,-0.85714 v 0.730361 h 0.304546 q 0.199816,0 0.297657,-0.08957 0.09784,-0.08957 0.09784,-0.27423 0,-0.177766 -0.104731,-0.271473 -0.103352,-0.09508 -0.30179,-0.09508 z" /> + d="m 14.954751,70.679291 h 1.220942 v 0.234266 h -0.942578 v 0.609093 h 0.901237 v 0.234267 h -0.901237 v 0.745518 h 0.968761 v 0.234267 h -1.247125 z" /> + d="m 17.775595,70.749571 v 0.282498 q -0.126779,-0.08131 -0.254937,-0.122646 -0.126779,-0.04134 -0.256315,-0.04134 -0.197059,0 -0.311436,0.09233 -0.114378,0.09095 -0.114378,0.246669 0,0.136425 0.07441,0.208083 0.07579,0.07166 0.281119,0.11989 l 0.146072,0.03307 q 0.289388,0.06752 0.42168,0.212217 0.132292,0.144694 0.132292,0.394119 0,0.293523 -0.181901,0.447863 -0.181901,0.15434 -0.529167,0.15434 -0.144694,0 -0.290766,-0.03169 -0.146072,-0.03032 -0.293522,-0.09233 v -0.296279 q 0.158474,0.100597 0.299034,0.147451 0.141938,0.04685 0.285254,0.04685 0.21084,0 0.327973,-0.09371 0.117133,-0.09508 0.117133,-0.264583 0,-0.15434 -0.0813,-0.235645 -0.07993,-0.0813 -0.279742,-0.125401 l -0.148828,-0.03445 q -0.286632,-0.06477 -0.416167,-0.195682 -0.129536,-0.130913 -0.129536,-0.351399 0,-0.275608 0.184657,-0.440972 0.186035,-0.166743 0.493338,-0.166743 0.118511,0 0.249425,0.02756 0.130913,0.02618 0.275607,0.07993 z" /> + d="m 22.940492,72.567203 q -0.111621,0.103353 -0.252181,0.157097 -0.139182,0.05236 -0.30179,0.05236 -0.391363,0 -0.609093,-0.279742 -0.21773,-0.281119 -0.21773,-0.786859 0,-0.504362 0.220486,-0.785482 0.220486,-0.282498 0.613227,-0.282498 0.129536,0 0.248047,0.03721 0.118511,0.03583 0.228754,0.110243 v 0.285254 q -0.111621,-0.106109 -0.228754,-0.155718 -0.117133,-0.05099 -0.248047,-0.05099 -0.271474,0 -0.407899,0.21084 -0.135048,0.209462 -0.135048,0.631142 0,0.428569 0.130914,0.635275 0.132291,0.205328 0.405143,0.205328 0.09233,0 0.16123,-0.02067 0.07028,-0.02205 0.12678,-0.06752 V 71.90988 h -0.299035 v -0.228754 h 0.564996 z" /> + d="m 23.965753,70.924582 -0.293523,1.052821 h 0.587045 z m -0.168121,-0.245291 h 0.337619 l 0.629764,2.057411 h -0.28801 l -0.151584,-0.536057 h -0.720714 l -0.148829,0.536057 h -0.28801 z" /> + d="m 25.09161,70.679291 h 1.142393 v 0.234266 h -0.431326 v 1.588878 h 0.431326 v 0.234267 H 25.09161 v -0.234267 h 0.431326 V 70.913557 H 25.09161 Z" /> + d="m 26.703915,70.679291 h 0.352777 l 0.694532,1.693609 v -1.693609 h 0.268717 v 2.057411 h -0.352778 l -0.694531,-1.693609 v 1.693609 h -0.268717 z" /> + + + + + + + + + + + + + + + diff --git a/res/LIMBOtemp.svg b/res/LIMBOtemp.svg index fd08f94..4a5e204 100644 --- a/res/LIMBOtemp.svg +++ b/res/LIMBOtemp.svg @@ -28,9 +28,9 @@ inkscape:window-height="1017" id="namedview118" showgrid="true" - inkscape:zoom="1.1137255" - inkscape:cx="-255.48368" - inkscape:cy="298.63246" + inkscape:zoom="2.227451" + inkscape:cx="-15.814717" + inkscape:cy="134.24544" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" @@ -108,7 +108,7 @@ inkscape:connector-curvature="0" /> @@ -218,70 +218,112 @@ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777766px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr;text-anchor:start;stroke-width:0.26458332px;">FREQ RES + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px">RES GAIN + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px">GAIN F.CV + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.82222223px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332px">F.MOD FREQ RES GAIN - + NON LIN + LIN + diff --git a/res/PERCO.svg b/res/PERCO.svg new file mode 100644 index 0000000..75d67cd --- /dev/null +++ b/res/PERCO.svg @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/PERCOtemp.svg b/res/PERCOtemp.svg new file mode 100644 index 0000000..879c693 --- /dev/null +++ b/res/PERCOtemp.svg @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + bId°° + pErCO + FREQ + RES + F.MOD + + + FREQ + + + + RES + + + + IN + + + + LP + + + + HP + + + + BP + + diff --git a/res/ZINC.svg b/res/ZINC.svg new file mode 100644 index 0000000..1177347 --- /dev/null +++ b/res/ZINC.svg @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/ZINCtemp.svg b/res/ZINCtemp.svg new file mode 100644 index 0000000..8cd004c --- /dev/null +++ b/res/ZINCtemp.svg @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + bId°° + ziNC + + MOD + + OUT + + CAR + A + D + MOD + CAR + OUT + diff --git a/src/Bidoo.cpp b/src/Bidoo.cpp index 7bf3ec5..8e67d36 100644 --- a/src/Bidoo.cpp +++ b/src/Bidoo.cpp @@ -25,4 +25,6 @@ void init(rack::Plugin *p) { p->addModel(createModel("Bidoo", "clACos", "clACos oscillator", OSCILLATOR_TAG)); p->addModel(createModel("Bidoo", "baR", "bAR compressor", DYNAMICS_TAG)); p->addModel(createModel("Bidoo", "lIMbO", "lIMbO filter", FILTER_TAG)); + p->addModel(createModel("Bidoo", "pErCO", "pErCO filter", FILTER_TAG)); + p->addModel(createModel("Bidoo", "ziNC", "ziNC vocoder", EFFECT_TAG)); } diff --git a/src/Bidoo.hpp b/src/Bidoo.hpp index 251fa94..4f01285 100644 --- a/src/Bidoo.hpp +++ b/src/Bidoo.hpp @@ -91,3 +91,11 @@ struct BARWidget : ModuleWidget { struct LIMBOWidget : ModuleWidget { LIMBOWidget(); }; + +struct PERCOWidget : ModuleWidget { + PERCOWidget(); +}; + +struct ZINCWidget : ModuleWidget { + ZINCWidget(); +}; diff --git a/src/LIMBO.cpp b/src/LIMBO.cpp index 0fdc667..89174f0 100644 --- a/src/LIMBO.cpp +++ b/src/LIMBO.cpp @@ -12,11 +12,16 @@ struct FilterStage { float mem = 0.0; - float Filter(float sample, float freq, float smpRate) + float Filter(float sample, float freq, float smpRate, float gain, int mode) { float g = tan(pi*freq/smpRate); float G = g/(1.0 + g); - float out = (sample - mem) * G + mem; + float out; + if (mode == 0) { + out = (sample - mem) * G + mem; + } else { + out = (tanh(sample*gain)/tanh(gain) - mem) * G + mem; + } mem = out + (sample - mem) * G ; return out; } @@ -31,11 +36,15 @@ struct LadderFilter float q; float freq; float smpRate; + int mode = 0; + float gain = 1; - void setParams(float freq, float q, float smpRate) { + void setParams(float freq, float q, float smpRate, float gain, int mode) { this->freq = freq; this->q=q; this->smpRate=smpRate; + this->mode = mode; + this->gain = gain; } float calcOutput(float sample) @@ -48,7 +57,7 @@ struct LadderFilter float S3 = stage3.mem/(1 + g); float S4 = stage4.mem/(1 + g); float S = G*G*G*S1 + G*G*S2 + G*S3 + S4; - return stage4.Filter(stage3.Filter(stage2.Filter(stage1.Filter((sample - q*S)/(1 + q*G),freq,smpRate),freq,smpRate),freq,smpRate),freq,smpRate); + return stage4.Filter(stage3.Filter(stage2.Filter(stage1.Filter((sample - q*S)/(1 + q*G),freq,smpRate,gain,mode),freq,smpRate,gain,mode),freq,smpRate,gain,mode),freq,smpRate,gain,mode); } }; @@ -59,6 +68,7 @@ struct LIMBO : Module { Q_PARAM, CMOD_PARAM, MUG_PARAM, + MODE_PARAM, NUM_PARAMS }; enum InputIds { @@ -90,14 +100,14 @@ struct LIMBO : Module { void LIMBO::step() { float cfreq = pow(2,rescalef(clampf(params[CUTOFF_PARAM].value + params[CMOD_PARAM].value * inputs[CUTOFF_INPUT].value / 5,0,1),0,1,4.5,13)); float q = 3.5 * clampf(params[Q_PARAM].value + inputs[Q_INPUT].value / 5.0, 0.0, 1.0); - lFilter.setParams(cfreq,q,engineGetSampleRate()); - rFilter.setParams(cfreq,q,engineGetSampleRate()); + float g = pow(2,rescalef(clampf(params[MUG_PARAM].value + inputs[MUG_INPUT].value / 5,0,1),0,1,0,3)); + int mode = (int)params[MODE_PARAM].value; + lFilter.setParams(cfreq,q,engineGetSampleRate(),g/3,mode); + rFilter.setParams(cfreq,q,engineGetSampleRate(),g/3,mode); float inL = inputs[IN_L].value/5; //normalise to -1/+1 we consider VCV Rack standard is #+5/-5V on VCO1 float inR = inputs[IN_R].value/5; - //filtering + makeup gain - float g = clampf(params[MUG_PARAM].value + inputs[MUG_INPUT].value,1,10); - inL = lFilter.calcOutput(inL)*5*g; - inR = rFilter.calcOutput(inR)*5*g; + inL = lFilter.calcOutput(inL)*5*(mode == 0 ? g : 1); + inR = rFilter.calcOutput(inR)*5*(mode == 0 ? g : 1); outputs[OUT_L].value = inL; outputs[OUT_R].value = inR; } @@ -134,8 +144,9 @@ LIMBOWidget::LIMBOWidget() { addParam(createParam(Vec(33, 61), module, LIMBO::CUTOFF_PARAM, 0, 1, 1)); addParam(createParam(Vec(12, 143), module, LIMBO::Q_PARAM, 0, 1, 0)); - addParam(createParam(Vec(71, 143), module, LIMBO::MUG_PARAM, 1, 10, 1)); + addParam(createParam(Vec(71, 143), module, LIMBO::MUG_PARAM, 0, 1, 0)); addParam(createParam(Vec(12, 208), module, LIMBO::CMOD_PARAM, -1, 1, 0)); + addParam(createParam(Vec(83, 217), module, LIMBO::MODE_PARAM, 0.0, 1.0, 0.0)); addInput(createInput(Vec(12, 280), module, LIMBO::CUTOFF_INPUT)); addInput(createInput(Vec(47, 280), module, LIMBO::Q_INPUT)); diff --git a/src/PERCO.cpp b/src/PERCO.cpp new file mode 100644 index 0000000..a23aace --- /dev/null +++ b/src/PERCO.cpp @@ -0,0 +1,128 @@ +// Based on Will Pirkle's courses & Vadim Zavalishin's book + +#include "Bidoo.hpp" +#include "BidooComponents.hpp" +#include "dsp/decimator.hpp" + +using namespace std; + +#define pi 3.14159265359 + + +struct MultiFilter +{ + float q; + float freq; + float smpRate; + float hp = 0,bp = 0,lp = 0,mem1 = 0,mem2 = 0; + + void setParams(float freq, float q, float smpRate) { + this->freq = freq; + this->q=q; + this->smpRate=smpRate; + } + + void calcOutput(float sample) + { + float g = tan(pi*freq/smpRate); + float R = 1.0/(2.0*q); + hp = (sample - (2.0*R + g)*mem1 - mem2)/(1.0 + 2.0*R*g + g*g); + bp = g*hp + mem1; + lp = g*bp + mem2; + mem1 = g*hp + bp; + mem2 = g*bp + lp; + } + +}; + +struct PERCO : Module { + enum ParamIds { + CUTOFF_PARAM, + Q_PARAM, + CMOD_PARAM, + NUM_PARAMS + }; + enum InputIds { + IN, + CUTOFF_INPUT, + Q_INPUT, + NUM_INPUTS + }; + enum OutputIds { + OUT_LP, + OUT_BP, + OUT_HP, + NUM_OUTPUTS + }; + enum LightIds { + LEARN_LIGHT, + NUM_LIGHTS + }; + MultiFilter filter; + + PERCO() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + } + + void step() override; + +}; + +void PERCO::step() { + float cfreq = pow(2,rescalef(clampf(params[CUTOFF_PARAM].value + params[CMOD_PARAM].value * inputs[CUTOFF_INPUT].value / 5,0,1),0,1,4.5,13)); + float q = 10 * clampf(params[Q_PARAM].value + inputs[Q_INPUT].value / 5.0, 0.1, 1.0); + filter.setParams(cfreq,q,engineGetSampleRate()); + float in = inputs[IN].value/5; //normalise to -1/+1 we consider VCV Rack standard is #+5/-5V on VCO1 + //filtering + filter.calcOutput(in); + outputs[OUT_LP].value = filter.lp * 5; + outputs[OUT_HP].value = filter.hp * 5; + outputs[OUT_BP].value = filter.bp * 5; +} + +struct PERCODisplay : TransparentWidget { + PERCO *module; + std::shared_ptr font; + PERCODisplay() { + font = Font::load(assetPlugin(plugin, "res/DejaVuSansMono.ttf")); + } + + void draw(NVGcontext *vg) override { + + } +}; + +PERCOWidget::PERCOWidget() { + PERCO *module = new PERCO(); + setModule(module); + box.size = Vec(15*8, 380); + + { + SVGPanel *panel = new SVGPanel(); + panel->box.size = box.size; + panel->setBackground(SVG::load(assetPlugin(plugin, "res/PERCO.svg"))); + addChild(panel); + } + + PERCODisplay *display = new PERCODisplay(); + display->module = module; + display->box.pos = Vec(5, 40); + display->box.size = Vec(110, 70); + addChild(display); + + addParam(createParam(Vec(33, 61), module, PERCO::CUTOFF_PARAM, 0, 1, 1)); + addParam(createParam(Vec(12, 143), module, PERCO::Q_PARAM, 0.1, 1, 0.1)); + addParam(createParam(Vec(71, 143), module, PERCO::CMOD_PARAM, -1, 1, 0)); + + addInput(createInput(Vec(10, 276), module, PERCO::IN)); + addInput(createInput(Vec(48, 276), module, PERCO::CUTOFF_INPUT)); + addInput(createInput(Vec(85, 276), module, PERCO::Q_INPUT)); + + addOutput(createOutput(Vec(10, 320), module, PERCO::OUT_LP)); + addOutput(createOutput(Vec(48, 320), module, PERCO::OUT_BP)); + addOutput(createOutput(Vec(85, 320), module, PERCO::OUT_HP)); + + addChild(createScrew(Vec(15, 0))); + addChild(createScrew(Vec(box.size.x-30, 0))); + addChild(createScrew(Vec(15, 365))); + addChild(createScrew(Vec(box.size.x-30, 365))); +} diff --git a/src/ZINC.cpp b/src/ZINC.cpp new file mode 100644 index 0000000..13b9499 --- /dev/null +++ b/src/ZINC.cpp @@ -0,0 +1,147 @@ +#include "Bidoo.hpp" +#include "BidooComponents.hpp" +#include "dsp/decimator.hpp" +#include "dep/filters/biquad.h" + +using namespace std; + +#define BANDS 16 + +struct ZINC : Module { + enum ParamIds { + BG_PARAM, + ATTACK_PARAM = BG_PARAM + BANDS, + DECAY_PARAM, + Q_PARAM, + GMOD_PARAM, + GCARR_PARAM, + G_PARAM, + SHAPE_PARAM, + NUM_PARAMS + }; + enum InputIds { + IN_MOD, + IN_CARR, + NUM_INPUTS + }; + enum OutputIds { + OUT, + NUM_OUTPUTS + }; + enum LightIds { + LEARN_LIGHT, + NUM_LIGHTS + }; + Biquad* iFilter[2*BANDS]; + Biquad* cFilter[2*BANDS]; + float mem[BANDS] = {0}; + float freq[BANDS] = {125,185,270,350,430,530,630,780,950,1150,1380,1680,2070,2780,3800,6400}; + float peaks[BANDS] = {0}; + + ZINC() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { + for(int i=0; i<2*BANDS; i++) { + iFilter[i] = new Biquad(bq_type_bandpass, freq[i%BANDS] / engineGetSampleRate(), 5, 6); + cFilter[i] = new Biquad(bq_type_bandpass, freq[i%BANDS] / engineGetSampleRate(), 5, 6); + } + } + + void step() override; + +}; + +void ZINC::step() { + float inM = inputs[IN_MOD].value/5; + float inC = inputs[IN_CARR].value/5; + const float slewMin = 0.001; + const float slewMax = 500.0; + const float shapeScale = 1/10.0; + float attack = params[ATTACK_PARAM].value; + float decay = params[DECAY_PARAM].value; + float slewAttack = slewMax * powf(slewMin / slewMax, attack); + float slewDecay = slewMax * powf(slewMin / slewMax, decay); + float out = 0.0; + + for(int i=0; iprocess(iFilter[i]->process(inM*params[GMOD_PARAM].value))); + if (peak>coeff) { + coeff += slewAttack * shapeScale * (peak - coeff) / engineGetSampleRate(); + if (coeff > peak) + coeff = peak; + } + else if (peak < coeff) { + coeff -= slewDecay * shapeScale * (coeff - peak) / engineGetSampleRate(); + if (coeff < peak) + coeff = peak; + } + peaks[i]=peak; + mem[i]=coeff; + out += cFilter[i+BANDS]->process(cFilter[i]->process(inC*params[GCARR_PARAM].value)) * coeff * params[BG_PARAM+i].value; + } + outputs[OUT].value = out * 5 * params[G_PARAM].value; +} + +struct ZINCDisplay : TransparentWidget { + ZINC *module; + std::shared_ptr font; + + ZINCDisplay() { + font = Font::load(assetPlugin(plugin, "res/DejaVuSansMono.ttf")); + } + + void draw(NVGcontext *vg) override { + nvgFontSize(vg, 10); + nvgFontFaceId(vg, font->handle); + nvgStrokeWidth(vg, 2); + nvgTextLetterSpacing(vg, -2); + nvgTextAlign(vg, NVG_ALIGN_CENTER); + static const int portX0[4] = {20, 63, 106, 149}; + for (int i=0; ifreq[i]); + nvgFillColor(vg,nvgRGBA(rescalef(clampf(module->peaks[i],0,1),0,1,0,255), 0, 0, 255)); + nvgText(vg, portX0[i%(BANDS/4)]+1, 35+43*(int)(i/4), fVal, NULL); + } + } +}; + +ZINCWidget::ZINCWidget() { + ZINC *module = new ZINC(); + setModule(module); + box.size = Vec(15*13, 380); + + { + SVGPanel *panel = new SVGPanel(); + panel->box.size = box.size; + panel->setBackground(SVG::load(assetPlugin(plugin, "res/ZINC.svg"))); + addChild(panel); + } + + ZINCDisplay *display = new ZINCDisplay(); + display->module = module; + display->box.pos = Vec(12, 12); + display->box.size = Vec(110, 70); + addChild(display); + + static const float portX0[4] = {20, 63, 106, 149}; + + for (int i = 0; i < BANDS; i++) { + addParam( createParam(Vec(portX0[i%(BANDS/4)]-1, 50+43*(int)(i/4)), module, ZINC::BG_PARAM + i, 0, 2, 1)); + } + addParam(createParam(Vec(portX0[0]+5, 230), module, ZINC::ATTACK_PARAM, 0.0, 0.25, 0.0)); + addParam(createParam(Vec(portX0[1]+5, 230), module, ZINC::DECAY_PARAM, 0.0, 0.25, 0.0)); + addParam(createParam(Vec(portX0[0]-1, 268), module, ZINC::GMOD_PARAM, 1, 10, 1)); + addParam(createParam(Vec(portX0[1]-1, 268), module, ZINC::GCARR_PARAM, 1, 10, 1)); + addParam(createParam(Vec(portX0[2]-1, 268), module, ZINC::G_PARAM, 1, 10, 1)); + + + addInput(createInput(Vec(10, 320), module, ZINC::IN_MOD)); + addInput(createInput(Vec(48, 320), module, ZINC::IN_CARR)); + + addOutput(createOutput(Vec(85, 320), module, ZINC::OUT)); + + addChild(createScrew(Vec(15, 0))); + addChild(createScrew(Vec(box.size.x-30, 0))); + addChild(createScrew(Vec(15, 365))); + addChild(createScrew(Vec(box.size.x-30, 365))); +} diff --git a/src/dep/filters/biquad.cpp b/src/dep/filters/biquad.cpp new file mode 100644 index 0000000..2e54be9 --- /dev/null +++ b/src/dep/filters/biquad.cpp @@ -0,0 +1,165 @@ +// +// Biquad.cpp +// +// Created by Nigel Redmon on 11/24/12 +// EarLevel Engineering: earlevel.com +// Copyright 2012 Nigel Redmon +// +// For a complete explanation of the Biquad code: +// http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/ +// +// License: +// +// This source code is provided as is, without warranty. +// You may copy and distribute verbatim copies of this document. +// You may modify and use this source code to create binary code +// for your own purposes, free or commercial. +// + +#include +#include "Biquad.h" + +Biquad::Biquad() { + type = bq_type_lowpass; + a0 = 1.0; + a1 = a2 = b1 = b2 = 0.0; + Fc = 0.50; + Q = 0.707; + peakGain = 0.0; + z1 = z2 = 0.0; +} + +Biquad::Biquad(int type, double Fc, double Q, double peakGainDB) { + setBiquad(type, Fc, Q, peakGainDB); + z1 = z2 = 0.0; +} + +Biquad::~Biquad() { +} + +void Biquad::setType(int type) { + this->type = type; + calcBiquad(); +} + +void Biquad::setQ(double Q) { + this->Q = Q; + calcBiquad(); +} + +void Biquad::setFc(double Fc) { + this->Fc = Fc; + calcBiquad(); +} + +void Biquad::setPeakGain(double peakGainDB) { + this->peakGain = peakGainDB; + calcBiquad(); +} + +void Biquad::setBiquad(int type, double Fc, double Q, double peakGainDB) { + this->type = type; + this->Q = Q; + this->Fc = Fc; + setPeakGain(peakGainDB); +} + +void Biquad::calcBiquad(void) { + double norm; + double V = pow(10, fabs(peakGain) / 20.0); + double K = tan(M_PI * Fc); + switch (this->type) { + case bq_type_lowpass: + norm = 1 / (1 + K / Q + K * K); + a0 = K * K * norm; + a1 = 2 * a0; + a2 = a0; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - K / Q + K * K) * norm; + break; + + case bq_type_highpass: + norm = 1 / (1 + K / Q + K * K); + a0 = 1 * norm; + a1 = -2 * a0; + a2 = a0; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - K / Q + K * K) * norm; + break; + + case bq_type_bandpass: + norm = 1 / (1 + K / Q + K * K); + a0 = K / Q * norm; + a1 = 0; + a2 = -a0; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - K / Q + K * K) * norm; + break; + + case bq_type_notch: + norm = 1 / (1 + K / Q + K * K); + a0 = (1 + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = a0; + b1 = a1; + b2 = (1 - K / Q + K * K) * norm; + break; + + case bq_type_peak: + if (peakGain >= 0) { // boost + norm = 1 / (1 + 1/Q * K + K * K); + a0 = (1 + V/Q * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - V/Q * K + K * K) * norm; + b1 = a1; + b2 = (1 - 1/Q * K + K * K) * norm; + } + else { // cut + norm = 1 / (1 + V/Q * K + K * K); + a0 = (1 + 1/Q * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - 1/Q * K + K * K) * norm; + b1 = a1; + b2 = (1 - V/Q * K + K * K) * norm; + } + break; + case bq_type_lowshelf: + if (peakGain >= 0) { // boost + norm = 1 / (1 + sqrt(2) * K + K * K); + a0 = (1 + sqrt(2*V) * K + V * K * K) * norm; + a1 = 2 * (V * K * K - 1) * norm; + a2 = (1 - sqrt(2*V) * K + V * K * K) * norm; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - sqrt(2) * K + K * K) * norm; + } + else { // cut + norm = 1 / (1 + sqrt(2*V) * K + V * K * K); + a0 = (1 + sqrt(2) * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - sqrt(2) * K + K * K) * norm; + b1 = 2 * (V * K * K - 1) * norm; + b2 = (1 - sqrt(2*V) * K + V * K * K) * norm; + } + break; + case bq_type_highshelf: + if (peakGain >= 0) { // boost + norm = 1 / (1 + sqrt(2) * K + K * K); + a0 = (V + sqrt(2*V) * K + K * K) * norm; + a1 = 2 * (K * K - V) * norm; + a2 = (V - sqrt(2*V) * K + K * K) * norm; + b1 = 2 * (K * K - 1) * norm; + b2 = (1 - sqrt(2) * K + K * K) * norm; + } + else { // cut + norm = 1 / (V + sqrt(2*V) * K + K * K); + a0 = (1 + sqrt(2) * K + K * K) * norm; + a1 = 2 * (K * K - 1) * norm; + a2 = (1 - sqrt(2) * K + K * K) * norm; + b1 = 2 * (K * K - V) * norm; + b2 = (V - sqrt(2*V) * K + K * K) * norm; + } + break; + } + + return; +} diff --git a/src/dep/filters/biquad.h b/src/dep/filters/biquad.h new file mode 100644 index 0000000..6875e95 --- /dev/null +++ b/src/dep/filters/biquad.h @@ -0,0 +1,60 @@ +// +// Biquad.h +// +// Created by Nigel Redmon on 11/24/12 +// EarLevel Engineering: earlevel.com +// Copyright 2012 Nigel Redmon +// +// For a complete explanation of the Biquad code: +// http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/ +// +// License: +// +// This source code is provided as is, without warranty. +// You may copy and distribute verbatim copies of this document. +// You may modify and use this source code to create binary code +// for your own purposes, free or commercial. +// + +#ifndef Biquad_h +#define Biquad_h + +enum { + bq_type_lowpass = 0, + bq_type_highpass, + bq_type_bandpass, + bq_type_notch, + bq_type_peak, + bq_type_lowshelf, + bq_type_highshelf +}; + +class Biquad { +public: + Biquad(); + Biquad(int type, double Fc, double Q, double peakGainDB); + ~Biquad(); + void setType(int type); + void setQ(double Q); + void setFc(double Fc); + void setPeakGain(double peakGainDB); + void setBiquad(int type, double Fc, double Q, double peakGain); + float process(float in); + +protected: + void calcBiquad(void); + + int type; + double a0, a1, a2, b1, b2; + double Fc, Q, peakGain; + double z1, z2; +}; + +inline float Biquad::process(float in) { + double out = in * a0 + z1; + z1 = in * a1 + z2 - b1 * out; + z2 = in * a2 - b2 * out; + return out; +} + +#endif // Biquad_h