├── .gitignore ├── .gitmodules ├── BAngr.ttl ├── LICENSE ├── README.md ├── doc └── screenshot.png ├── inc ├── surface.png └── surface.svg ├── makefile ├── manifest.ttl └── src ├── Airwindows ├── LICENSE ├── XRegion.cpp └── XRegion.hpp ├── BAngr.cpp ├── BAngr.hpp ├── BAngrDial.hpp ├── BAngrGUI.cpp ├── BAngrGUI.hpp ├── BAngrRangeDial.hpp ├── BAngr_Dictionary.data ├── ButterworthBandPassFilter.hpp ├── ButterworthFilter.hpp ├── ButterworthHighPassFilter.hpp ├── ButterworthLowPassFilter.hpp ├── ControllerLimits.hpp ├── Definitions.hpp ├── Dot.hpp ├── Limit.hpp ├── Ports.hpp └── Urids.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | /BAngr.lv2/** 2 | /src/BWidgets/include/** 3 | /src/BWidgets/build/** 4 | .clangd 5 | .tags 6 | *.zip 7 | *.tar.xz 8 | *.tar.gz 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/BWidgets"] 2 | path = src/BWidgets 3 | url = https://github.com/sjaehn/BWidgets 4 | -------------------------------------------------------------------------------- /BAngr.ttl: -------------------------------------------------------------------------------- 1 | @prefix atom: . 2 | @prefix doap: . 3 | @prefix foaf: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix xsd: . 7 | @prefix lv2: . 8 | @prefix time: . 9 | @prefix urid: . 10 | @prefix param: . 11 | @prefix patch: . 12 | @prefix state: . 13 | @prefix ui: . 14 | 15 | 16 | 17 | a foaf:Person; 18 | foaf:name "Sven Jaehnichen"; 19 | # foaf:mbox ; 20 | foaf:homepage . 21 | 22 | 23 | a ui:X11UI; 24 | ui:binary ; 25 | lv2:extensionData ui:idleInterface ; 26 | lv2:requiredFeature ui:idleInterface ; 27 | ui:portNotification [ 28 | ui:plugin ; 29 | lv2:symbol "control_2" ; 30 | ui:notifyType atom:Blank 31 | ] . 32 | 33 | 34 | a lv2:Parameter ; 35 | rdfs:label "X-Cursor" ; 36 | rdfs:range atom:Float ; 37 | lv2:minimum 0.0 ; 38 | lv2:maximum 1.0 . 39 | 40 | 41 | a lv2:Parameter ; 42 | rdfs:label "Y-Cursor" ; 43 | rdfs:range atom:Float ; 44 | lv2:minimum 0.0 ; 45 | lv2:maximum 1.0 . 46 | 47 | 48 | a lv2:Plugin, lv2:DistortionPlugin, doap:Project ; 49 | doap:name "B.Angr" ; 50 | rdfs:comment "A multi-dimensional dynamicly distorted staggered multi-bandpass LV2 plugin, for extreme soundmangling. Based on Airwindows XRegion." ; 51 | doap:maintainer ; 52 | doap:license ; 53 | lv2:microVersion 3 ; 54 | lv2:minorVersion 6 ; 55 | lv2:extensionData state:interface ; 56 | lv2:optionalFeature lv2:hardRTCapable , state:loadDefaultState , state:threadSafeRestore ; 57 | lv2:binary ; 58 | lv2:requiredFeature urid:map ; 59 | ui:ui ; 60 | patch:writable , 61 | ; 62 | lv2:port [ 63 | a lv2:InputPort , atom:AtomPort ; 64 | atom:bufferType atom:Sequence ; 65 | atom:supports time:Position , patch:Message ; 66 | lv2:index 0 ; 67 | lv2:symbol "control_1" ; 68 | lv2:name "Control_1" ; 69 | ] , [ 70 | a lv2:OutputPort , atom:AtomPort ; 71 | atom:bufferType atom:Sequence ; 72 | lv2:designation lv2:control ; 73 | atom:supports patch:Message ; 74 | lv2:index 1 ; 75 | lv2:symbol "control_2" ; 76 | lv2:name "Control_2" ; 77 | ] , [ 78 | a lv2:AudioPort , lv2:InputPort ; 79 | lv2:index 2 ; 80 | lv2:symbol "audio_in_1" ; 81 | lv2:name "Audio Input 1" ; 82 | ] , [ 83 | a lv2:AudioPort , lv2:InputPort ; 84 | lv2:index 3 ; 85 | lv2:symbol "audio_in_2" ; 86 | lv2:name "Audio Input 2" ; 87 | ] , [ 88 | a lv2:AudioPort , lv2:OutputPort ; 89 | lv2:index 4 ; 90 | lv2:symbol "audio_out_1" ; 91 | lv2:name "Audio Output 1" ; 92 | ] , [ 93 | a lv2:AudioPort , lv2:OutputPort ; 94 | lv2:index 5 ; 95 | lv2:symbol "audio_out_2" ; 96 | lv2:name "Audio Output 2" ; 97 | ] , [ 98 | a lv2:InputPort , lv2:ControlPort ; 99 | lv2:index 6 ; 100 | lv2:symbol "bypass" ; 101 | lv2:name "Bypass" ; 102 | lv2:portProperty lv2:integer , lv2:toggled ; 103 | lv2:default 0 ; 104 | lv2:minimum 0 ; 105 | lv2:maximum 1 ; 106 | ] , [ 107 | a lv2:InputPort , lv2:ControlPort ; 108 | lv2:index 7 ; 109 | lv2:symbol "dry_wet" ; 110 | lv2:name "Dry / wet" ; 111 | lv2:default 1.0 ; 112 | lv2:minimum 0.0 ; 113 | lv2:maximum 1.0 ; 114 | ] , [ 115 | a lv2:InputPort , lv2:ControlPort ; 116 | lv2:index 8 ; 117 | lv2:symbol "speed" ; 118 | lv2:name "Speed" ; 119 | lv2:default 0.5 ; 120 | lv2:minimum 0.0 ; 121 | lv2:maximum 1.0 ; 122 | ] , [ 123 | a lv2:InputPort , lv2:ControlPort ; 124 | lv2:index 9 ; 125 | lv2:symbol "speed_range" ; 126 | lv2:name "Speed range" ; 127 | lv2:default 0.25 ; 128 | lv2:minimum 0.0 ; 129 | lv2:maximum 1.0 ; 130 | ] , [ 131 | a lv2:InputPort , lv2:ControlPort ; 132 | lv2:index 10 ; 133 | lv2:symbol "speed_flexibility_type" ; 134 | lv2:name "Speed flexibility type" ; 135 | lv2:portProperty lv2:integer, lv2:enumeration ; 136 | lv2:scalePoint [ rdfs:label "Random"; rdf:value 0 ] ; 137 | lv2:scalePoint [ rdfs:label "Level"; rdf:value 1 ] ; 138 | lv2:default 0 ; 139 | lv2:minimum 0 ; 140 | lv2:maximum 1 ; 141 | ] , [ 142 | a lv2:InputPort , lv2:ControlPort ; 143 | lv2:index 11 ; 144 | lv2:symbol "speed_flexibility_amount" ; 145 | lv2:name "Speed flexibility amount" ; 146 | lv2:default 0.5 ; 147 | lv2:minimum 0.0 ; 148 | lv2:maximum 1.0 ; 149 | ] , [ 150 | a lv2:InputPort , lv2:ControlPort ; 151 | lv2:index 12 ; 152 | lv2:symbol "spin" ; 153 | lv2:name "Spin" ; 154 | lv2:default 0.0 ; 155 | lv2:minimum -1.0 ; 156 | lv2:maximum 1.0 ; 157 | ] , [ 158 | a lv2:InputPort , lv2:ControlPort ; 159 | lv2:index 13 ; 160 | lv2:symbol "spin_range" ; 161 | lv2:name "Spin range" ; 162 | lv2:default 0.1 ; 163 | lv2:minimum 0.0 ; 164 | lv2:maximum 2.0 ; 165 | ] , [ 166 | a lv2:InputPort , lv2:ControlPort ; 167 | lv2:index 14 ; 168 | lv2:symbol "spin_flexibility_type" ; 169 | lv2:name "Spin flexibility type" ; 170 | lv2:portProperty lv2:integer, lv2:enumeration ; 171 | lv2:scalePoint [ rdfs:label "Random"; rdf:value 0 ] ; 172 | lv2:scalePoint [ rdfs:label "Level"; rdf:value 1 ] ; 173 | lv2:scalePoint [ rdfs:label "Lows"; rdf:value 2 ] ; 174 | lv2:scalePoint [ rdfs:label "Mids"; rdf:value 3 ] ; 175 | lv2:scalePoint [ rdfs:label "Highs"; rdf:value 4 ] ; 176 | lv2:default 0 ; 177 | lv2:minimum 0 ; 178 | lv2:maximum 4 ; 179 | ] , [ 180 | a lv2:InputPort , lv2:ControlPort ; 181 | lv2:index 15 ; 182 | lv2:symbol "spin_flexibility_amount" ; 183 | lv2:name "Spin flexibility amount" ; 184 | lv2:default 0.5 ; 185 | lv2:minimum 0.0 ; 186 | lv2:maximum 1.0 ; 187 | ] , [ 188 | a lv2:InputPort , lv2:ControlPort ; 189 | lv2:index 16 ; 190 | lv2:symbol "fx1_gain" ; 191 | lv2:name "FX1 Gain" ; 192 | lv2:default 0.5 ; 193 | lv2:minimum 0.0 ; 194 | lv2:maximum 1.0 ; 195 | ] , [ 196 | a lv2:InputPort , lv2:ControlPort ; 197 | lv2:index 17 ; 198 | lv2:symbol "fx1_first" ; 199 | lv2:name "FX1 First" ; 200 | lv2:default 0.2 ; 201 | lv2:minimum 0.0 ; 202 | lv2:maximum 1.0 ; 203 | ] , [ 204 | a lv2:InputPort , lv2:ControlPort ; 205 | lv2:index 18 ; 206 | lv2:symbol "fx1_last" ; 207 | lv2:name "FX1 Last" ; 208 | lv2:default 0.1 ; 209 | lv2:minimum 0.0 ; 210 | lv2:maximum 1.0 ; 211 | ] , [ 212 | a lv2:InputPort , lv2:ControlPort ; 213 | lv2:index 19 ; 214 | lv2:symbol "fx1_nuke" ; 215 | lv2:name "FX1 Nuke" ; 216 | lv2:default 1.0 ; 217 | lv2:minimum 0.0 ; 218 | lv2:maximum 1.0 ; 219 | ] , [ 220 | a lv2:InputPort , lv2:ControlPort ; 221 | lv2:index 20 ; 222 | lv2:symbol "fx1_mix" ; 223 | lv2:name "FX1 Dry/wet" ; 224 | lv2:default 1.0 ; 225 | lv2:minimum 0.0 ; 226 | lv2:maximum 1.0 ; 227 | ] , [ 228 | a lv2:InputPort , lv2:ControlPort ; 229 | lv2:index 21 ; 230 | lv2:symbol "fx1_pan" ; 231 | lv2:name "FX1 Pan" ; 232 | lv2:default 0.0 ; 233 | lv2:minimum -1.0 ; 234 | lv2:maximum 1.0 ; 235 | ] , [ 236 | a lv2:InputPort , lv2:ControlPort ; 237 | lv2:index 22 ; 238 | lv2:symbol "fx2_gain" ; 239 | lv2:name "FX2 Gain" ; 240 | lv2:default 0.5 ; 241 | lv2:minimum 0.0 ; 242 | lv2:maximum 1.0 ; 243 | ] , [ 244 | a lv2:InputPort , lv2:ControlPort ; 245 | lv2:index 23 ; 246 | lv2:symbol "fx2_first" ; 247 | lv2:name "FX2 First" ; 248 | lv2:default 0.7 ; 249 | lv2:minimum 0.0 ; 250 | lv2:maximum 1.0 ; 251 | ] , [ 252 | a lv2:InputPort , lv2:ControlPort ; 253 | lv2:index 24 ; 254 | lv2:symbol "fx2_last" ; 255 | lv2:name "FX2 Last" ; 256 | lv2:default 0.8 ; 257 | lv2:minimum 0.0 ; 258 | lv2:maximum 1.0 ; 259 | ] , [ 260 | a lv2:InputPort , lv2:ControlPort ; 261 | lv2:index 25 ; 262 | lv2:symbol "fx2_nuke" ; 263 | lv2:name "FX2 Nuke" ; 264 | lv2:default 1.0 ; 265 | lv2:minimum 0.0 ; 266 | lv2:maximum 1.0 ; 267 | ] , [ 268 | a lv2:InputPort , lv2:ControlPort ; 269 | lv2:index 26 ; 270 | lv2:symbol "fx2_mix" ; 271 | lv2:name "FX2 Dry/wet" ; 272 | lv2:default 1.0 ; 273 | lv2:minimum 0.0 ; 274 | lv2:maximum 1.0 ; 275 | ] , [ 276 | a lv2:InputPort , lv2:ControlPort ; 277 | lv2:index 27 ; 278 | lv2:symbol "fx2_pan" ; 279 | lv2:name "FX2 Pan" ; 280 | lv2:default 0.0 ; 281 | lv2:minimum -1.0 ; 282 | lv2:maximum 1.0 ; 283 | ] , [ 284 | a lv2:InputPort , lv2:ControlPort ; 285 | lv2:index 28 ; 286 | lv2:symbol "fx3_gain" ; 287 | lv2:name "FX3 Gain" ; 288 | lv2:default 0.75 ; 289 | lv2:minimum 0.0 ; 290 | lv2:maximum 1.0 ; 291 | ] , [ 292 | a lv2:InputPort , lv2:ControlPort ; 293 | lv2:index 29 ; 294 | lv2:symbol "fx3_first" ; 295 | lv2:name "FX3 First" ; 296 | lv2:default 0.5 ; 297 | lv2:minimum 0.0 ; 298 | lv2:maximum 1.0 ; 299 | ] , [ 300 | a lv2:InputPort , lv2:ControlPort ; 301 | lv2:index 30 ; 302 | lv2:symbol "fx3_last" ; 303 | lv2:name "FX3 Last" ; 304 | lv2:default 0.8 ; 305 | lv2:minimum 0.0 ; 306 | lv2:maximum 1.0 ; 307 | ] , [ 308 | a lv2:InputPort , lv2:ControlPort ; 309 | lv2:index 31 ; 310 | lv2:symbol "fx3_nuke" ; 311 | lv2:name "FX3 Nuke" ; 312 | lv2:default 0.5 ; 313 | lv2:minimum 0.0 ; 314 | lv2:maximum 1.0 ; 315 | ] , [ 316 | a lv2:InputPort , lv2:ControlPort ; 317 | lv2:index 32 ; 318 | lv2:symbol "fx3_mix" ; 319 | lv2:name "FX3 Dry/wet" ; 320 | lv2:default 1.0 ; 321 | lv2:minimum 0.0 ; 322 | lv2:maximum 1.0 ; 323 | ] , [ 324 | a lv2:InputPort , lv2:ControlPort ; 325 | lv2:index 33 ; 326 | lv2:symbol "fx3_pan" ; 327 | lv2:name "FX3 Pan" ; 328 | lv2:default 0.5 ; 329 | lv2:minimum -1.0 ; 330 | lv2:maximum 1.0 ; 331 | ] , [ 332 | a lv2:InputPort , lv2:ControlPort ; 333 | lv2:index 34 ; 334 | lv2:symbol "fx4_gain" ; 335 | lv2:name "FX4 Gain" ; 336 | lv2:default 0.5 ; 337 | lv2:minimum 0.0 ; 338 | lv2:maximum 1.0 ; 339 | ] , [ 340 | a lv2:InputPort , lv2:ControlPort ; 341 | lv2:index 35 ; 342 | lv2:symbol "fx4_first" ; 343 | lv2:name "FX4 First" ; 344 | lv2:default 0.2 ; 345 | lv2:minimum 0.0 ; 346 | lv2:maximum 1.0 ; 347 | ] , [ 348 | a lv2:InputPort , lv2:ControlPort ; 349 | lv2:index 36 ; 350 | lv2:symbol "fx4_last" ; 351 | lv2:name "FX4 Last" ; 352 | lv2:default 0.5 ; 353 | lv2:minimum 0.0 ; 354 | lv2:maximum 1.0 ; 355 | ] , [ 356 | a lv2:InputPort , lv2:ControlPort ; 357 | lv2:index 37 ; 358 | lv2:symbol "fx4_nuke" ; 359 | lv2:name "FX4 Nuke" ; 360 | lv2:default 0.2 ; 361 | lv2:minimum 0.0 ; 362 | lv2:maximum 1.0 ; 363 | ] , [ 364 | a lv2:InputPort , lv2:ControlPort ; 365 | lv2:index 38 ; 366 | lv2:symbol "fx4_mix" ; 367 | lv2:name "FX4 Dry/wet" ; 368 | lv2:default 1.0 ; 369 | lv2:minimum 0.0 ; 370 | lv2:maximum 1.0 ; 371 | ] , [ 372 | a lv2:InputPort , lv2:ControlPort ; 373 | lv2:index 39 ; 374 | lv2:symbol "fx4_pan" ; 375 | lv2:name "FX4 Pan" ; 376 | lv2:default -0.5 ; 377 | lv2:minimum -1.0 ; 378 | lv2:maximum 1.0 ; 379 | ] ; 380 | 381 | state:state [ 382 | "0.5"^^xsd:float ; 383 | "0.5"^^xsd:float ; 384 | ] . 385 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # B.Angr 2 | A multi-dimensional dynamicly distorted staggered multi-bandpass LV2 plugin, for extreme soundmangling. 3 | Based on Airwindows XRegion. 4 | 5 | Key features: 6 | * Multi-bandpass / distortion 7 | * Cross-fading between four instances 8 | * Automatic or user-controlled flow 9 | * Optionally follows the beat 10 | 11 | ![screenshot](https://raw.githubusercontent.com/sjaehn/BAngr/master/doc/screenshot.png "Screenshot from B.Angr") 12 | 13 | 14 | ## Installation 15 | 16 | a) Install the bangr package for your system 17 | * [Arch](https://aur.archlinux.org/packages/bangr.lv2-git) by SpotlightKid 18 | * [FreeBSD](https://www.freshports.org/audio/bangr-lv2) by yurivict 19 | 20 | Note: This will NOT necessarily install the latest version of B.Angr. The version provided depends on the packagers. 21 | 22 | b) Use the latest provided binaries 23 | 24 | Unpack the provided bangr-\*.zip or bangr-\*.tar.xz from the latest release and 25 | copy the BAngr.lv2 folder to your lv2 directory (depending on your system settings, 26 | ~/.lv2/, /usr/lib/lv2/, /usr/local/lib/lv2/, or ...). 27 | 28 | c) Build your own binaries in the following three steps. 29 | 30 | Step 1: [Download the latest published version](https://github.com/sjaehn/BAngr/releases) of B.Angr. 31 | Or clone or [download the master](https://github.com/sjaehn/BAngr/archive/master.zip) of this repository. 32 | 33 | Step 2: Install pkg-config and the development packages for x11, cairo, and lv2 if not done yet. If you 34 | don't have already got the build tools (compilers, make, libraries) then install them too. 35 | 36 | On Debian-based systems you may run: 37 | ``` 38 | sudo apt-get install build-essential 39 | sudo apt-get install pkg-config libx11-dev libcairo2-dev lv2-dev 40 | ``` 41 | 42 | On Arch-based systems you may run: 43 | ``` 44 | sudo pacman -S base-devel 45 | sudo pacman -S pkg-config libx11 cairo lv2 46 | ``` 47 | 48 | Step 3: Building and installing into the default lv2 directory (/usr/local/lib/lv2/) is easy using `make` and 49 | `make install`. Simply call: 50 | ``` 51 | make 52 | sudo make install 53 | ``` 54 | 55 | **Optional:** Standard `make` and `make install` parameters are supported. You may build a debugging version using 56 | `make CPPFLAGS+=-g`. For installation into an alternative directory (e.g., /usr/lib/lv2/), change the 57 | variable `PREFIX` while installing: `sudo make install PREFIX=/usr`. If you want to freely choose the 58 | install target directory, change the variable `LV2DIR` (e.g., `make install LV2DIR=~/.lv2`) or even define 59 | `DESTDIR`. 60 | 61 | **Optional:** Further supported parameters are `LANGUAGE` (two letters code) to change the GUI language and 62 | `SKIN` to change the skin (see customize). 63 | 64 | 65 | ## Running 66 | 67 | After the installation Ardour, Carla, and any other LV2 host should automatically detect B.Angr. 68 | 69 | If jalv is installed, you can also call it 70 | 71 | ``` 72 | jalv.gtk https://www.jahnichen.de/plugins/lv2/BAngr 73 | ``` 74 | 75 | to run it stand-alone and connect it to the JACK system. 76 | 77 | 78 | ## Usage 79 | 80 | The user interface of B.Angr contains four parameter instances of the XRegion parameters gain, 81 | first, last, nuke, and mix. Plus an additional pan dial for each instance. Sliding between the 82 | instances is controlled by the white point in the central controller fiels. The movement of 83 | this point can be controlled by the parameters speed and spin. But you can also slide between 84 | the four instances by dragging the white point of the central controller field to 85 | the respective instance. 86 | 87 | The flexible amount of speed and spin can be increased or decreased by dragging or scrolling 88 | the white arrows on the outside the repective dial. The behaviour of the flexible amount can 89 | be controlled by the audio input signal. Set the type (level, lows, mids, highs) and the amount 90 | of control (from 0 = random to 1 = full control). And let the white point move to the music. 91 | Or leave everything in the random state. 92 | 93 | More about XRegion at http://www.airwindows.com/xregion/ . 94 | 95 | 96 | ## Internationalization 97 | B.Angr now uses the dictionaries of the new B.Widgets toolkit and all labels 98 | are now automatically shown in your system language (if translation is 99 | provided). The dictionary for this plugin is stored in 100 | src/BAngr_Dictionary.data. If you want to add a translation to your language, 101 | simply edit this file in your text editor und use the (POSIX) language code 102 | (format: language_TERRITORY) of your language. 103 | 104 | E. g., if you want to add a french translation of "Help", simply change 105 | ``` 106 | { 107 | "Help", 108 | { 109 | {"de_DE", "Hilfe"}, 110 | {"it_IT", "Aiuto"} 111 | } 112 | }, 113 | ``` 114 | to 115 | ``` 116 | { 117 | "Help", 118 | { 119 | {"de_DE", "Hilfe"}, 120 | {"fr_FR", "Aide"}, 121 | {"it_IT", "Aiuto"} 122 | } 123 | }, 124 | ``` 125 | 126 | Once you changed the dictionary, you have to re-build the plugin. And please 127 | share your translations with other users by either submitting a git pull 128 | request or notifying me (issue report, e-mail, ...). 129 | 130 | 131 | ## What's new 132 | 133 | * Use new B.Widgets toolkit 134 | * Internationalization: EN, DE 135 | 136 | 137 | ## Acknowledgments 138 | 139 | * Thanks to Chris Johnson for the Airwindows plugin XRegion: http://www.airwindows.com/xregion/ . 140 | Support his work via https://www.patreon.com/airwindows . 141 | 142 | 143 | ## Links 144 | 145 | * Preview video: https://www.youtube.com/watch?v=-kWy_1UYazo 146 | -------------------------------------------------------------------------------- /doc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjaehn/BAngr/d477f6db15301a17fd345085138505d5a6507409/doc/screenshot.png -------------------------------------------------------------------------------- /inc/surface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjaehn/BAngr/d477f6db15301a17fd345085138505d5a6507409/inc/surface.png -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | 3 | # Bundle 4 | PREFIX ?= /usr/local 5 | LV2DIR ?= $(PREFIX)/lib/lv2 6 | BUNDLE = BAngr.lv2 7 | DSP = BAngr 8 | DSP_SRC = ./src/BAngr.cpp 9 | GUI = BAngrGUI 10 | GUI_SRC = ./src/BAngrGUI.cpp 11 | OBJ_EXT = .so 12 | DSP_OBJ = $(DSP)$(OBJ_EXT) 13 | GUI_OBJ = $(GUI)$(OBJ_EXT) 14 | B_OBJECTS = $(addprefix $(BUNDLE)/, $(DSP_OBJ) $(GUI_OBJ)) 15 | ROOTFILES = *.ttl LICENSE 16 | INCFILES = inc/*.png 17 | B_FILES = $(addprefix $(BUNDLE)/, $(ROOTFILES) $(INCFILES)) 18 | DSP_INCL = src/Airwindows/XRegion.cpp 19 | GUI_CXX_INCL = src/BWidgets/BUtilities/vsystem.cpp 20 | 21 | # pkg-config 22 | PKG_CONFIG ?= pkg-config 23 | GUI_LIBS += lv2 x11 cairo 24 | LV2_LIBS += lv2 25 | ifneq ($(shell $(PKG_CONFIG) --exists fontconfig || echo no), no) 26 | override GUI_LIBS += fontconfig 27 | override GUIPPFLAGS += -DPKG_HAVE_FONTCONFIG 28 | endif 29 | DSPCFLAGS += `$(PKG_CONFIG) --cflags --static $(LV2_LIBS)` 30 | GUICFLAGS += -I$(CURDIR)/src/BWidgets/include `$(PKG_CONFIG) --cflags --static $(GUI_LIBS)` 31 | DSPLIBS += -Wl,-Bstatic -lm `$(PKG_CONFIG) --libs --static $(LV2_LIBS)` -Wl,-Bdynamic 32 | GUILIBS += -Wl,-Bstatic -lbwidgetscore -lcairoplus -lpugl -lm -Wl,-Bdynamic `$(PKG_CONFIG) --libs $(GUI_LIBS)` 33 | 34 | # complile 35 | CC ?= gcc 36 | CXX ?= g++ 37 | INSTALL ?= install 38 | INSTALL_PROGRAM ?= $(INSTALL) 39 | INSTALL_DATA ?= $(INSTALL) -m644 40 | STRIP ?= strip 41 | OPTIMIZATIONS ?=-O3 -ffast-math 42 | override CPPFLAGS += -DPIC 43 | override GUIPPFLAGS += -DPUGL_HAVE_CAIRO 44 | override CFLAGS +=-Wall -fvisibility=hidden -fPIC $(OPTIMIZATIONS) 45 | override CXXFLAGS +=-Wall -std=c++17 -fvisibility=hidden -fPIC $(OPTIMIZATIONS) 46 | override STRIPFLAGS +=-s 47 | override LDFLAGS +=-Lsrc/BWidgets/build -Wl,-Bstatic -Wl,-Bdynamic -Wl,--as-needed -shared -pthread 48 | 49 | ifdef WWW_BROWSER_CMD 50 | override GUIPPFLAGS += -DWWW_BROWSER_CMD=\"$(WWW_BROWSER_CMD)\" 51 | endif 52 | 53 | # check lib versions 54 | ifeq ($(shell $(PKG_CONFIG) --exists 'lv2 >= 1.12.4' || echo no), no) 55 | $(error lv2 >= 1.12.4 not found. Please install lv2 >= 1.12.4 first.) 56 | endif 57 | ifeq ($(shell $(PKG_CONFIG) --exists 'x11 >= 1.6.0' || echo no), no) 58 | $(error x11 >= 1.6.0 not found. Please install x11 >= 1.6.0 first.) 59 | endif 60 | ifeq ($(shell $(PKG_CONFIG) --exists 'cairo >= 1.12.0' || echo no), no) 61 | $(error cairo >= 1.12.0 not found. Please install cairo >= 1.12.0 first.) 62 | endif 63 | 64 | $(BUNDLE): clean $(DSP_OBJ) $(GUI_OBJ) 65 | @cp $(ROOTFILES) $(BUNDLE) 66 | @mkdir -p $(BUNDLE)/inc 67 | @cp $(INCFILES) $(BUNDLE)/inc 68 | 69 | all: $(BUNDLE) 70 | 71 | $(DSP_OBJ): $(DSP_SRC) 72 | @echo -n Build $(BUNDLE) DSP... 73 | @mkdir -p $(BUNDLE) 74 | @$(CXX) $(CPPFLAGS) $(OPTIMIZATIONS) $(CXXFLAGS) $(LDFLAGS) $(DSPCFLAGS) $< $(DSP_INCL) $(DSPLIBS) -o $(BUNDLE)/$@ 75 | ifeq (,$(filter -g,$(CXXFLAGS))) 76 | @$(STRIP) $(STRIPFLAGS) $(BUNDLE)/$@ 77 | endif 78 | @echo \ done. 79 | 80 | $(GUI_OBJ): $(GUI_SRC) src/BWidgets/build 81 | @echo -n Build $(BUNDLE) GUI... 82 | @mkdir -p $(BUNDLE) 83 | @mkdir -p $(BUNDLE)/tmp 84 | @cd $(BUNDLE)/tmp; $(CXX) $(CPPFLAGS) $(GUIPPFLAGS) $(CXXFLAGS) $(GUICFLAGS) $(addprefix $(CURDIR)/, $< $(GUI_CXX_INCL)) -c 85 | @$(CXX) $(LDFLAGS) $(BUNDLE)/tmp/*.o $(GUILIBS) -o $(BUNDLE)/$@ 86 | ifeq (,$(filter -g,$(CXXFLAGS))) 87 | @$(STRIP) $(STRIPFLAGS) $(BUNDLE)/$@ 88 | endif 89 | @rm -rf $(BUNDLE)/tmp 90 | @echo \ done. 91 | 92 | src/BWidgets/build: 93 | @echo Build Toolkit... 94 | @cd src/BWidgets ; $(MAKE) -s cairoplus CFLAGS+=-fvisibility=hidden 95 | @cd src/BWidgets ; $(MAKE) -s pugl CPPFLAGS+="-DPIC -DPUGL_API=\"__attribute__((visibility(\\\"hidden\\\")))\"" CFLAGS+=-fvisibility=hidden 96 | @cd src/BWidgets ; $(MAKE) -s bwidgets CPPFLAGS+=-DBUTILITIES_DICTIONARY_DATAFILE=\"\\\"../../BAngr_Dictionary.data\\\"\" CXXFLAGS+=-fvisibility=hidden 97 | @echo ...done. 98 | 99 | install: 100 | @echo -n Install $(BUNDLE) to $(DESTDIR)$(LV2DIR)... 101 | @$(INSTALL) -d $(DESTDIR)$(LV2DIR)/$(BUNDLE) 102 | @$(INSTALL) -d $(DESTDIR)$(LV2DIR)/$(BUNDLE)/inc 103 | @$(INSTALL_PROGRAM) -m755 $(B_OBJECTS) $(DESTDIR)$(LV2DIR)/$(BUNDLE) 104 | @$(INSTALL_DATA) $(addprefix $(BUNDLE)/, $(ROOTFILES)) $(DESTDIR)$(LV2DIR)/$(BUNDLE) 105 | @$(INSTALL_DATA) $(addprefix $(BUNDLE)/, $(INCFILES)) $(DESTDIR)$(LV2DIR)/$(BUNDLE)/inc 106 | @echo \ done. 107 | 108 | uninstall: 109 | @echo -n Uninstall $(BUNDLE)... 110 | @rm -f $(addprefix $(DESTDIR)$(LV2DIR)/$(BUNDLE)/, $(ROOTFILES) $(INCFILES)) 111 | -@rmdir $(DESTDIR)$(LV2DIR)/$(BUNDLE)/inc 112 | @rm -f $(DESTDIR)$(LV2DIR)/$(BUNDLE)/$(GUI_OBJ) 113 | @rm -f $(DESTDIR)$(LV2DIR)/$(BUNDLE)/$(DSP_OBJ) 114 | -@rmdir $(DESTDIR)$(LV2DIR)/$(BUNDLE) 115 | @echo \ done. 116 | 117 | clean: 118 | @echo -n Remove $(BUNDLE)... 119 | @rm -rf $(BUNDLE) 120 | @cd src/BWidgets ; $(MAKE) -s clean 121 | @echo \ done. 122 | 123 | .PHONY: all install uninstall clean 124 | 125 | .NOTPARALLEL: 126 | -------------------------------------------------------------------------------- /manifest.ttl: -------------------------------------------------------------------------------- 1 | @prefix lv2: . 2 | @prefix rdfs: . 3 | @prefix ui: . 4 | 5 | 6 | a lv2:Plugin ; 7 | lv2:binary ; 8 | rdfs:seeAlso . 9 | 10 | 11 | a ui:X11UI; 12 | ui:binary ; 13 | rdfs:seeAlso . -------------------------------------------------------------------------------- /src/Airwindows/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Chris Johnson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/Airwindows/XRegion.cpp: -------------------------------------------------------------------------------- 1 | /* ======================================== 2 | * XRegion - XRegion.h 3 | * Copyright (c) 2016 airwindows, All rights reserved 4 | * ======================================== */ 5 | 6 | /* MIT License 7 | 8 | Copyright (c) 2018 Chris Johnson 9 | Copyright (C) 2021 Sven Jähnichen 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | */ 29 | 30 | #include "XRegion.hpp" 31 | #include 32 | 33 | XRegion::XRegion (const double rate) : 34 | rate (rate), 35 | params {0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f} 36 | { 37 | for (int x = 0; x < 15; x++) {biquad[x] = 0.0f; biquadA[x] = 0.0f; biquadB[x] = 0.0f; biquadC[x] = 0.0f; biquadD[x] = 0.0f;} 38 | fpdL = 1.0; while (fpdL < 16386) fpdL = rand()*UINT32_MAX; 39 | fpdR = 1.0; while (fpdR < 16386) fpdR = rand()*UINT32_MAX; 40 | } 41 | 42 | XRegion::~XRegion() {} 43 | 44 | void XRegion::process (float* input1, float* input2, float* output1, float* output2, int32_t sampleFrames) 45 | { 46 | float gain = powf (params[0] + 0.5f, 4); 47 | 48 | float high = params[1]; 49 | float low = params[2]; 50 | float mid = (high + low) * 0.5f; 51 | float spread = 1.001f - fabsf (high - low); 52 | float nuke = params[3]; 53 | 54 | biquad[0] = high * high * high *20000.0f / rate; 55 | if (biquad[0] < 0.00009f) biquad[0] = 0.00009f; 56 | float compensation = sqrtf (biquad[0]) * 6.4f * spread; 57 | float clipFactor = 0.75f + (biquad[0] * nuke * 37.0f); 58 | 59 | const float hm = 0.5f * (high + mid); 60 | biquadA[0] = hm * hm * hm * 20000.0f / rate; 61 | if (biquadA[0] < 0.00009f) biquadA[0] = 0.00009f; 62 | float compensationA = sqrtf (biquadA[0]) * 6.4f * spread; 63 | float clipFactorA = 0.75f + (biquadA[0] * nuke * 37.0f); 64 | 65 | biquadB[0] = mid * mid * mid *20000.0f / rate; 66 | if (biquadB[0] < 0.00009f) biquadB[0] = 0.00009f; 67 | float compensationB = sqrtf (biquadB[0]) * 6.4f * spread; 68 | float clipFactorB = 0.75f + (biquadB[0] * nuke * 37.0f); 69 | 70 | const float ml = 0.5f * (mid + low); 71 | biquadC[0] = ml * ml * ml * 20000.0f / rate; 72 | if (biquadC[0] < 0.00009f) biquadC[0] = 0.00009f; 73 | float compensationC = sqrtf (biquadC[0]) * 6.4f * spread; 74 | float clipFactorC = 0.75f + (biquadC[0] * nuke * 37.0f); 75 | 76 | biquadD[0] = low * low * low * 20000.0f / rate; 77 | if (biquadD[0] < 0.00009f) biquadD[0] = 0.00009f; 78 | float compensationD = sqrtf (biquadD[0]) * 6.4f * spread; 79 | float clipFactorD = 0.75f + (biquadD[0] * nuke * 37.0f); 80 | 81 | float K = tanf (M_PI * biquad[0]); 82 | float norm = 1.0f / (1.0f + K / 0.7071f + K * K); 83 | biquad[2] = K / 0.7071f * norm; 84 | biquad[4] = -biquad[2]; 85 | biquad[5] = 2.0f * (K * K - 1.0f) * norm; 86 | biquad[6] = (1.0f - K / 0.7071f + K * K) * norm; 87 | 88 | K = tanf (M_PI * biquadA[0]); 89 | norm = 1.0f / (1.0f + K / 0.7071f + K * K); 90 | biquadA[2] = K / 0.7071f * norm; 91 | biquadA[4] = -biquadA[2]; 92 | biquadA[5] = 2.0f * (K * K - 1.0f) * norm; 93 | biquadA[6] = (1.0f - K / 0.7071f + K * K) * norm; 94 | 95 | K = tanf (M_PI * biquadB[0]); 96 | norm = 1.0f / (1.0f + K / 0.7071f + K * K); 97 | biquadB[2] = K / 0.7071f * norm; 98 | biquadB[4] = -biquadB[2]; 99 | biquadB[5] = 2.0f * (K * K - 1.0f) * norm; 100 | biquadB[6] = (1.0f - K / 0.7071f + K * K) * norm; 101 | 102 | K = tanf (M_PI * biquadC[0]); 103 | norm = 1.0f / (1.0f + K / 0.7071f + K * K); 104 | biquadC[2] = K / 0.7071f * norm; 105 | biquadC[4] = -biquadC[2]; 106 | biquadC[5] = 2.0f * (K * K - 1.0f) * norm; 107 | biquadC[6] = (1.0f - K / 0.7071f + K * K) * norm; 108 | 109 | K = tanf (M_PI * biquadD[0]); 110 | norm = 1.0f / (1.0f + K / 0.7071f + K * K); 111 | biquadD[2] = K / 0.7071f * norm; 112 | biquadD[4] = -biquadD[2]; 113 | biquadD[5] = 2.0f * (K * K - 1.0f) * norm; 114 | biquadD[6] = (1.0f - K / 0.7071f + K * K) * norm; 115 | 116 | float aWet = 1.0f; 117 | float bWet = 1.0f; 118 | float cWet = 1.0f; 119 | float dWet = params[3] * 4.0f; 120 | float wet = params[4]; 121 | float pan = params[5]; 122 | 123 | //four-stage wet/dry control using progressive stages that bypass when not engaged 124 | if (dWet < 1.0f) {aWet = dWet; bWet = 0.0f; cWet = 0.0f; dWet = 0.0f;} 125 | else if (dWet < 2.0f) {bWet = dWet - 1.0f; cWet = 0.0f; dWet = 0.0f;} 126 | else if (dWet < 3.0f) {cWet = dWet - 2.0f; dWet = 0.0f;} 127 | else {dWet -= 3.0f;} 128 | //this is one way to make a little set of dry/wet stages that are successively added to the 129 | //output as the control is turned up. Each one independently goes from 0-1 and stays at 1 130 | //beyond that point: this is a way to progressively add a 'black box' sound processing 131 | //which lets you fall through to simpler processing at lower settings. 132 | float outSample = 0.0f; 133 | 134 | while (--sampleFrames >= 0) 135 | { 136 | float inputSampleL = *input1; 137 | float inputSampleR = *input2; 138 | if (fabsf(inputSampleL)<1.18e-37) inputSampleL = fpdL * 1.18e-37; 139 | if (fabsf(inputSampleR)<1.18e-37) inputSampleR = fpdR * 1.18e-37; 140 | float drySampleL = inputSampleL; 141 | float drySampleR = inputSampleR; 142 | 143 | if (gain != 1.0f) { 144 | inputSampleL *= gain; 145 | inputSampleR *= gain; 146 | } 147 | 148 | float nukeLevelL = inputSampleL; 149 | float nukeLevelR = inputSampleR; 150 | 151 | inputSampleL *= clipFactor; 152 | if (inputSampleL > 1.57079633f) inputSampleL = 1.57079633f; 153 | if (inputSampleL < -1.57079633f) inputSampleL = -1.57079633f; 154 | inputSampleL = sinf(inputSampleL); 155 | outSample = biquad[2]*inputSampleL+biquad[4]*biquad[8]-biquad[5]*biquad[9]-biquad[6]*biquad[10]; 156 | biquad[8] = biquad[7]; biquad[7] = inputSampleL; biquad[10] = biquad[9]; 157 | biquad[9] = outSample; //DF1 left 158 | inputSampleL = outSample / compensation; nukeLevelL = inputSampleL; 159 | 160 | inputSampleR *= clipFactor; 161 | if (inputSampleR > 1.57079633f) inputSampleR = 1.57079633f; 162 | if (inputSampleR < -1.57079633f) inputSampleR = -1.57079633f; 163 | inputSampleR = sinf(inputSampleR); 164 | outSample = biquad[2]*inputSampleR+biquad[4]*biquad[12]-biquad[5]*biquad[13]-biquad[6]*biquad[14]; 165 | biquad[12] = biquad[11]; biquad[11] = inputSampleR; biquad[14] = biquad[13]; 166 | biquad[13] = outSample; //DF1 right 167 | inputSampleR = outSample / compensation; nukeLevelR = inputSampleR; 168 | 169 | if (aWet > 0.0) { 170 | inputSampleL *= clipFactorA; 171 | if (inputSampleL > 1.57079633f) inputSampleL = 1.57079633f; 172 | if (inputSampleL < -1.57079633f) inputSampleL = -1.57079633f; 173 | inputSampleL = sinf(inputSampleL); 174 | outSample = biquadA[2]*inputSampleL+biquadA[4]*biquadA[8]-biquadA[5]*biquadA[9]-biquadA[6]*biquadA[10]; 175 | biquadA[8] = biquadA[7]; biquadA[7] = inputSampleL; biquadA[10] = biquadA[9]; 176 | biquadA[9] = outSample; //DF1 left 177 | inputSampleL = outSample / compensationA; inputSampleL = (inputSampleL * aWet) + (nukeLevelL * (1.0f-aWet)); 178 | nukeLevelL = inputSampleL; 179 | 180 | inputSampleR *= clipFactorA; 181 | if (inputSampleR > 1.57079633f) inputSampleR = 1.57079633f; 182 | if (inputSampleR < -1.57079633f) inputSampleR = -1.57079633f; 183 | inputSampleR = sinf(inputSampleR); 184 | outSample = biquadA[2]*inputSampleR+biquadA[4]*biquadA[12]-biquadA[5]*biquadA[13]-biquadA[6]*biquadA[14]; 185 | biquadA[12] = biquadA[11]; biquadA[11] = inputSampleR; biquadA[14] = biquadA[13]; 186 | biquadA[13] = outSample; //DF1 right 187 | inputSampleR = outSample / compensationA; inputSampleR = (inputSampleR * aWet) + (nukeLevelR * (1.0f-aWet)); 188 | nukeLevelR = inputSampleR; 189 | } 190 | if (bWet > 0.0) { 191 | inputSampleL *= clipFactorB; 192 | if (inputSampleL > 1.57079633f) inputSampleL = 1.57079633f; 193 | if (inputSampleL < -1.57079633f) inputSampleL = -1.57079633f; 194 | inputSampleL = sinf(inputSampleL); 195 | outSample = biquadB[2]*inputSampleL+biquadB[4]*biquadB[8]-biquadB[5]*biquadB[9]-biquadB[6]*biquadB[10]; 196 | biquadB[8] = biquadB[7]; biquadB[7] = inputSampleL; biquadB[10] = biquadB[9]; 197 | biquadB[9] = outSample; //DF1 left 198 | inputSampleL = outSample / compensationB; inputSampleL = (inputSampleL * bWet) + (nukeLevelL * (1.0f-bWet)); 199 | nukeLevelL = inputSampleL; 200 | 201 | inputSampleR *= clipFactorB; 202 | if (inputSampleR > 1.57079633f) inputSampleR = 1.57079633f; 203 | if (inputSampleR < -1.57079633f) inputSampleR = -1.57079633f; 204 | inputSampleR = sinf(inputSampleR); 205 | outSample = biquadB[2]*inputSampleR+biquadB[4]*biquadB[12]-biquadB[5]*biquadB[13]-biquadB[6]*biquadB[14]; 206 | biquadB[12] = biquadB[11]; biquadB[11] = inputSampleR; biquadB[14] = biquadB[13]; 207 | biquadB[13] = outSample; //DF1 right 208 | inputSampleR = outSample / compensationB; inputSampleR = (inputSampleR * bWet) + (nukeLevelR * (1.0f-bWet)); 209 | nukeLevelR = inputSampleR; 210 | } 211 | if (cWet > 0.0) { 212 | inputSampleL *= clipFactorC; 213 | if (inputSampleL > 1.57079633f) inputSampleL = 1.57079633f; 214 | if (inputSampleL < -1.57079633f) inputSampleL = -1.57079633f; 215 | inputSampleL = sinf(inputSampleL); 216 | outSample = biquadC[2]*inputSampleL+biquadC[4]*biquadC[8]-biquadC[5]*biquadC[9]-biquadC[6]*biquadC[10]; 217 | biquadC[8] = biquadC[7]; biquadC[7] = inputSampleL; biquadC[10] = biquadC[9]; 218 | biquadC[9] = outSample; //DF1 left 219 | inputSampleL = outSample / compensationC; inputSampleL = (inputSampleL * cWet) + (nukeLevelL * (1.0f-cWet)); 220 | nukeLevelL = inputSampleL; 221 | 222 | inputSampleR *= clipFactorC; 223 | if (inputSampleR > 1.57079633f) inputSampleR = 1.57079633f; 224 | if (inputSampleR < -1.57079633f) inputSampleR = -1.57079633f; 225 | inputSampleR = sinf(inputSampleR); 226 | outSample = biquadC[2]*inputSampleR+biquadC[4]*biquadC[12]-biquadC[5]*biquadC[13]-biquadC[6]*biquadC[14]; 227 | biquadC[12] = biquadC[11]; biquadC[11] = inputSampleR; biquadC[14] = biquadC[13]; 228 | biquadC[13] = outSample; //DF1 right 229 | inputSampleR = outSample / compensationC; inputSampleR = (inputSampleR * cWet) + (nukeLevelR * (1.0f-cWet)); 230 | nukeLevelR = inputSampleR; 231 | } 232 | if (dWet > 0.0) { 233 | inputSampleL *= clipFactorD; 234 | if (inputSampleL > 1.57079633f) inputSampleL = 1.57079633f; 235 | if (inputSampleL < -1.57079633f) inputSampleL = -1.57079633f; 236 | inputSampleL = sinf(inputSampleL); 237 | outSample = biquadD[2]*inputSampleL+biquadD[4]*biquadD[8]-biquadD[5]*biquadD[9]-biquadD[6]*biquadD[10]; 238 | biquadD[8] = biquadD[7]; biquadD[7] = inputSampleL; biquadD[10] = biquadD[9]; 239 | biquadD[9] = outSample; //DF1 left 240 | inputSampleL = outSample / compensationD; inputSampleL = (inputSampleL * dWet) + (nukeLevelL * (1.0f-dWet)); 241 | nukeLevelL = inputSampleL; 242 | 243 | inputSampleR *= clipFactorD; 244 | if (inputSampleR > 1.57079633f) inputSampleR = 1.57079633f; 245 | if (inputSampleR < -1.57079633f) inputSampleR = -1.57079633f; 246 | inputSampleR = sinf(inputSampleR); 247 | outSample = biquadD[2]*inputSampleR+biquadD[4]*biquadD[12]-biquadD[5]*biquadD[13]-biquadD[6]*biquadD[14]; 248 | biquadD[12] = biquadD[11]; biquadD[11] = inputSampleR; biquadD[14] = biquadD[13]; 249 | biquadD[13] = outSample; //DF1 right 250 | inputSampleR = outSample / compensationD; inputSampleR = (inputSampleR * dWet) + (nukeLevelR * (1.0f-dWet)); 251 | nukeLevelR = inputSampleR; 252 | } 253 | 254 | if (inputSampleL > 1.57079633f) inputSampleL = 1.57079633f; 255 | if (inputSampleL < -1.57079633f) inputSampleL = -1.57079633f; 256 | inputSampleL = sinf(inputSampleL); 257 | if (inputSampleR > 1.57079633f) inputSampleR = 1.57079633f; 258 | if (inputSampleR < -1.57079633f) inputSampleR = -1.57079633f; 259 | inputSampleR = sinf(inputSampleR); 260 | 261 | if (wet < 1.0f) { 262 | inputSampleL = (drySampleL * (1.0f-wet))+(inputSampleL * wet); 263 | inputSampleR = (drySampleR * (1.0f-wet))+(inputSampleR * wet); 264 | } 265 | 266 | *output1 = inputSampleL * (1.0f - (pan > 0.0f) * pan); 267 | *output2 = inputSampleR * (1.0f + (pan < 0.0f) * pan); 268 | 269 | input1++; 270 | input2++; 271 | output1++; 272 | output2++; 273 | } 274 | } 275 | 276 | void XRegion::setParameters (const float* values) 277 | { 278 | memcpy (params, values, 6 * sizeof (float)); 279 | } 280 | 281 | float* XRegion::getParameters () {return params;} 282 | -------------------------------------------------------------------------------- /src/Airwindows/XRegion.hpp: -------------------------------------------------------------------------------- 1 | /* ======================================== 2 | * XRegion - XRegion.h 3 | * Created 8/12/11 by SPIAdmin 4 | * Copyright (c) 2011 __MyCompanyName__, All rights reserved 5 | * ======================================== */ 6 | 7 | /* MIT License 8 | 9 | Copyright (c) 2018 Chris Johnson 10 | Copyright (C) 2021 Sven Jähnichen 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | 31 | #ifndef XREGION_HPP_ 32 | #define XREGION_HPP_ 33 | 34 | #include 35 | #include 36 | 37 | 38 | class XRegion 39 | { 40 | public: 41 | XRegion (const double rate); 42 | XRegion (const XRegion& that) = delete; 43 | ~XRegion(); 44 | XRegion& operator= (const XRegion& that) = delete; 45 | 46 | void process (float* input1, float* input2, float* output1, float* output2, int32_t sampleFrames); 47 | float* getParameters (); 48 | void setParameters (const float* values); 49 | 50 | private: 51 | double rate; 52 | float biquad[15]; 53 | float biquadA[15]; 54 | float biquadB[15]; 55 | float biquadC[15]; 56 | float biquadD[15]; 57 | uint32_t fpdL; 58 | uint32_t fpdR; 59 | float params[6]; 60 | }; 61 | 62 | #endif /* XREGION_HPP_ */ 63 | -------------------------------------------------------------------------------- /src/BAngr.cpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #include "BAngr.hpp" 22 | 23 | #include 24 | #include 25 | #include "ControllerLimits.hpp" 26 | 27 | #define LIMIT(g , min, max) ((g) > (max) ? (max) : ((g) < (min) ? (min) : (g))) 28 | 29 | const float flexTime[NR_FLEX] = {1.0f, 0.05f, 0.05f, 0.05f, 0.05f}; 30 | 31 | BAngr::BAngr (double samplerate, const LV2_Feature* const* features) : 32 | map(NULL), 33 | rate (samplerate), 34 | xcursor (0.5f), 35 | ycursor (0.5f), 36 | listen (false), 37 | rnd (time (0)), 38 | bidist (-1.0, 1.0), 39 | count (0), 40 | fader (0.0f), 41 | speed (0.0f), 42 | speedrand (0.0f), 43 | dspeedrand (0.0f), 44 | speedflex (0.0f), 45 | spin (0.0f), 46 | spinrand (0.0f), 47 | dspinrand (0.0f), 48 | spinflex (0.0f), 49 | spindir (1.0f), 50 | ang (2.0 * M_PI * bidist (rnd)), 51 | speedlevel (0.0f), 52 | speedmaxlevel (0.1f), 53 | spinlevel (0.0f), 54 | spinmaxlevel (0.1f), 55 | lowpassFilter (rate, 200.0, 8), 56 | highpassFilter (rate, 4000.0, 8), 57 | bandpassFilter (rate, 200.0, 4000.0, 8), 58 | controlPort (nullptr), 59 | notifyPort (nullptr), 60 | audioInput1 (nullptr), 61 | audioInput2 (nullptr), 62 | audioOutput1 (nullptr), 63 | audioOutput2 (nullptr), 64 | newControllers {nullptr}, 65 | controllers {0.0f}, 66 | xregion (samplerate) 67 | 68 | { 69 | //Scan host features for URID map 70 | LV2_URID_Map* m = NULL; 71 | for (int i = 0; features[i]; ++i) 72 | { 73 | if (strcmp(features[i]->URI, LV2_URID__map) == 0) 74 | { 75 | m = (LV2_URID_Map*) features[i]->data; 76 | } 77 | } 78 | if (!m) throw std::invalid_argument ("Host does not support urid:map"); 79 | 80 | //Map URIS 81 | map = m; 82 | getURIs (m, &urids); 83 | 84 | // Initialize forge 85 | lv2_atom_forge_init (&forge, map); 86 | 87 | } 88 | 89 | BAngr::~BAngr () {} 90 | 91 | void BAngr::connect_port(uint32_t port, void *data) 92 | { 93 | switch (port) { 94 | case CONTROL: 95 | controlPort = (LV2_Atom_Sequence*) data; 96 | break; 97 | case NOTIFY: 98 | notifyPort = (LV2_Atom_Sequence*) data; 99 | break; 100 | case AUDIO_IN_1: 101 | audioInput1 = (float*) data; 102 | break; 103 | case AUDIO_IN_2: 104 | audioInput2 = (float*) data; 105 | break; 106 | case AUDIO_OUT_1: 107 | audioOutput1 = (float*) data; 108 | break; 109 | case AUDIO_OUT_2: 110 | audioOutput2 = (float*) data; 111 | break; 112 | default: 113 | if ((port >= CONTROLLERS) && (port < CONTROLLERS + NR_CONTROLLERS)) newControllers[port - CONTROLLERS] = (float*) data; 114 | } 115 | } 116 | 117 | void BAngr::run (uint32_t n_samples) 118 | { 119 | // Check ports 120 | if ((!controlPort) || (!notifyPort) || (!audioInput1) || (!audioInput2) || (!audioOutput1) || (!audioOutput2)) return; 121 | for (int i = 0; i < NR_CONTROLLERS; ++i) 122 | { 123 | if (!newControllers[i]) return; 124 | } 125 | 126 | // Update controller values 127 | for (int i = 0; i < NR_CONTROLLERS; ++i) 128 | { 129 | if (controllers[i] != *newControllers[i]) controllers[i] = controllerLimits[i].validate (*newControllers[i]); 130 | } 131 | 132 | // Prepare forge buffer and initialize atom sequence 133 | const uint32_t space = notifyPort->atom.size; 134 | lv2_atom_forge_set_buffer(&forge, (uint8_t*) notifyPort, space); 135 | lv2_atom_forge_sequence_head(&forge, &frame, 0); 136 | 137 | // Process GUI data 138 | uint32_t last_t =0; 139 | LV2_ATOM_SEQUENCE_FOREACH(controlPort, ev) 140 | { 141 | if (lv2_atom_forge_is_object_type(&forge, ev->body.type)) 142 | { 143 | const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body; 144 | 145 | if (obj->body.otype == urids.bangr_cursorOn) listen = true; 146 | else if (obj->body.otype == urids.bangr_cursorOff) listen = false; 147 | 148 | else if (obj->body.otype == urids.patch_Set) 149 | { 150 | const LV2_Atom* property = NULL; 151 | const LV2_Atom* value = NULL; 152 | lv2_atom_object_get 153 | ( 154 | obj, 155 | urids.patch_property, &property, 156 | urids.patch_value, &value, 157 | NULL 158 | ); 159 | 160 | if (property && (property->type == urids.atom_URID) && value) 161 | { 162 | const uint32_t key = ((const LV2_Atom_URID*)property)->body; 163 | 164 | if ((key == urids.bangr_xcursor) && (value->type == urids.atom_Float)) xcursor = ((LV2_Atom_Float*)value)->body; 165 | else if ((key == urids.bangr_ycursor) && (value->type == urids.atom_Float)) ycursor = ((LV2_Atom_Float*)value)->body; 166 | } 167 | } 168 | 169 | // Play samples 170 | uint32_t next_t = (ev->time.frames < n_samples ? ev->time.frames : n_samples); 171 | play (last_t, next_t); 172 | last_t = next_t; 173 | } 174 | } 175 | 176 | // Play remaining samples 177 | if (last_t < n_samples) play (last_t, n_samples); 178 | 179 | // Send collected data to GUI 180 | if (!listen) notifyCursor (); 181 | 182 | // Close off sequence 183 | lv2_atom_forge_pop (&forge, &frame); 184 | } 185 | 186 | void BAngr::play (const uint32_t start, const uint32_t end) 187 | { 188 | for (uint32_t i = start; i < end; ++i) 189 | { 190 | // Update cursor 191 | if (!listen) 192 | { 193 | if (count >= rate) 194 | { 195 | dspeedrand = bidist (rnd) * controllers[SPEED_RANGE] - speedrand; 196 | dspinrand = bidist (rnd) * controllers[SPIN_RANGE] - spinrand; 197 | count = 0.0; 198 | } 199 | 200 | else count++; 201 | 202 | float dspeedflex; 203 | float dspinflex; 204 | const int speedtype = controllers[SPEED_TYPE]; 205 | const int spintype = controllers[SPIN_TYPE]; 206 | 207 | // Filter lows, mids, highs for level calculation 208 | std::array s; 209 | s.fill (0.5f * (audioInput1[i] + audioInput2[i])); 210 | if ((speedtype == LOWS) || (spintype == LOWS)) s[LOWS] = lowpassFilter.process (s[LOWS]); 211 | if ((speedtype == MIDS) || (spintype == MIDS)) s[MIDS] = bandpassFilter.process (s[MIDS]); 212 | if ((speedtype == HIGHS) || (spintype == HIGHS)) s[HIGHS] = highpassFilter.process (s[HIGHS]); 213 | 214 | // Calculate change in speed flexibility 215 | if (speedtype == RANDOM) dspeedflex = dspeedrand * (1.0f / (flexTime[speedtype] * rate)); 216 | else 217 | { 218 | // Calculate level 219 | const float coeff = fabsf (s[speedtype]); 220 | if (coeff >= speedmaxlevel) speedmaxlevel = coeff; 221 | else speedmaxlevel = (1.0 - 1.0 / (4.0 * rate)) * speedmaxlevel; 222 | if (speedmaxlevel < 0.0001f) speedmaxlevel = 0.0001f; // Limit to -80 db to prevent div by zero 223 | speedlevel = (1.0 - 1.0 / (flexTime[LEVEL] * rate)) * speedlevel + 1.0 / (flexTime[LEVEL] * rate) * (2.0 * coeff / speedmaxlevel); 224 | 225 | dspeedflex = (2.0f * LIMIT (speedlevel, 0.0f, 1.0f) - 1.0f) * controllers[SPEED_RANGE] - speedflex; 226 | 227 | // Command line meter (for debugging) 228 | /* 229 | if (int(count) % 1000 == 0) 230 | { 231 | char s[41]; 232 | memset (s, ' ', 40); 233 | int x = int (40 * LIMIT (speedlevel, 0.0f, 1.0f)); 234 | memset (s, '.', x); 235 | s[40] = 0; 236 | fprintf (stderr, "\r%s", s); 237 | } 238 | */ 239 | } 240 | 241 | // Calculate change in spin flexibility 242 | if (spintype == RANDOM) dspinflex = dspinrand * (1.0f / (flexTime[spintype] * rate)); 243 | else 244 | { 245 | // Calculate level 246 | const float coeff = fabsf (s[spintype]); 247 | if (coeff >= spinmaxlevel) spinmaxlevel = coeff; 248 | else spinmaxlevel = (1.0 - 1.0 / (4.0 * rate)) * spinmaxlevel; 249 | if (spinmaxlevel < 0.0001f) spinmaxlevel = 0.0001f; // Limit to -80 db to prevent div by zero 250 | const float nspinlevel = (1.0 - 1.0 / (flexTime[LEVEL] * rate)) * spinlevel + 1.0 / (flexTime[LEVEL] * rate) * (2.0 * coeff / spinmaxlevel); 251 | 252 | if ((spinlevel >= 0.2f) && (nspinlevel < 0.2f)) spindir = (bidist (rnd) >= 0.0f ? spindir : -spindir); 253 | spinlevel = nspinlevel; 254 | dspinflex = spindir * LIMIT (spinlevel, 0.0f, 1.0f) * controllers[SPIN_RANGE] - spinflex; 255 | }; 256 | 257 | // Update speed 258 | speedrand += (1.0f / rate) * dspeedrand; 259 | speedflex += dspeedflex; 260 | speed = controllers[SPEED] + controllers[SPEED_AMOUNT] * speedflex + (1.0f - controllers[SPEED_AMOUNT]) * speedrand; 261 | speed = LIMIT (speed, 0.0f, 1.0f); 262 | 263 | // Update ang 264 | spinrand += (1.0f / rate) * dspinrand; 265 | spinflex += dspinflex; 266 | spin = controllers[SPIN] + controllers[SPIN_AMOUNT] * spinflex + (1.0f - controllers[SPIN_AMOUNT]) * spinrand; 267 | spin = LIMIT (spin, -1.0f, 1.0f); 268 | ang += 2.0 * M_PI * (10.0 / rate) * spin; 269 | 270 | // Calulate new positions 271 | const float dx = sinf (ang); 272 | const float dy = cosf (ang); 273 | xcursor += dx * (1.0 / rate) * speed * speed; 274 | ycursor += dy * (1.0 / rate) * speed * speed; 275 | 276 | // Reflections 277 | if (xcursor < 0.0f) 278 | { 279 | xcursor = 0.0f; 280 | if (dx < 0.0f) {ang = -ang; spin = 0.0f;} 281 | } 282 | 283 | else if (xcursor > 1.0f) 284 | { 285 | xcursor = 1.0f; 286 | if (dx > 0.0f) {ang = -ang; spin = 0.0f;} 287 | } 288 | 289 | if (ycursor < 0.0f) 290 | { 291 | ycursor = 0.0f; 292 | if (dy < 0.0f) {ang = -M_PI - ang; spin = 0.0f;} 293 | } 294 | 295 | else if (ycursor > 1.0f) 296 | { 297 | ycursor = 1.0f; 298 | if (dy > 0.0f) {ang = -M_PI - ang; spin = 0.0f;} 299 | } 300 | } 301 | 302 | // Calculate params for cursor position 303 | float params[NR_PARAMS] = {0}; 304 | for (int i = 0; i < NR_PARAMS; ++i) 305 | { 306 | params[i] = 307 | ( 308 | ((1.0f - xcursor) * (1.0f - ycursor) * controllers[FX + 0 * NR_PARAMS + i]) + 309 | ((1.0f - xcursor) * ycursor * controllers[FX + 1 * NR_PARAMS + i]) + 310 | (xcursor * ycursor * controllers[FX + 2 * NR_PARAMS + i]) + 311 | (xcursor * (1.0 - ycursor) * controllers[FX + 3 * NR_PARAMS + i]) 312 | ); 313 | } 314 | 315 | // Update fader 316 | if (fader != (1.0f - controllers[BYPASS])) 317 | { 318 | fader += (fader < 1.0f - controllers[BYPASS] ? 100.0 / rate : -100.0 / rate); 319 | fader = LIMIT (fader, 0.0f, 1.0f); 320 | } 321 | 322 | // Set params and process 323 | if (fader) 324 | { 325 | float out1 = audioOutput1[i]; 326 | float out2 = audioOutput2[i]; 327 | xregion.setParameters (params); 328 | xregion.process (&audioInput1[i], &audioInput2[i], &out1, &out2, 1); 329 | 330 | // Dry/wet mix 331 | audioOutput1[i] = fader * controllers[DRY_WET] * out1 + (1.0f - fader * controllers[DRY_WET]) * audioInput1[i]; 332 | audioOutput2[i] = fader * controllers[DRY_WET] * out2 + (1.0f - fader * controllers[DRY_WET]) * audioInput2[i]; 333 | } 334 | 335 | else 336 | { 337 | audioOutput1[i] = audioInput1[i]; 338 | audioOutput2[i] = audioInput2[i]; 339 | 340 | } 341 | } 342 | } 343 | 344 | void BAngr::notifyCursor() 345 | { 346 | LV2_Atom_Forge_Frame frame; 347 | lv2_atom_forge_frame_time(&forge, 0); 348 | lv2_atom_forge_object(&forge, &frame, 0, urids.patch_Set); 349 | lv2_atom_forge_key(&forge, urids.patch_property); 350 | lv2_atom_forge_urid(&forge, urids.bangr_xcursor); 351 | lv2_atom_forge_key(&forge, urids.patch_value); 352 | lv2_atom_forge_float(&forge, xcursor); 353 | lv2_atom_forge_pop(&forge, &frame); 354 | 355 | lv2_atom_forge_frame_time(&forge, 0); 356 | lv2_atom_forge_object(&forge, &frame, 0, urids.patch_Set); 357 | lv2_atom_forge_key(&forge, urids.patch_property); 358 | lv2_atom_forge_urid(&forge, urids.bangr_ycursor); 359 | lv2_atom_forge_key(&forge, urids.patch_value); 360 | lv2_atom_forge_float(&forge, ycursor); 361 | lv2_atom_forge_pop(&forge, &frame); 362 | } 363 | 364 | LV2_State_Status BAngr::state_save (LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, 365 | const LV2_Feature* const* features) 366 | { 367 | store (handle, urids.bangr_xcursor, &xcursor, sizeof (float), urids.atom_Float, LV2_STATE_IS_POD); 368 | store (handle, urids.bangr_ycursor, &ycursor, sizeof (float), urids.atom_Float, LV2_STATE_IS_POD); 369 | return LV2_STATE_SUCCESS; 370 | } 371 | 372 | LV2_State_Status BAngr::state_restore (LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, 373 | const LV2_Feature* const* features) 374 | { 375 | size_t size; 376 | uint32_t type; 377 | uint32_t valflags; 378 | 379 | const void* xcursorData = retrieve(handle, urids.bangr_xcursor, &size, &type, &valflags); 380 | if (xcursorData && (type == urids.atom_Float)) xcursor = LIMIT (*(const float*)xcursorData, 0.0f, 1.0f); 381 | 382 | const void* ycursorData = retrieve(handle, urids.bangr_ycursor, &size, &type, &valflags); 383 | if (ycursorData && (type == urids.atom_Float)) ycursor = LIMIT (*(const float*)ycursorData, 0.0f, 1.0f); 384 | 385 | return LV2_STATE_SUCCESS; 386 | } 387 | 388 | static LV2_Handle instantiate (const LV2_Descriptor* descriptor, double samplerate, const char* bundle_path, const LV2_Feature* const* features) 389 | { 390 | // New instance 391 | BAngr* instance; 392 | try {instance = new BAngr(samplerate, features);} 393 | catch (std::exception& exc) 394 | { 395 | fprintf (stderr, "BAngr.lv2: Plugin instantiation failed. %s\n", exc.what ()); 396 | return NULL; 397 | } 398 | 399 | if (!instance->map) 400 | { 401 | fprintf(stderr, "BAngr.lv2: Host does not support urid:map.\n"); 402 | delete (instance); 403 | return NULL; 404 | } 405 | 406 | return (LV2_Handle)instance; 407 | } 408 | 409 | static void connect_port (LV2_Handle instance, uint32_t port, void *data) 410 | { 411 | BAngr* inst = (BAngr*) instance; 412 | if (inst) inst->connect_port (port, data); 413 | } 414 | 415 | static void run (LV2_Handle instance, uint32_t n_samples) 416 | { 417 | BAngr* inst = (BAngr*) instance; 418 | if (inst) inst->run (n_samples); 419 | } 420 | 421 | static void cleanup (LV2_Handle instance) 422 | { 423 | BAngr* inst = (BAngr*) instance; 424 | if (inst) delete inst; 425 | } 426 | 427 | static LV2_State_Status state_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, 428 | const LV2_Feature* const* features) 429 | { 430 | BAngr* inst = (BAngr*)instance; 431 | if (!inst) return LV2_STATE_SUCCESS; 432 | 433 | inst->state_save (store, handle, flags, features); 434 | return LV2_STATE_SUCCESS; 435 | } 436 | 437 | static LV2_State_Status state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, 438 | const LV2_Feature* const* features) 439 | { 440 | BAngr* inst = (BAngr*)instance; 441 | if (inst) inst->state_restore (retrieve, handle, flags, features); 442 | return LV2_STATE_SUCCESS; 443 | } 444 | 445 | static const void* extension_data(const char* uri) 446 | { 447 | static const LV2_State_Interface state = {state_save, state_restore}; 448 | if (!strcmp(uri, LV2_STATE__interface)) return &state; 449 | return NULL; 450 | } 451 | 452 | static const LV2_Descriptor descriptor = 453 | { 454 | BANGR_URI, 455 | instantiate, 456 | connect_port, 457 | NULL, //activate, 458 | run, 459 | NULL, //deactivate, 460 | cleanup, 461 | extension_data 462 | }; 463 | 464 | // LV2 Symbol Export 465 | LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index) 466 | { 467 | switch (index) 468 | { 469 | case 0: return &descriptor; 470 | default: return NULL; 471 | } 472 | } 473 | -------------------------------------------------------------------------------- /src/BAngr.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef BANGR_HPP_ 22 | #define BANGR_HPP_ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "Definitions.hpp" 35 | #include "Ports.hpp" 36 | #include "Urids.hpp" 37 | #include "Airwindows/XRegion.hpp" 38 | #include "ButterworthLowPassFilter.hpp" 39 | #include "ButterworthHighPassFilter.hpp" 40 | #include "ButterworthBandPassFilter.hpp" 41 | 42 | 43 | class BAngr 44 | { 45 | public: 46 | BAngr (double samplerate, const LV2_Feature* const* features); 47 | ~BAngr(); 48 | 49 | void connect_port (uint32_t port, void *data); 50 | void run (uint32_t n_samples); 51 | LV2_State_Status state_save(LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features); 52 | LV2_State_Status state_restore(LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features); 53 | 54 | LV2_URID_Map* map; 55 | 56 | private: 57 | double rate; 58 | float xcursor; 59 | float ycursor; 60 | bool listen; 61 | std::minstd_rand rnd; 62 | std::uniform_real_distribution bidist; 63 | double count; 64 | float fader; 65 | float speed; 66 | float speedrand; 67 | float dspeedrand; 68 | float speedflex; 69 | float spin; 70 | float spinrand; 71 | float dspinrand; 72 | float spinflex; 73 | float spindir; 74 | float ang; 75 | float speedlevel; 76 | float speedmaxlevel; 77 | float spinlevel; 78 | float spinmaxlevel; 79 | ButterworthLowPassFilter lowpassFilter; 80 | ButterworthHighPassFilter highpassFilter; 81 | ButterworthBandPassFilter bandpassFilter; 82 | 83 | // Control ports 84 | LV2_Atom_Sequence* controlPort; 85 | LV2_Atom_Sequence* notifyPort; 86 | 87 | // Audio ports 88 | float* audioInput1; 89 | float* audioInput2; 90 | float* audioOutput1; 91 | float* audioOutput2; 92 | 93 | // Controllers 94 | float* newControllers[NR_CONTROLLERS]; 95 | float controllers[NR_CONTROLLERS]; 96 | 97 | // Urids 98 | BAngrURIs urids; 99 | 100 | // Internals 101 | LV2_Atom_Forge forge; 102 | LV2_Atom_Forge_Frame frame; 103 | XRegion xregion; 104 | 105 | void play (const uint32_t start, const uint32_t end); 106 | void notifyCursor(); 107 | 108 | }; 109 | 110 | #endif /* BANGR_HPP_ */ 111 | -------------------------------------------------------------------------------- /src/BAngrDial.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 - 2023 by Sven Jähnichen 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef BANGRDIAL_HPP_ 21 | #define BANGRDIAL_HPP_ 22 | 23 | #include "BWidgets/BWidgets/ValueDial.hpp" 24 | 25 | class BAngrDial : public BWidgets::ValueDial 26 | { 27 | public: 28 | BAngrDial (); 29 | BAngrDial (const uint32_t urid, const std::string& title); 30 | BAngrDial (const double value, const double min, const double max, double step = 0.0, 31 | uint32_t urid = BUTILITIES_URID_UNKNOWN_URID, std::string title = ""); 32 | BAngrDial (const double x, const double y, const double width, const double height, 33 | const double value, const double min, const double max, double step = 0.0, 34 | std::function transferFunc = ValueTransferable::noTransfer, 35 | std::function reTransferFunc = ValueTransferable::noTransfer, 36 | std::function displayFunc = valueToString, 37 | std::function reDisplayFunc = stringToValue, 38 | uint32_t urid = BUTILITIES_URID_UNKNOWN_URID, std::string title = ""); 39 | 40 | virtual Widget* clone () const override; 41 | void copy (const BAngrDial* that); 42 | virtual void update () override; 43 | 44 | protected: 45 | virtual void drawArc (cairo_t* cr, const double xc, const double yc, const double radius, 46 | const double min, const double max, 47 | const BStyles::Color fgColor, const BStyles::Color bgColor); 48 | virtual void draw () override; 49 | virtual void draw (const double x0, const double y0, const double width, const double height) override; 50 | virtual void draw (const BUtilities::Area<>& area) override; 51 | }; 52 | 53 | inline BAngrDial::BAngrDial () : 54 | BAngrDial ( 55 | 0.0, 0.0, BWIDGETS_DEFAULT_VALUEDIAL_WIDTH, BWIDGETS_DEFAULT_VALUEDIAL_HEIGHT, 56 | 0.0, 0.0, 1.0, 0.0, 57 | ValueTransferable::noTransfer, 58 | ValueTransferable::noTransfer, 59 | valueToString, 60 | stringToValue, 61 | BUTILITIES_URID_UNKNOWN_URID, "") 62 | { 63 | 64 | } 65 | 66 | inline BAngrDial::BAngrDial (const uint32_t urid, const std::string& title) : 67 | BAngrDial (0.0, 0.0, BWIDGETS_DEFAULT_VALUEDIAL_WIDTH, BWIDGETS_DEFAULT_VALUEDIAL_HEIGHT, 68 | 0.0, 0.0, 1.0, 0.0, 69 | ValueTransferable::noTransfer, 70 | ValueTransferable::noTransfer, 71 | valueToString, 72 | stringToValue, 73 | urid, title) 74 | { 75 | 76 | } 77 | 78 | inline BAngrDial::BAngrDial (const double value, const double min, const double max, double step, uint32_t urid, std::string title) : 79 | BAngrDial (0.0, 0.0, BWIDGETS_DEFAULT_VALUEDIAL_WIDTH, BWIDGETS_DEFAULT_VALUEDIAL_HEIGHT, 80 | value, min, max, step, 81 | ValueTransferable::noTransfer, 82 | ValueTransferable::noTransfer, 83 | valueToString, 84 | stringToValue, 85 | urid, title) 86 | { 87 | 88 | } 89 | 90 | inline BAngrDial::BAngrDial (const double x, const double y, const double width, const double height, 91 | double value, const double min, const double max, double step, 92 | std::function transferFunc, 93 | std::function reTransferFunc, 94 | std::function displayFunc, 95 | std::function reDisplayFunc, 96 | uint32_t urid, std::string title) : 97 | ValueDial (x, y, width, height, value, min, max, step, transferFunc, reTransferFunc, displayFunc, reDisplayFunc, urid, title) 98 | { 99 | } 100 | 101 | inline BWidgets::Widget* BAngrDial::clone () const 102 | { 103 | Widget* f = new BAngrDial (urid_, title_); 104 | f->copy (this); 105 | return f; 106 | } 107 | 108 | inline void BAngrDial::copy (const BAngrDial* that) 109 | { 110 | ValueDial::copy (that); 111 | } 112 | 113 | inline void BAngrDial::update () 114 | { 115 | ValueDial::update(); 116 | label.moveTo(label.center(), label.middle()); 117 | } 118 | 119 | inline void BAngrDial::drawArc (cairo_t* cr, const double xc, const double yc, const double radius, 120 | const double min, const double max, 121 | const BStyles::Color fgColor, const BStyles::Color bgColor) 122 | { 123 | cairo_set_line_width (cr, 0.0); 124 | 125 | // Arc 126 | cairo_set_source_rgba (cr, CAIRO_RGBA(bgColor)); 127 | cairo_arc (cr, xc, yc, 0.96 * radius, BWIDGETS_DEFAULT_DRAWARC_START, BWIDGETS_DEFAULT_DRAWARC_END); 128 | cairo_arc_negative (cr, xc, yc, 0.70 * radius, BWIDGETS_DEFAULT_DRAWARC_END, BWIDGETS_DEFAULT_DRAWARC_START); 129 | cairo_close_path (cr); 130 | cairo_fill (cr); 131 | 132 | // Fill 133 | cairo_set_source_rgba (cr, CAIRO_RGBA(fgColor)); 134 | cairo_arc (cr, xc, yc, 0.96 * radius - 0.2, BWIDGETS_DEFAULT_DRAWARC_START + min * BWIDGETS_DEFAULT_DRAWARC_SIZE, BWIDGETS_DEFAULT_DRAWARC_START + max * BWIDGETS_DEFAULT_DRAWARC_SIZE); 135 | cairo_arc_negative (cr, xc, yc, 0.7 * radius - 0.2, BWIDGETS_DEFAULT_DRAWARC_START + max * BWIDGETS_DEFAULT_DRAWARC_SIZE, BWIDGETS_DEFAULT_DRAWARC_START + min * BWIDGETS_DEFAULT_DRAWARC_SIZE); 136 | cairo_close_path (cr); 137 | cairo_fill (cr); 138 | } 139 | 140 | inline void BAngrDial::draw () 141 | { 142 | draw (0, 0, getWidth(), getHeight()); 143 | } 144 | 145 | inline void BAngrDial::draw (const double x0, const double y0, const double width, const double height) 146 | { 147 | draw (BUtilities::Area<> (x0, y0, width, height)); 148 | } 149 | 150 | inline void BAngrDial::draw (const BUtilities::Area<>& area) 151 | { 152 | if ((!cairoSurface()) || (cairo_surface_status (cairoSurface()) != CAIRO_STATUS_SUCCESS)) return; 153 | 154 | // Draw super class widget elements first 155 | Widget::draw (area); 156 | 157 | // Draw only if minimum requirements satisfied 158 | if ((getHeight () >= 1) && (getWidth () >= 1)) 159 | { 160 | cairo_t* cr = cairo_create (cairoSurface()); 161 | 162 | if (cairo_status (cr) == CAIRO_STATUS_SUCCESS) 163 | { 164 | // Limit cairo-drawing area 165 | cairo_rectangle (cr, area.getX (), area.getY (), area.getWidth (), area.getHeight ()); 166 | cairo_clip (cr); 167 | 168 | const double rval = getRatioFromValue (getValue()); 169 | const double rad = 0.5 * (scale_.getWidth() < scale_.getHeight() ? scale_.getWidth() : scale_.getHeight()); 170 | const BStyles::Color fgColor = getFgColors()[getStatus()]; 171 | const BStyles::Color bgColor = getBgColors()[getStatus()]; 172 | 173 | if (step_ >= 0.0) 174 | { 175 | drawArc (cr, getXOffset() + 0.5 * getEffectiveWidth(), getYOffset() + 0.5 * getEffectiveHeight(), rad - 1.0, 0.0, rval, fgColor, bgColor); 176 | } 177 | 178 | else 179 | { 180 | drawArc (cr, getXOffset() + 0.5 * getEffectiveWidth(), getYOffset() + 0.5 * getEffectiveHeight(), rad - 1.0, 1.0 - rval, 1.0, fgColor, bgColor); 181 | } 182 | } 183 | 184 | cairo_destroy (cr); 185 | } 186 | } 187 | #endif /* BANGRDIAL_HPP_ */ 188 | -------------------------------------------------------------------------------- /src/BAngrGUI.cpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 - 2023 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #include "BAngrGUI.hpp" 22 | #include 23 | #include 24 | #include "BAngrDial.hpp" 25 | #include "BWidgets/BEvents/Event.hpp" 26 | #include "BWidgets/BEvents/ExposeEvent.hpp" 27 | #include "BWidgets/BUtilities/Dictionary.hpp" 28 | #include "BWidgets/BWidgets/ComboBox.hpp" 29 | #include "BWidgets/BWidgets/Label.hpp" 30 | #include "BWidgets/BWidgets/Supports/ValueTransferable.hpp" 31 | #include "BWidgets/BWidgets/Supports/ValueableTyped.hpp" 32 | #include "Ports.hpp" 33 | #include "BWidgets/BUtilities/vsystem.hpp" 34 | 35 | 36 | BAngrGUI::BAngrGUI (const char *bundle_path, const LV2_Feature *const *features, PuglNativeView parentWindow) : 37 | Window (1000, 560, parentWindow, URID(), "B.Choppr", true, PUGL_MODULE, 0), 38 | controller (NULL), 39 | write_function (NULL), 40 | pluginPath (bundle_path ? std::string (bundle_path) : std::string ("")), 41 | map (nullptr), 42 | 43 | mContainer(0, 0, 1000, 560, pluginPath + "inc/surface.png", URID ("/bgimage")), 44 | cursor (480, 260, 40, 40, URID ("/dot")), 45 | poweredLabel (720, 540, 250, 20, BDICT("Powered by Airwindows XRegion"), URID ("/rlabel")), 46 | helpButton (918, 508, 24, 24, false, false, URID ("/halobutton"), BDICT ("Help")), 47 | ytButton (948, 508, 24, 24, false, false, URID ("/halobutton"), BDICT ("Preview")), 48 | bypassButton (900, 30, 20, 20, 2, true, false, URID ("/redbutton"), BDICT ("Bypass")), 49 | bypassLabel (880, 60, 60, 20, BDICT ("Bypass"), URID ("/label")), 50 | drywetDial (940, 20, 40, 40, 1.0, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Dry/wet")), 51 | drywetLabel (930, 60, 60, 20, BDICT ("Dry/wet"), URID ("/label")), 52 | speedDial (370, 460, 60, 60, 0.5, 0.5, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Speed")), 53 | speedLabel (350, 520, 100, 20, BDICT("Speed"), URID("/label")), 54 | spinDial (570, 460, 60, 60, 0.0, 0.0, -1.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Spin")), 55 | spinLabel (550, 520, 100, 20, BDICT("Spin"), URID("/label")), 56 | speedScreen (180, 480, 100, 35, URID("/screen")), 57 | speedFlexLabel (220, 520, 100, 20, BDICT("Flexibility"), URID("/label")), 58 | speedTypeCombobox (280, 490, 80, 20, 0, -120, 80, 120, {BDICT("Random"), BDICT("Level"), BDICT("Lows"), BDICT("Mids"), BDICT("Highs")}, 1, URID("/menu")), 59 | speedAmountSlider (200, 485, 80, 20, 0.0, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Speed")), 60 | spinScreen (640, 480, 100, 35, URID("/screen")), 61 | spinFlexLabel (680, 520, 100, 20, BDICT("Flexibility"), URID("/label")), 62 | spinTypeCombobox (740, 490, 80, 20, 0, -120, 80, 120, {BDICT("Random"), BDICT("Level"), BDICT("Lows"), BDICT("Mids"), BDICT("Highs")}, 1, URID("/menu")), 63 | spinAmountSlider (660, 485, 80, 20, 0.0, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Spin")) 64 | { 65 | // Init param widgets 66 | for (int i = 0; i < NR_FX; ++i) 67 | { 68 | fx[i].container = new BWidgets::Widget (20 + int (i / 2) * 660, 100 + int (((i + 1) & 3) / 2) * 200, 300, 160, URID ("/widget")); 69 | fx[i].paramDials[0] = new BAngrDial (0, 10, 60, 60, 0.5, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Gain")); 70 | fx[i].paramLabels[0] = new BWidgets::Label (0, 70, 60, 20, BDICT("Gain"), URID("/label")); 71 | fx[i].paramDials[1] = new BAngrDial (80, 10, 60, 60, 0.5, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("First")); 72 | fx[i].paramLabels[1] = new BWidgets::Label (80, 70, 60, 20, BDICT("First"), URID("/label")); 73 | fx[i].paramDials[2] = new BAngrDial (160, 10, 60, 60, 0.5, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Last")); 74 | fx[i].paramLabels[2] = new BWidgets::Label (160, 70, 60, 20, BDICT("Last"), URID("/label")); 75 | fx[i].paramDials[3] = new BAngrDial (240, 10, 60, 60, 0.0, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Nuke")); 76 | fx[i].paramLabels[3] = new BWidgets::Label (240, 70, 60, 20, BDICT("Nuke"), URID("/label")); 77 | fx[i].paramDials[4] = new BAngrDial (40, 70, 60, 60, 1.0, 0.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Mix")); 78 | fx[i].paramLabels[4] = new BWidgets::Label (40, 130, 60, 20, BDICT("Mix"), URID("/label")); 79 | fx[i].paramDials[5] = new BAngrDial (200, 70, 60, 60, 0.0, -1.0, 1.0, 0.0, BNOTRANSFERD, BNOTRANSFERD, BDOUBLE_TO_STRING, BSTRING_TO_DOUBLE, URID ("/dial"), BDICT ("Pan")); 80 | fx[i].paramLabels[5] = new BWidgets::Label (200, 130, 60, 20, BDICT("Pan"), URID("/label")); 81 | } 82 | 83 | // Link controllers 84 | controllerWidgets[BYPASS] = &bypassButton; 85 | controllerWidgets[DRY_WET] = &drywetDial; 86 | controllerWidgets[SPEED] = &speedDial; 87 | controllerWidgets[SPEED_RANGE] = &speedDial.range; 88 | controllerWidgets[SPEED_TYPE] = &speedTypeCombobox; 89 | controllerWidgets[SPEED_AMOUNT] = &speedAmountSlider; 90 | controllerWidgets[SPIN] = &spinDial; 91 | controllerWidgets[SPIN_RANGE] = &spinDial.range; 92 | controllerWidgets[SPIN_TYPE] = &spinTypeCombobox; 93 | controllerWidgets[SPIN_AMOUNT] = &spinAmountSlider; 94 | 95 | for (int i = 0; i < NR_FX; ++i) 96 | { 97 | for (int j = 0; j < NR_PARAMS; ++j) 98 | { 99 | controllerWidgets[FX + i * NR_PARAMS + j] = fx[i].paramDials[j]; 100 | } 101 | } 102 | 103 | // Configure widgets 104 | cursor.setDraggable (true); 105 | drywetDial.setClickable(false); 106 | drywetDial.setScrollable(true); 107 | drywetDial.label.hide(); 108 | speedDial.setClickable(false); 109 | speedDial.setScrollable(true); 110 | spinDial.setClickable(false); 111 | spinDial.setScrollable(true); 112 | speedAmountSlider.setClickable(false); 113 | speedAmountSlider.setScrollable(true); 114 | spinAmountSlider.setClickable(false); 115 | spinAmountSlider.setScrollable(true); 116 | for (Fx& f : fx) 117 | { 118 | for (BAngrDial* b : f.paramDials) 119 | { 120 | b->setClickable(false); 121 | b->setScrollable(true); 122 | } 123 | } 124 | setTheme(theme); 125 | 126 | 127 | // Set callbacks 128 | for (BWidgets::Widget* c : controllerWidgets) c->setCallbackFunction (BEvents::Event::EventType::valueChangedEvent, BAngrGUI::valueChangedCallback); 129 | cursor.setCallbackFunction (BEvents::Event::EventType::pointerDragEvent, BAngrGUI::cursorDraggedCallback); 130 | cursor.setCallbackFunction (BEvents::Event::EventType::buttonPressEvent, BAngrGUI::cursorDraggedCallback); 131 | cursor.setCallbackFunction (BEvents::Event::EventType::buttonReleaseEvent, BAngrGUI::cursorReleasedCallback); 132 | poweredLabel.setCallbackFunction (BEvents::Event::EventType::buttonPressEvent, BAngrGUI::xregionClickedCallback); 133 | helpButton.setCallbackFunction (BEvents::Event::EventType::buttonPressEvent, BAngrGUI::helpButtonClickedCallback); 134 | ytButton.setCallbackFunction (BEvents::Event::EventType::buttonPressEvent, BAngrGUI::ytButtonClickedCallback); 135 | 136 | // Pack widgets 137 | for (Fx& f : fx) 138 | { 139 | for (BAngrDial* d : f.paramDials) f.container->add (d); 140 | for (BWidgets::Label* l : f.paramLabels) f.container->add (l); 141 | mContainer.add (f.container); 142 | } 143 | mContainer.add (&bypassButton); 144 | mContainer.add (&bypassLabel); 145 | mContainer.add (&drywetDial); 146 | mContainer.add (&drywetLabel); 147 | mContainer.add (&speedDial); 148 | mContainer.add (&speedLabel); 149 | mContainer.add (&spinDial); 150 | mContainer.add (&spinLabel); 151 | mContainer.add (&speedFlexLabel); 152 | mContainer.add (&speedTypeCombobox); 153 | mContainer.add (&speedAmountSlider); 154 | mContainer.add (&spinFlexLabel); 155 | mContainer.add (&spinTypeCombobox); 156 | mContainer.add (&spinAmountSlider); 157 | mContainer.add (&speedScreen); 158 | mContainer.add (&spinScreen); 159 | mContainer.add (&cursor); 160 | mContainer.add (&poweredLabel); 161 | mContainer.add (&helpButton); 162 | mContainer.add (&ytButton); 163 | add (&mContainer); 164 | 165 | //Scan host features for URID map 166 | LV2_URID_Map* m = NULL; 167 | 168 | for (int i = 0; features[i]; ++i) 169 | { 170 | if (strcmp(features[i]->URI, LV2_URID__map) == 0) m = static_cast (features[i]->data); 171 | } 172 | if (!m) throw std::invalid_argument ("Host does not support urid:map"); 173 | 174 | //Map URIS 175 | map = m; 176 | getURIs (map, &urids); 177 | 178 | // Initialize forge 179 | lv2_atom_forge_init (&forge,map); 180 | } 181 | 182 | BAngrGUI::~BAngrGUI() 183 | { 184 | for (const Fx& fxi : fx) 185 | { 186 | delete fxi.container; 187 | for (const BAngrDial* d : fxi.paramDials) delete d; 188 | for (const BWidgets::Label* l : fxi.paramLabels) delete l; 189 | } 190 | } 191 | 192 | void BAngrGUI::portEvent(uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer) 193 | { 194 | // Notify port 195 | if ((format == urids.atom_eventTransfer) && (port_index == NOTIFY)) 196 | { 197 | const LV2_Atom* atom = static_cast (buffer); 198 | if (lv2_atom_forge_is_object_type(&forge, atom->type)) 199 | { 200 | const LV2_Atom_Object* obj = reinterpret_cast (atom); 201 | 202 | if (obj->body.otype == urids.patch_Set) 203 | { 204 | const LV2_Atom* property = NULL; 205 | const LV2_Atom* value = NULL; 206 | lv2_atom_object_get 207 | ( 208 | obj, 209 | urids.patch_property, &property, 210 | urids.patch_value, &value, 211 | NULL 212 | ); 213 | 214 | if (property && (property->type == urids.atom_URID) && value) 215 | { 216 | const uint32_t key = reinterpret_cast(property)->body; 217 | 218 | if ((key == urids.bangr_xcursor) && (value->type == urids.atom_Float)) 219 | { 220 | const float xcursor = reinterpret_cast(value)->body; 221 | cursor.moveTo ((400.0 + xcursor * 200.0) - 0.5 * cursor.getWidth(), cursor.getPosition().y); 222 | } 223 | 224 | else if ((key == urids.bangr_ycursor) && (value->type == urids.atom_Float)) 225 | { 226 | const float ycursor = reinterpret_cast(value)->body; 227 | cursor.moveTo (cursor.getPosition().x, (180.0 + ycursor * 200.0) - 0.5 * cursor.getHeight()); 228 | } 229 | } 230 | } 231 | } 232 | } 233 | 234 | // Scan controller ports 235 | else if ((format == 0) && (port_index >= CONTROLLERS) && (port_index < CONTROLLERS + NR_CONTROLLERS)) 236 | { 237 | const float* pval = static_cast (buffer); 238 | 239 | // Offst Comboboxes by 1 240 | if ((port_index - CONTROLLERS == SPEED_TYPE) || (port_index - CONTROLLERS == SPIN_TYPE)) 241 | { 242 | BWidgets::ComboBox* combobox = dynamic_cast(controllerWidgets[port_index - CONTROLLERS]); 243 | if (combobox) combobox->setValue(*pval + 1); 244 | } 245 | 246 | // All other control ports 247 | else 248 | { 249 | BWidgets::ValueableTyped* valueable = dynamic_cast*>(controllerWidgets[port_index - CONTROLLERS]); 250 | if (valueable) valueable->setValue (*pval); 251 | } 252 | } 253 | } 254 | 255 | void BAngrGUI::onConfigureRequest (BEvents::Event* event) 256 | { 257 | Window::onConfigureRequest (event); 258 | 259 | BEvents::ExposeEvent* ee = dynamic_cast(event); 260 | if (!ee) return; 261 | const double sz = (ee->getArea().getWidth() / 1000.0 > ee->getArea().getHeight() / 560.0 ? ee->getArea().getHeight() / 560.0 : ee->getArea().getWidth() / 1000.0); 262 | setZoom (sz); 263 | } 264 | 265 | void BAngrGUI::sendCursor () 266 | { 267 | sendCursorOn(); 268 | sendXCursor(); 269 | sendYCursor(); 270 | } 271 | 272 | void BAngrGUI::sendXCursor () 273 | { 274 | uint8_t obj_buf[128]; 275 | lv2_atom_forge_set_buffer(&forge, obj_buf, sizeof(obj_buf)); 276 | 277 | LV2_Atom_Forge_Frame frame; 278 | LV2_Atom* msg = reinterpret_cast(lv2_atom_forge_object(&forge, &frame, 0, urids.patch_Set)); 279 | lv2_atom_forge_key(&forge, urids.patch_property); 280 | lv2_atom_forge_urid(&forge, urids.bangr_xcursor); 281 | lv2_atom_forge_key(&forge, urids.patch_value); 282 | lv2_atom_forge_float(&forge, ((cursor.getPosition().x + 0.5 * cursor.getWidth()) - 400.0) / 200.0); 283 | lv2_atom_forge_pop(&forge, &frame); 284 | write_function(controller, CONTROL, lv2_atom_total_size(msg), urids.atom_eventTransfer, msg); 285 | } 286 | 287 | void BAngrGUI::sendYCursor () 288 | { 289 | uint8_t obj_buf[128]; 290 | lv2_atom_forge_set_buffer(&forge, obj_buf, sizeof(obj_buf)); 291 | 292 | LV2_Atom_Forge_Frame frame; 293 | LV2_Atom* msg = reinterpret_cast(lv2_atom_forge_object(&forge, &frame, 0, urids.patch_Set)); 294 | lv2_atom_forge_key(&forge, urids.patch_property); 295 | lv2_atom_forge_urid(&forge, urids.bangr_ycursor); 296 | lv2_atom_forge_key(&forge, urids.patch_value); 297 | lv2_atom_forge_float(&forge, ((cursor.getPosition().y + 0.5 * cursor.getHeight()) - 180.0) / 200.0); 298 | lv2_atom_forge_pop(&forge, &frame); 299 | write_function(controller, CONTROL, lv2_atom_total_size(msg), urids.atom_eventTransfer, msg); 300 | } 301 | 302 | void BAngrGUI::sendCursorOn () 303 | { 304 | uint8_t obj_buf[64]; 305 | lv2_atom_forge_set_buffer(&forge, obj_buf, sizeof(obj_buf)); 306 | 307 | LV2_Atom_Forge_Frame frame; 308 | LV2_Atom* msg = reinterpret_cast(lv2_atom_forge_object(&forge, &frame, 0, urids.bangr_cursorOn)); 309 | lv2_atom_forge_pop(&forge, &frame); 310 | write_function(controller, CONTROL, lv2_atom_total_size(msg), urids.atom_eventTransfer, msg); 311 | } 312 | 313 | void BAngrGUI::sendCursorOff () 314 | { 315 | uint8_t obj_buf[64]; 316 | lv2_atom_forge_set_buffer(&forge, obj_buf, sizeof(obj_buf)); 317 | 318 | LV2_Atom_Forge_Frame frame; 319 | LV2_Atom* msg = reinterpret_cast(lv2_atom_forge_object(&forge, &frame, 0, urids.bangr_cursorOff)); 320 | lv2_atom_forge_pop(&forge, &frame); 321 | write_function(controller, CONTROL, lv2_atom_total_size(msg), urids.atom_eventTransfer, msg); 322 | } 323 | 324 | void BAngrGUI::valueChangedCallback (BEvents::Event* event) 325 | { 326 | if (!event) return; 327 | 328 | BWidgets::Widget* widget = event->getWidget (); 329 | if (!widget) return; 330 | 331 | BAngrGUI* ui = dynamic_cast (widget->getMainWindow()); 332 | if (!ui) return; 333 | 334 | int controllerNr = -1; 335 | float value = nanf(""); 336 | 337 | // Identify controller 338 | for (int i = 0; i < NR_CONTROLLERS; ++i) 339 | { 340 | if (widget == ui->controllerWidgets[i]) 341 | { 342 | controllerNr = i; 343 | break; 344 | } 345 | } 346 | 347 | // Controllers 348 | if (controllerNr >= 0) 349 | { 350 | if (controllerNr == SPEED_TYPE) 351 | { 352 | value = ui->speedTypeCombobox.getValue() - 1.0f; 353 | if (value == RANDOM) ui->speedScreen.show(); 354 | else ui->speedScreen.hide(); 355 | } 356 | 357 | else if (controllerNr == SPIN_TYPE) 358 | { 359 | value = ui->spinTypeCombobox.getValue() - 1.0f; 360 | if (value == RANDOM) ui->spinScreen.show(); 361 | else ui->spinScreen.hide(); 362 | } 363 | 364 | else 365 | { 366 | // Range widgets: Update parent dials as callbacks are overwritten 367 | if (controllerNr == SPEED_RANGE) ui->speedDial.update(); 368 | if (controllerNr == SPIN_RANGE) ui->spinDial.update(); 369 | 370 | BWidgets::ValueableTyped* valueable = dynamic_cast*>(widget); 371 | if (valueable) value = valueable->getValue(); 372 | } 373 | 374 | if (!isnanf(value)) ui->write_function(ui->controller, CONTROLLERS + controllerNr, sizeof(float), 0, &value); 375 | } 376 | } 377 | 378 | void BAngrGUI::cursorDraggedCallback (BEvents::Event* event) 379 | { 380 | if (!event) return; 381 | Dot* widget = dynamic_cast(event->getWidget ()); 382 | if (!widget) return; 383 | BAngrGUI* ui = dynamic_cast (widget->getMainWindow()); 384 | if (!ui) return; 385 | if (widget != &ui->cursor) return; 386 | 387 | double x = std::min (std::max (ui->cursor.getPosition().x + 0.5 * ui->cursor.getWidth(), 400.0), 600.0); 388 | double y = std::min (std::max (ui->cursor.getPosition().y + 0.5 * ui->cursor.getHeight(), 180.0), 380.0); 389 | 390 | ui->cursor.moveTo (x - 0.5 * ui->cursor.getWidth(), y - 0.5 * ui->cursor.getHeight()); 391 | ui->sendCursor(); 392 | } 393 | 394 | void BAngrGUI::cursorReleasedCallback (BEvents::Event* event) 395 | { 396 | if (!event) return; 397 | Dot* widget = dynamic_cast (event->getWidget ()); 398 | if (!widget) return; 399 | BAngrGUI* ui = dynamic_cast (widget->getMainWindow()); 400 | if (!ui) return; 401 | if (widget != &ui->cursor) return; 402 | 403 | ui->sendCursorOff(); 404 | } 405 | 406 | void BAngrGUI::xregionClickedCallback (BEvents::Event* event) 407 | { 408 | char cmd[] = WWW_BROWSER_CMD; 409 | char param[] = XREGION_URL; 410 | char* argv[] = {cmd, param, NULL}; 411 | std::cerr << "BAngr.lv2#GUI: Call " << XREGION_URL << " for Airwindows XRegion.\n"; 412 | if (BUtilities::vsystem (argv) == -1) std::cerr << "BAngr.lv2#GUI: Couldn't fork.\n"; 413 | } 414 | 415 | void BAngrGUI::helpButtonClickedCallback (BEvents::Event* event) 416 | { 417 | char cmd[] = WWW_BROWSER_CMD; 418 | char param[] = HELP_URL; 419 | char* argv[] = {cmd, param, NULL}; 420 | std::cerr << "BAngr.lv2#GUI: Call " << HELP_URL << " for help.\n"; 421 | if (BUtilities::vsystem (argv) == -1) std::cerr << "BAngr.lv2#GUI: Couldn't fork.\n"; 422 | } 423 | 424 | void BAngrGUI::ytButtonClickedCallback (BEvents::Event* event) 425 | { 426 | char cmd[] = WWW_BROWSER_CMD; 427 | char param[] = YT_URL; 428 | char* argv[] = {cmd, param, NULL}; 429 | std::cerr << "BAngr.lv2#GUI: Call " << YT_URL << " for preview video.\n"; 430 | if (BUtilities::vsystem (argv) == -1) std::cerr << "BAngr.lv2#GUI: Couldn't fork.\n"; 431 | } 432 | 433 | static LV2UI_Handle instantiate (const LV2UI_Descriptor *descriptor, const char *plugin_uri, const char *bundle_path, 434 | LV2UI_Write_Function write_function, LV2UI_Controller controller, LV2UI_Widget *widget, 435 | const LV2_Feature *const *features) 436 | { 437 | PuglNativeView parentWindow = 0; 438 | 439 | if (strcmp(plugin_uri, BANGR_URI) != 0) 440 | { 441 | std::cerr << "BAngr.lv2#GUI: GUI does not support plugin with URI " << plugin_uri << std::endl; 442 | return NULL; 443 | } 444 | 445 | for (int i = 0; features[i]; ++i) 446 | { 447 | if (!strcmp(features[i]->URI, LV2_UI__parent)) parentWindow = reinterpret_cast (features[i]->data); 448 | } 449 | if (parentWindow == 0) std::cerr << "BAngr.lv2#GUI: No parent window.\n"; 450 | 451 | // New instance 452 | BAngrGUI* ui; 453 | try {ui = new BAngrGUI (bundle_path, features, parentWindow);} 454 | catch (std::exception& exc) 455 | { 456 | std::cerr << "BAngr.lv2#GUI: Instantiation failed. " << exc.what () << std::endl; 457 | return NULL; 458 | } 459 | 460 | ui->controller = controller; 461 | ui->write_function = write_function; 462 | *widget = (LV2UI_Widget) ui->getNativeView (); 463 | return (LV2UI_Handle) ui; 464 | } 465 | 466 | static void cleanup(LV2UI_Handle ui) 467 | { 468 | BAngrGUI* pluginGui = static_cast (ui); 469 | if (pluginGui) delete pluginGui; 470 | } 471 | 472 | static void portEvent(LV2UI_Handle ui, uint32_t port_index, uint32_t buffer_size, 473 | uint32_t format, const void* buffer) 474 | { 475 | BAngrGUI* pluginGui = static_cast (ui); 476 | if (pluginGui) pluginGui->portEvent(port_index, buffer_size, format, buffer); 477 | } 478 | 479 | static int callIdle (LV2UI_Handle ui) 480 | { 481 | BAngrGUI* pluginGui = static_cast (ui); 482 | if (pluginGui) pluginGui->handleEvents (); 483 | return 0; 484 | } 485 | 486 | static const LV2UI_Idle_Interface idle = {callIdle}; 487 | 488 | static const void* extensionData(const char* uri) 489 | { 490 | if (!strcmp(uri, LV2_UI__idleInterface)) return &idle; 491 | else return NULL; 492 | } 493 | 494 | static const LV2UI_Descriptor guiDescriptor = 495 | { 496 | BANGR_GUI_URI, 497 | instantiate, 498 | cleanup, 499 | portEvent, 500 | extensionData 501 | }; 502 | 503 | // LV2 Symbol Export 504 | LV2_SYMBOL_EXPORT const LV2UI_Descriptor *lv2ui_descriptor(uint32_t index) 505 | { 506 | switch (index) { 507 | case 0: return &guiDescriptor; 508 | default:return NULL; 509 | } 510 | } 511 | -------------------------------------------------------------------------------- /src/BAngrGUI.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 - 2023 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef BANGRGUI_HPP_ 22 | #define BANGRGUI_HPP_ 23 | 24 | #include "BWidgets/BWidgets/Draws/Oops/definitions.hpp" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "BWidgets/BStyles/Status.hpp" 31 | #include "BWidgets/BStyles/Types/Border.hpp" 32 | #include "BWidgets/BStyles/Types/Color.hpp" 33 | #include "BWidgets/BWidgets/Widget.hpp" 34 | #include "BWidgets/BWidgets/Window.hpp" 35 | #include "BWidgets/BWidgets/Knob.hpp" 36 | #include "BWidgets/BWidgets/Label.hpp" 37 | #include "BWidgets/BWidgets/ComboBox.hpp" 38 | #include "BWidgets/BWidgets/ValueHSlider.hpp" 39 | #include "BWidgets/BWidgets/Image.hpp" 40 | #include "BAngrDial.hpp" 41 | #include "BAngrRangeDial.hpp" 42 | #include "Dot.hpp" 43 | #include "Definitions.hpp" 44 | #include "Ports.hpp" 45 | #include "Urids.hpp" 46 | 47 | #ifndef LIMIT 48 | #define LIMIT(g , max) ((g) > (max) ? (max) : (g)) 49 | #endif 50 | 51 | #ifndef WWW_BROWSER_CMD 52 | #define WWW_BROWSER_CMD "x-www-browser" 53 | #endif 54 | 55 | #define XREGION_URL "http://www.airwindows.com/xregion/" 56 | #define HELP_URL "https://github.com/sjaehn/BAngr/blob/master/README.md" 57 | #define YT_URL "https://www.youtube.com/watch?v=-kWy_1UYazo" 58 | #define URID(x) (BURID(BANGR_GUI_URI x)) 59 | 60 | class BAngrGUI : public BWidgets::Window 61 | { 62 | public: 63 | BAngrGUI (const char *bundle_path, const LV2_Feature *const *features, PuglNativeView parentWindow); 64 | ~BAngrGUI (); 65 | void portEvent (uint32_t port_index, uint32_t buffer_size, uint32_t format, const void *buffer); 66 | void sendCursor (); 67 | void sendXCursor (); 68 | void sendYCursor (); 69 | void sendCursorOn (); 70 | void sendCursorOff (); 71 | virtual void onConfigureRequest (BEvents::Event* event) override; 72 | 73 | LV2UI_Controller controller; 74 | LV2UI_Write_Function write_function; 75 | 76 | 77 | private: 78 | static void valueChangedCallback (BEvents::Event* event); 79 | static void cursorDraggedCallback (BEvents::Event* event); 80 | static void cursorReleasedCallback (BEvents::Event* event); 81 | static void xregionClickedCallback (BEvents::Event* event); 82 | static void helpButtonClickedCallback (BEvents::Event* event); 83 | static void ytButtonClickedCallback (BEvents::Event* event); 84 | 85 | std::string pluginPath; 86 | 87 | LV2_Atom_Forge forge; 88 | BAngrURIs urids; 89 | LV2_URID_Map* map; 90 | // LV2_URID_Unmap* unmap; 91 | 92 | // Widgets 93 | BWidgets::Image mContainer; 94 | Dot cursor; 95 | BWidgets::Label poweredLabel; 96 | BWidgets::Button helpButton; 97 | BWidgets::Button ytButton; 98 | BWidgets::Knob bypassButton; 99 | BWidgets::Label bypassLabel; 100 | BAngrDial drywetDial; 101 | BWidgets::Label drywetLabel; 102 | BAngrRangeDial speedDial; 103 | BWidgets::Label speedLabel; 104 | BAngrRangeDial spinDial; 105 | BWidgets::Label spinLabel; 106 | BWidgets::Widget speedScreen; 107 | BWidgets::Label speedFlexLabel; 108 | BWidgets::ComboBox speedTypeCombobox; 109 | BWidgets::ValueHSlider speedAmountSlider; 110 | BWidgets::Widget spinScreen; 111 | BWidgets::Label spinFlexLabel; 112 | BWidgets::ComboBox spinTypeCombobox; 113 | BWidgets::ValueHSlider spinAmountSlider; 114 | 115 | struct Fx 116 | { 117 | BWidgets::Widget* container; 118 | std::array paramDials; 119 | std::array paramLabels; 120 | }; 121 | std::array fx; 122 | 123 | // Controllers 124 | std::array controllerWidgets; 125 | 126 | // Definition of styles 127 | BStyles::ColorMap fgColors = BStyles::ColorMap {{{1.0, 0.0, 0.0, 1.0}, {1.0, 0.3, 0.3, 1.0}, {0.7, 0.0, 0.0, 1.0}, {0.0, 0.0, 0.0, 0.0}}}; 128 | BStyles::ColorMap txColors = BStyles::ColorMap {{{0.8, 0.8, 0.8, 1.0}, {1.0, 1.0, 1.0, 1.0}, {0.5, 0.5, 0.5, 1.0}, {0.0, 0.0, 0.0, 0.0}}}; 129 | BStyles::ColorMap bgColors = BStyles::ColorMap {{{0.15, 0.15, 0.15, 1.0}, {0.3, 0.3, 0.3, 1.0}, {0.05, 0.05, 0.05, 1.0}, {0.0, 0.0, 0.0, 0.0}}}; 130 | BStyles::ColorMap noColors = BStyles::ColorMap {{{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}}}; 131 | 132 | BStyles::Border border = {{fgColors[BStyles::Status::normal], 1.0}, 0.0, 2.0, 0.0}; 133 | BStyles::Border menuBorder = {{noColors[BStyles::Status::normal], 1.0}, 0.0, 0.0, 0.0}; 134 | BStyles::Border menuBorder2 = {{bgColors[BStyles::Status::normal], 1.0}, 0.0, 0.0, 0.0}; 135 | BStyles::Border btBorder = BStyles::Border (BStyles::Line (bgColors[BStyles::Status::normal].illuminate (BStyles::Color::darkened), 1.0), 0.0, 0.0, 3.0); 136 | BStyles::Border labelBorder = {BStyles::noLine, 4.0, 0.0, 0.0}; 137 | BStyles::Fill widgetBg = BStyles::noFill; 138 | BStyles::Fill screenBg = BStyles::Fill (BStyles::Color ({0.04, 0.0, 0.0, 0.8})); 139 | BStyles::Font defaultFont = BStyles::Font 140 | ( 141 | "Sans", 142 | CAIRO_FONT_SLANT_NORMAL, 143 | CAIRO_FONT_WEIGHT_NORMAL, 144 | 12.0, 145 | BStyles::Font::TextAlign::center, 146 | BStyles::Font::TextVAlign::middle 147 | ); 148 | 149 | BStyles::Font smFont = BStyles::Font 150 | ( 151 | "Sans", 152 | CAIRO_FONT_SLANT_NORMAL, 153 | CAIRO_FONT_WEIGHT_NORMAL, 154 | 9.0, 155 | BStyles::Font::TextAlign::center, 156 | BStyles::Font::TextVAlign::middle 157 | ); 158 | 159 | BStyles::Font rFont = BStyles::Font 160 | ( 161 | "Sans", 162 | CAIRO_FONT_SLANT_NORMAL, 163 | CAIRO_FONT_WEIGHT_NORMAL, 164 | 12.0, 165 | BStyles::Font::TextAlign::right, 166 | BStyles::Font::TextVAlign::middle 167 | ); 168 | 169 | BStyles::Font lFont = BStyles::Font 170 | ( 171 | "Sans", 172 | CAIRO_FONT_SLANT_NORMAL, 173 | CAIRO_FONT_WEIGHT_NORMAL, 174 | 12.0, 175 | BStyles::Font::TextAlign::left, 176 | BStyles::Font::TextVAlign::middle 177 | ); 178 | 179 | BStyles::Theme theme = BStyles::Theme 180 | { 181 | // main 182 | { 183 | URID ("/main"), 184 | BStyles::Style 185 | ({ 186 | {BURID(BSTYLES_STYLEPROPERTY_BACKGROUND_URI), BUtilities::makeAny(widgetBg)}, 187 | {BURID(BSTYLES_STYLEPROPERTY_BORDER_URI), BUtilities::makeAny(BStyles::noBorder)} 188 | }) 189 | }, 190 | 191 | // screen 192 | { 193 | URID ("/screen"), 194 | BStyles::Style 195 | ({ 196 | {BURID(BSTYLES_STYLEPROPERTY_BACKGROUND_URI), BUtilities::makeAny(screenBg)}, 197 | {BURID(BSTYLES_STYLEPROPERTY_BORDER_URI), BUtilities::makeAny(BStyles::noBorder)} 198 | }) 199 | }, 200 | 201 | // button 202 | { 203 | URID ("/button"), 204 | BStyles::Style 205 | ({ 206 | {BURID(BSTYLES_STYLEPROPERTY_BACKGROUND_URI), BUtilities::makeAny({BStyles::Fill(fgColors[BStyles::Status::normal])})}, 207 | {BURID(BSTYLES_STYLEPROPERTY_BGCOLORS_URI), BUtilities::makeAny(fgColors)}, 208 | {BURID(BSTYLES_STYLEPROPERTY_BORDER_URI), BUtilities::makeAny(btBorder)} 209 | }) 210 | }, 211 | 212 | // button/label 213 | { 214 | URID ("/button/label"), 215 | BStyles::Style 216 | ({ 217 | {BURID(BSTYLES_STYLEPROPERTY_FONT_URI), BUtilities::makeAny(defaultFont)}, 218 | {BURID(BSTYLES_STYLEPROPERTY_TXCOLORS_URI), BUtilities::makeAny(bgColors)} 219 | }) 220 | }, 221 | 222 | // redbutton 223 | { 224 | URID ("/redbutton"), 225 | BStyles::Style 226 | ({ 227 | {BURID(BSTYLES_STYLEPROPERTY_BGCOLORS_URI), BUtilities::makeAny(bgColors)}, 228 | {BURID(BSTYLES_STYLEPROPERTY_FGCOLORS_URI), BUtilities::makeAny(BStyles::reds)} 229 | }) 230 | }, 231 | 232 | // halobutton 233 | { 234 | URID ("/halobutton"), 235 | BStyles::Style 236 | ({ 237 | {BURID(BSTYLES_STYLEPROPERTY_BACKGROUND_URI), BUtilities::makeAny({BStyles::noFill})}, 238 | {BURID(BSTYLES_STYLEPROPERTY_BGCOLORS_URI), BUtilities::makeAny(noColors)}, 239 | {BURID(BSTYLES_STYLEPROPERTY_BORDER_URI), BUtilities::makeAny(BStyles::noBorder)} 240 | }) 241 | }, 242 | 243 | // label 244 | { 245 | URID ("/label"), 246 | BStyles::Style 247 | ({ 248 | {BURID(BSTYLES_STYLEPROPERTY_FONT_URI), BUtilities::makeAny(defaultFont)}, 249 | {BURID(BSTYLES_STYLEPROPERTY_TXCOLORS_URI), BUtilities::makeAny(txColors)} 250 | }) 251 | }, 252 | 253 | // rlabel 254 | { 255 | URID ("/rlabel"), 256 | BStyles::Style 257 | ({ 258 | {BURID(BSTYLES_STYLEPROPERTY_FONT_URI), BUtilities::makeAny(rFont)}, 259 | {BURID(BSTYLES_STYLEPROPERTY_TXCOLORS_URI), BUtilities::makeAny(txColors)} 260 | }) 261 | }, 262 | 263 | // dot 264 | { 265 | URID ("/dot"), 266 | BStyles::Style 267 | ({ 268 | {BURID(BSTYLES_STYLEPROPERTY_FGCOLORS_URI), BUtilities::makeAny(txColors)} 269 | }) 270 | }, 271 | 272 | // dial 273 | { 274 | URID ("/dial"), 275 | BStyles::Style 276 | ({ 277 | {BURID(BSTYLES_STYLEPROPERTY_BGCOLORS_URI), BUtilities::makeAny(BStyles::darks)}, 278 | {BURID(BSTYLES_STYLEPROPERTY_FGCOLORS_URI), BUtilities::makeAny(fgColors)}, 279 | {URID ("/dial/label"), BUtilities::makeAny 280 | ( 281 | BStyles::Style 282 | { 283 | {BURID(BSTYLES_STYLEPROPERTY_FONT_URI), BUtilities::makeAny(smFont)}, 284 | {BURID(BSTYLES_STYLEPROPERTY_TXCOLORS_URI), BUtilities::makeAny(txColors)} 285 | } 286 | )} 287 | }) 288 | } 289 | 290 | }; 291 | }; 292 | 293 | #endif /* BANGRGUI_HPP_ */ -------------------------------------------------------------------------------- /src/BAngrRangeDial.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 - 2023 by Sven Jähnichen 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef BANGRRANGEDIAL_HPP_ 21 | #define BANGRRANGEDIAL_HPP_ 22 | 23 | #include "BAngrDial.hpp" 24 | #include "BWidgets/BEvents/Event.hpp" 25 | #include "BWidgets/BEvents/PointerEvent.hpp" 26 | #include "BWidgets/BStyles/Types/Color.hpp" 27 | #include "BWidgets/BWidgets/Dial.hpp" 28 | #include "BWidgets/BWidgets/Frame.hpp" 29 | #include "BWidgets/BWidgets/Supports/ValueableTyped.hpp" 30 | #include 31 | #include 32 | #include 33 | 34 | class BAngrRangeDial : public BAngrDial 35 | { 36 | public: 37 | BWidgets::Dial range; 38 | 39 | BAngrRangeDial (); 40 | BAngrRangeDial (const uint32_t urid, const std::string& title); 41 | BAngrRangeDial (const double value, const double range, const double min, const double max, double step = 0.0, 42 | uint32_t urid = BUTILITIES_URID_UNKNOWN_URID, std::string title = ""); 43 | BAngrRangeDial (const double x, const double y, const double width, const double height, 44 | const double value, const double range, const double min, const double max, double step = 0.0, 45 | std::function transferFunc = ValueTransferable::noTransfer, 46 | std::function reTransferFunc = ValueTransferable::noTransfer, 47 | std::function displayFunc = BAngrDial::valueToString, 48 | std::function reDisplayFunc = BAngrDial::stringToValue, 49 | uint32_t urid = BUTILITIES_URID_UNKNOWN_URID, std::string title = ""); 50 | 51 | virtual Widget* clone () const override; 52 | void copy (const BAngrRangeDial* that); 53 | virtual void setMin (const double& min) override; 54 | virtual void setMax (const double& max) override; 55 | virtual void setStep (const double& step) override; 56 | virtual void setRange (const double& min, const double& max) override; 57 | virtual void setRange (const double& min, const double& max, const double& step) override; 58 | virtual void update () override; 59 | virtual void onPointerDragged (BEvents::Event* event) override; 60 | virtual void onWheelScrolled (BEvents::Event* event) override; 61 | 62 | protected: 63 | static void rangeChangedCallback (BEvents::Event* event); 64 | virtual void draw () override; 65 | virtual void draw (const double x0, const double y0, const double width, const double height) override; 66 | virtual void draw (const BUtilities::Area<>& area) override; 67 | 68 | }; 69 | 70 | inline BAngrRangeDial::BAngrRangeDial () : 71 | BAngrRangeDial (0.0, 0.0, 0.0, 0.0, 72 | 0.0, 0.0, 0.0, 1.0, 0.0, 73 | ValueTransferable::noTransfer, ValueTransferable::noTransfer, 74 | BAngrDial::valueToString, BAngrDial::stringToValue, 75 | BUTILITIES_URID_UNKNOWN_URID, "") 76 | { 77 | 78 | } 79 | 80 | 81 | 82 | inline BAngrRangeDial::BAngrRangeDial (const uint32_t urid, const std::string& title) : 83 | BAngrRangeDial (0.0, 0.0, 0.0, 0.0, 84 | 0.0, 0.0, 0.0, 1.0, 0.0, 85 | ValueTransferable::noTransfer, ValueTransferable::noTransfer, 86 | BAngrDial::valueToString, BAngrDial::stringToValue, 87 | urid, title) 88 | { 89 | 90 | } 91 | 92 | inline BAngrRangeDial::BAngrRangeDial (const double value, const double range, const double min, const double max, double step, uint32_t urid, std::string title) : 93 | BAngrRangeDial (0.0, 0.0, 0.0, 0.0, 94 | value, range, min, max, step, 95 | ValueTransferable::noTransfer, ValueTransferable::noTransfer, 96 | BAngrDial::valueToString, BAngrDial::stringToValue, 97 | urid, title) 98 | { 99 | 100 | } 101 | 102 | inline BAngrRangeDial::BAngrRangeDial (const double x, const double y, const double width, const double height, 103 | const double value, const double range, const double min, const double max, double step, 104 | std::function transferFunc, 105 | std::function reTransferFunc, 106 | std::function displayFunc, 107 | std::function reDisplayFunc, 108 | uint32_t urid, std::string title) : 109 | BAngrDial (x, y, width, height, value, min, max, step, transferFunc, reTransferFunc, displayFunc, reDisplayFunc, urid, title), 110 | range (0, 0, 0, 0, range, 0, max - min, step) 111 | { 112 | this->range.hide(); 113 | this->range.setCallbackFunction(BEvents::Event::EventType::valueChangedEvent, rangeChangedCallback); 114 | add (&this->range); 115 | } 116 | 117 | inline BWidgets::Widget* BAngrRangeDial::clone () const 118 | { 119 | Widget* f = new BAngrRangeDial (urid_, title_); 120 | f->copy (this); 121 | return f; 122 | } 123 | 124 | inline void BAngrRangeDial::copy (const BAngrRangeDial* that) 125 | { 126 | range.copy (&that->range); 127 | BAngrDial::copy (that); 128 | } 129 | 130 | 131 | inline void BAngrRangeDial::setMin (const double& min) 132 | { 133 | range.setMin(min); 134 | BAngrDial::setMin(min); 135 | } 136 | inline void BAngrRangeDial::setMax (const double& max) 137 | { 138 | range.setMax(max); 139 | BAngrDial::setMax(max); 140 | } 141 | 142 | inline void BAngrRangeDial::setStep (const double& step) 143 | { 144 | range.setStep(step); 145 | BAngrDial::setStep(step); 146 | } 147 | 148 | inline void BAngrRangeDial::setRange (const double& min, const double& max) 149 | { 150 | range.setRange(min, max); 151 | BAngrDial::setRange(min, max); 152 | } 153 | 154 | inline void BAngrRangeDial::setRange (const double& min, const double& max, const double& step) 155 | { 156 | range.setRange(min, max, step); 157 | BAngrDial::setRange(min, max, step); 158 | } 159 | 160 | inline void BAngrRangeDial::update () 161 | { 162 | BWidgets::Label* f = dynamic_cast(focus_); 163 | if (f) 164 | { 165 | f->setText(getTitle() + ": " + std::to_string (this->getValue())); 166 | f->resize(); 167 | } 168 | 169 | const bool lv = label.isValueable(); 170 | label.setValueable (false); 171 | label.setText (display_ (getValue())); 172 | label.setValueable (lv); 173 | label.resize(); 174 | label.moveTo(label.center(), label.middle()); 175 | 176 | const double x0 = getXOffset (); 177 | const double y0 = getYOffset (); 178 | const double w = getEffectiveWidth (); 179 | const double h = getEffectiveHeight (); 180 | const double ext = std::min (w, h); 181 | const double xm = x0 + 0.5 * w; 182 | const double ym = y0 + 0.5 * h; 183 | scale_ = BUtilities::Area<> (xm - 0.4 * ext, ym - 0.4 * ext, 0.8 * ext, 0.8 * ext); 184 | Widget::update(); 185 | } 186 | 187 | inline void BAngrRangeDial::onPointerDragged (BEvents::Event* event) 188 | { 189 | BEvents::PointerEvent* pev = dynamic_cast (event); 190 | if (!pev) return; 191 | 192 | const double x0 = getXOffset (); 193 | const double y0 = getYOffset (); 194 | const double w = getEffectiveWidth (); 195 | const double h = getEffectiveHeight (); 196 | const double ext = std::min (w, h); 197 | const double xm = x0 + 0.5 * w; 198 | const double ym = y0 + 0.5 * h; 199 | const double doxm = pev->getOrigin().x - xm; 200 | const double doym = pev->getOrigin().y - ym; 201 | const double r = sqrt (doxm * doxm + doym * doym); 202 | 203 | // Inside dial arc: Forward event to dial 204 | if (r <= 0.4 * ext) BAngrDial::onPointerDragged(event); 205 | 206 | // Outside dial arc: Drag handles 207 | else 208 | { 209 | if (getEffectiveWidth() >= 1) 210 | { 211 | if (range.getStep() != 0.0) range.setValue (range.getValue() - pev->getDelta().y * range.getStep ()); 212 | else range.setValue (range.getValueFromRatio (range.getRatioFromValue (range.getValue()) - pev->getDelta().y / 213 | (0.5 * scale_.getWidth() * BWIDGETS_DEFAULT_DRAWARC_SIZE))); 214 | } 215 | Draggable::onPointerDragged (event); 216 | } 217 | } 218 | 219 | inline void BAngrRangeDial::onWheelScrolled (BEvents::Event* event) 220 | { 221 | BEvents::WheelEvent* wev = dynamic_cast (event); 222 | if (!wev) return; 223 | 224 | const double x0 = getXOffset (); 225 | const double y0 = getYOffset (); 226 | const double w = getEffectiveWidth (); 227 | const double h = getEffectiveHeight (); 228 | const double ext = std::min (w, h); 229 | const double xm = x0 + 0.5 * w; 230 | const double ym = y0 + 0.5 * h; 231 | const double doxm = wev->getPosition().x - xm; 232 | const double doym = wev->getPosition().y - ym; 233 | const double r = sqrt (doxm * doxm + doym * doym); 234 | 235 | // Inside dial arc: Forward event to dial 236 | if (r <= 0.4 * ext) BAngrDial::onWheelScrolled(event); 237 | 238 | // Outside dial arc: Scroll handles 239 | else 240 | { 241 | if (getEffectiveWidth() >= 1) 242 | { 243 | if (range.getStep() != 0.0) range.setValue (range.getValue() - wev->getDelta().y * range.getStep ()); 244 | else range.setValue (range.getValueFromRatio (range.getRatioFromValue (range.getValue()) - wev->getDelta().y / 245 | (0.5 * scale_.getWidth() * BWIDGETS_DEFAULT_DRAWARC_SIZE))); 246 | } 247 | Scrollable::onWheelScrolled (event); 248 | } 249 | } 250 | 251 | inline void BAngrRangeDial::rangeChangedCallback (BEvents::Event* event) 252 | { 253 | BEvents::ValueChangeTypedEvent* vev = dynamic_cast*>(event); 254 | if (!vev) return; 255 | 256 | BAngrDial* w = dynamic_cast(vev->getWidget()); 257 | if (!w) return; 258 | 259 | BAngrRangeDial* p = dynamic_cast(w->getParentWidget()); 260 | if (!p) return; 261 | 262 | p->update(); 263 | } 264 | 265 | inline void BAngrRangeDial::draw () 266 | { 267 | draw (0, 0, getWidth(), getHeight()); 268 | } 269 | 270 | inline void BAngrRangeDial::draw (const double x0, const double y0, const double width, const double height) 271 | { 272 | draw (BUtilities::Area<> (x0, y0, width, height)); 273 | } 274 | 275 | inline void BAngrRangeDial::draw (const BUtilities::Area<>& area) 276 | { 277 | if ((!cairoSurface()) || (cairo_surface_status (cairoSurface()) != CAIRO_STATUS_SUCCESS)) return; 278 | 279 | // Draw super class widget elements first 280 | BAngrDial::draw (area); 281 | 282 | const double x0 = getXOffset (); 283 | const double y0 = getYOffset (); 284 | const double h = getEffectiveHeight (); 285 | const double w = getEffectiveWidth (); 286 | const double d = (w < h ? w : h); 287 | const double xc = x0 + 0.5 * w; 288 | const double yc = y0 + 0.5 * h; 289 | 290 | // Draw scale only if it is not a null widget 291 | if (d >= 1) 292 | { 293 | cairo_t* cr = cairo_create (cairoSurface()); 294 | 295 | if (cairo_status (cr) == CAIRO_STATUS_SUCCESS) 296 | { 297 | // Limit cairo-drawing area 298 | cairo_rectangle (cr, area.getX (), area.getY (), area.getWidth (), area.getHeight ()); 299 | cairo_clip (cr); 300 | 301 | const double v1 = std::max (std::min (getValue() - range.getValue(), getMax()), getMin()); 302 | const double v2 = std::max (std::min (getValue() + range.getValue(), getMax()), getMin()); 303 | double rv1 = getRatioFromValue(v1); 304 | double rv2 = getRatioFromValue(v2); 305 | if (rv2 < rv1) std::swap (rv1, rv2); 306 | const double p1 = BWIDGETS_DEFAULT_DRAWARC_START + BWIDGETS_DEFAULT_DRAWARC_SIZE * rv1; 307 | const double p2 = BWIDGETS_DEFAULT_DRAWARC_START + BWIDGETS_DEFAULT_DRAWARC_SIZE * rv2; 308 | const BStyles::Color fgColor = BStyles::white; 309 | 310 | cairo_new_path (cr); 311 | 312 | // Arc 313 | cairo_set_source_rgba (cr, CAIRO_RGBA (fgColor)); 314 | cairo_set_line_width (cr, 0.0); 315 | cairo_arc (cr, xc, yc, 0.46 * d, p1, p2); 316 | cairo_arc_negative (cr, xc, yc , 0.48 * d, p2, p1); 317 | cairo_close_path (cr); 318 | cairo_fill (cr); 319 | 320 | // Arrows 321 | cairo_save (cr); 322 | 323 | cairo_translate (cr, xc, yc); 324 | cairo_rotate (cr, p1); 325 | cairo_move_to (cr, 0.5 * d, 0); 326 | cairo_rel_line_to (cr, -0.06 * d, 0); 327 | cairo_rel_line_to (cr, 0.03 * d, -0.04 * d); 328 | cairo_close_path (cr); 329 | cairo_fill (cr); 330 | 331 | cairo_restore (cr); 332 | cairo_translate (cr, xc, yc); 333 | cairo_rotate (cr, p2); 334 | cairo_move_to (cr, 0.5 * d, 0); 335 | cairo_rel_line_to (cr, -0.06 * d, 0); 336 | cairo_rel_line_to (cr, 0.03 * d, 0.04 * d); 337 | cairo_close_path (cr); 338 | cairo_fill (cr); 339 | } 340 | cairo_destroy (cr); 341 | } 342 | } 343 | 344 | 345 | #endif /* BANGRRANGEDIAL_HPP_ */ 346 | -------------------------------------------------------------------------------- /src/BAngr_Dictionary.data: -------------------------------------------------------------------------------- 1 | { 2 | { 3 | "Gain", 4 | { 5 | {"de_DE", "Verstärk."}, 6 | {"fr_FR", "Gain"} 7 | } 8 | }, 9 | 10 | { 11 | "First", 12 | { 13 | {"de_DE", "Erster"}, 14 | {"fr_FR", "Premier"} 15 | } 16 | }, 17 | 18 | { 19 | "Last", 20 | { 21 | {"de_DE", "Letzter"}, 22 | {"fr_FR", "Dernier"} 23 | } 24 | }, 25 | 26 | { 27 | "Nuke", 28 | { 29 | {"de_DE", "Nuke"}, 30 | {"fr_FR", "Atomiser"} 31 | } 32 | }, 33 | 34 | { 35 | "Mix", 36 | { 37 | {"de_DE", "Mix"}, 38 | {"fr_FR", "Mix"} 39 | } 40 | }, 41 | 42 | { 43 | "Pan", 44 | { 45 | {"de_DE", "Panorama"}, 46 | {"fr_FR", "Panoramique"} 47 | } 48 | }, 49 | 50 | { 51 | "Speed", 52 | { 53 | {"de_DE", "Geschwindigkeit"}, 54 | {"fr_FR", "Vitesse"} 55 | } 56 | }, 57 | 58 | { 59 | "Spin", 60 | { 61 | {"de_DE", "Drehung"}, 62 | {"fr_FR", "Rotation"} 63 | } 64 | }, 65 | 66 | { 67 | "Powered by Airwindows XRegion", 68 | { 69 | {"de_DE", "Powered by Airwindows XRegion"}, 70 | {"fr_FR", "Powered by Airwindows XRegion"} 71 | } 72 | }, 73 | 74 | { 75 | "Help", 76 | { 77 | {"de_DE", "Hilfe"}, 78 | {"fr_FR", "Aide"} 79 | } 80 | }, 81 | 82 | { 83 | "Preview", 84 | { 85 | {"de_DE", "Vorschau"}, 86 | {"fr_FR", "Prévisualisation"} 87 | } 88 | }, 89 | 90 | { 91 | "Bypass", 92 | { 93 | {"de_DE", "Bypass"}, 94 | {"fr_FR", "Activer"} 95 | } 96 | }, 97 | 98 | { 99 | "Dry/wet", 100 | { 101 | {"de_DE", "Dry/wet"}, 102 | {"fr_FR", "Dry/wet"} 103 | } 104 | }, 105 | 106 | { 107 | "Flexibility", 108 | { 109 | {"de_DE", "Flexibilität"}, 110 | {"fr_FR", "Flexibilité"} 111 | } 112 | }, 113 | 114 | { 115 | "Random", 116 | { 117 | {"de_DE", "Zufall"}, 118 | {"fr_FR", "Aléatoire"} 119 | } 120 | }, 121 | 122 | { 123 | "Level", 124 | { 125 | {"de_DE", "Lautstärke"}, 126 | {"fr_FR", "Volume"} 127 | } 128 | }, 129 | 130 | { 131 | "Lows", 132 | { 133 | {"de_DE", "Tiefen"}, 134 | {"fr_FR", "Basses"} 135 | } 136 | }, 137 | 138 | { 139 | "Mids", 140 | { 141 | {"de_DE", "Mitten"}, 142 | {"fr_FR", "Medium"} 143 | } 144 | }, 145 | 146 | { 147 | "Highs", 148 | { 149 | {"de_DE", "Höhen"}, 150 | {"fr_FR", "Aigüs"} 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/ButterworthBandPassFilter.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef BUTTERWORTHBANDPASSFILTER_HPP_ 22 | #define BUTTERWORTHBANDPASSFILTER_HPP_ 23 | 24 | #include "ButterworthLowPassFilter.hpp" 25 | #include "ButterworthHighPassFilter.hpp" 26 | 27 | class ButterworthBandPassFilter 28 | { 29 | public: 30 | ButterworthBandPassFilter (const double rate, const double lowCutoff, const double highCutoff, const int order) : 31 | lowpass (rate, highCutoff, order), 32 | highpass (rate, lowCutoff, order) 33 | { 34 | 35 | } 36 | 37 | void set (const double rate, const double lowCutoff, const double highCutoff, const int order) 38 | { 39 | lowpass.set (rate, highCutoff, order); 40 | highpass.set (rate, lowCutoff, order); 41 | } 42 | 43 | float process (const float input) {return highpass.process (lowpass.process (input));} 44 | 45 | float get () const {return highpass.get();} 46 | 47 | void clear() 48 | { 49 | lowpass.clear(); 50 | highpass.clear(); 51 | } 52 | 53 | 54 | protected: 55 | ButterworthLowPassFilter lowpass; 56 | ButterworthHighPassFilter highpass; 57 | }; 58 | 59 | #endif /* BUTTERWORTHBANDPASSFILTER_HPP_ */ 60 | -------------------------------------------------------------------------------- /src/ButterworthFilter.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef BUTTERWORTHFILTER_HPP_ 22 | #define BUTTERWORTHFILTER_HPP_ 23 | 24 | #include 25 | #include 26 | 27 | #define BUTTERWORTH_MAXORDER 16 28 | 29 | class ButterworthFilter 30 | { 31 | public: 32 | ButterworthFilter() : ButterworthFilter (0) {} 33 | 34 | ButterworthFilter (const int order) : 35 | order (order), 36 | o2 (order / 2), 37 | f1 (1) 38 | { 39 | coeff0.fill (0); 40 | coeff1.fill (0); 41 | coeff2.fill (0); 42 | clear(); 43 | } 44 | 45 | float process (const float input) 46 | { 47 | output = input; 48 | 49 | for (int i = 0; i < o2; ++i) 50 | { 51 | buffer0[i] = buffer1[i] * coeff1[i] + buffer2[i] * coeff2[i] + output; 52 | output = (buffer0[i] + buffer1[i] * f1 + buffer2[i]) * coeff0[i]; 53 | buffer2[i] = buffer1[i]; 54 | buffer1[i] = buffer0[i]; 55 | } 56 | 57 | return output; 58 | } 59 | 60 | float get() const {return output;} 61 | 62 | void clear() 63 | { 64 | buffer0.fill (0.0f); 65 | buffer1.fill (0.0f); 66 | buffer2.fill (0.0f); 67 | } 68 | 69 | 70 | protected: 71 | int order; 72 | int o2; 73 | std::array coeff0; 74 | std::array coeff1; 75 | std::array coeff2; 76 | float f1; 77 | std::array buffer0; 78 | std::array buffer1; 79 | std::array buffer2; 80 | float output; 81 | }; 82 | 83 | #endif /* BUTTERWORTHFILTER_HPP_ */ 84 | -------------------------------------------------------------------------------- /src/ButterworthHighPassFilter.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef BUTTERWORTHHIGHPASSFILTER_HPP_ 22 | #define BUTTERWORTHHIGHPASSFILTER_HPP_ 23 | 24 | #include "ButterworthFilter.hpp" 25 | 26 | class ButterworthHighPassFilter : public ButterworthFilter 27 | { 28 | public: 29 | ButterworthHighPassFilter (const double rate, const double cutoff, const int order) : 30 | ButterworthFilter (order) 31 | 32 | { 33 | set (rate, cutoff, order); 34 | } 35 | 36 | void set (const double rate, const double cutoff, const int order) 37 | { 38 | 39 | this->order = order; 40 | o2 = order / 2; 41 | f1 = -2; 42 | const double a = tan (M_PI * cutoff / rate); 43 | const double a2 = a * a; 44 | 45 | for (int i = 0; i < o2; ++i) 46 | { 47 | const double r = sin (M_PI * (2.0 * double (i) + 1.0) / (2.0 * double (order))); 48 | const double s = a2 + 2.0 * a * r + 1.0; 49 | coeff0[i] = 1.0 / s; 50 | coeff1[i] = 2.0 * (1.0 - a2) / s; 51 | coeff2[i] = -(a2 - 2.0 * a * r + 1.0) / s; 52 | } 53 | } 54 | }; 55 | 56 | #endif /* BUTTERWORTHHIGHPASSFILTER_HPP_ */ 57 | -------------------------------------------------------------------------------- /src/ButterworthLowPassFilter.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef BUTTERWORTHLOWPASSFILTER_HPP_ 22 | #define BUTTERWORTHLOWPASSFILTER_HPP_ 23 | 24 | #include "ButterworthFilter.hpp" 25 | 26 | class ButterworthLowPassFilter : public ButterworthFilter 27 | { 28 | public: 29 | ButterworthLowPassFilter (const double rate, const double cutoff, const int order) : 30 | ButterworthFilter (order) 31 | { 32 | set (rate, cutoff, order); 33 | } 34 | 35 | void set (const double rate, const double cutoff, const int order) 36 | { 37 | 38 | this->order = order; 39 | o2 = order / 2; 40 | f1 = 2; 41 | 42 | const double a = tan (M_PI * cutoff / rate); 43 | const double a2 = a * a; 44 | 45 | for (int i = 0; i < o2; ++i) 46 | { 47 | const double r = sin (M_PI * (2.0 * double (i) + 1.0) / (2.0 * double (order))); 48 | const double s = a2 + 2.0 * a * r + 1.0; 49 | coeff0[i] = a2 / s; 50 | coeff1[i] = 2.0 * (1.0 - a2) / s; 51 | coeff2[i] = -(a2 - 2.0 * a * r + 1.0) / s; 52 | } 53 | } 54 | 55 | }; 56 | 57 | #endif /* BUTTERWORTHLOWPASSFILTER_HPP_ */ 58 | -------------------------------------------------------------------------------- /src/ControllerLimits.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef CONTROLLERLIMITS_HPP_ 22 | #define CONTROLLERLIMITS_HPP_ 23 | 24 | #include "Limit.hpp" 25 | #include "Ports.hpp" 26 | 27 | const Limit controllerLimits [NR_CONTROLLERS] = 28 | { 29 | {0.0, 1.0, 1.0}, // Bypass 30 | {0.0, 1.0, 0.0}, // Dry/wet 31 | {0.0, 1.0, 0.0}, // Speed 32 | {0.0, 1.0, 0.0}, // Speed range 33 | {0.0, 4.0, 1.0}, // Speed type 34 | {0.0, 1.0, 0.0}, // Speed amount 35 | {-1.0, 1.0, 0.0}, // Spin 36 | {0.0, 2.0, 0.0}, // Spin range 37 | {0.0, 4.0, 1.0}, // Spin type 38 | {0.0, 1.0, 0.0}, // Spin amount 39 | {0.0, 1.0, 0.0}, // FX1: Gain 40 | {0.0, 1.0, 0.0}, // First 41 | {0.0, 1.0, 0.0}, // Last 42 | {0.0, 1.0, 0.0}, // Nuke 43 | {0.0, 1.0, 0.0}, // Mix 44 | {-1.0, 1.0, 0.0}, // Pan 45 | {0.0, 1.0, 0.0}, // FX2: Gain 46 | {0.0, 1.0, 0.0}, // First 47 | {0.0, 1.0, 0.0}, // Last 48 | {0.0, 1.0, 0.0}, // Nuke 49 | {0.0, 1.0, 0.0}, // Mix 50 | {-1.0, 1.0, 0.0}, // Pan 51 | {0.0, 1.0, 0.0}, // FX3: Gain 52 | {0.0, 1.0, 0.0}, // First 53 | {0.0, 1.0, 0.0}, // Last 54 | {0.0, 1.0, 0.0}, // Nuke 55 | {0.0, 1.0, 0.0}, // Mix 56 | {-1.0, 1.0, 0.0}, // Pan 57 | {0.0, 1.0, 0.0}, // FX4: Gain 58 | {0.0, 1.0, 0.0}, // First 59 | {0.0, 1.0, 0.0}, // Last 60 | {0.0, 1.0, 0.0}, // Nuke 61 | {0.0, 1.0, 0.0}, // Mix 62 | {-1.0, 1.0, 0.0} // Pan 63 | }; 64 | 65 | #endif /* CONTROLLERLIMITS_HPP_ */ -------------------------------------------------------------------------------- /src/Definitions.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef DEFINITIONS_HPP_ 22 | #define DEFINITIONS_HPP_ 23 | 24 | #define BANGR_URI "https://www.jahnichen.de/plugins/lv2/BAngr" 25 | #define BANGR_GUI_URI "https://www.jahnichen.de/plugins/lv2/BAngr#gui" 26 | 27 | #endif /* DEFINITIONS_HPP_ */ 28 | -------------------------------------------------------------------------------- /src/Dot.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Glitch effect sequencer LV2 plugin 3 | * 4 | * Copyright (C) 2021 - 2022 by Sven Jähnichen 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef DOT_HPP_ 21 | #define DOT_HPP_ 22 | 23 | #include "BWidgets/BStyles/Types/Color.hpp" 24 | #include "BWidgets/BWidgets/Frame.hpp" 25 | #include "BWidgets/BWidgets/Supports/Clickable.hpp" 26 | #include 27 | 28 | class Dot : public BWidgets::Frame, 29 | public BWidgets::Clickable 30 | { 31 | public: 32 | Dot () : Dot (0, 0, 0, 0, BUTILITIES_URID_UNKNOWN_URID, "") {} 33 | Dot (uint32_t urid = BUTILITIES_URID_UNKNOWN_URID, std::string title = "") : 34 | Dot (0, 0, 0, 0, urid, title) {} 35 | Dot (const double x, const double y, const double width, const double height, 36 | uint32_t urid = BUTILITIES_URID_UNKNOWN_URID, std::string title = "") : 37 | Frame (x, y, width, height, urid, title), 38 | BWidgets::Clickable() 39 | {} 40 | 41 | virtual Widget* clone () const override 42 | { 43 | Widget* f = new Dot (urid_, title_); 44 | f->copy (this); 45 | return f; 46 | } 47 | 48 | inline void copy (const Dot* that) 49 | { 50 | Clickable::operator= (*that); 51 | Frame::copy (that); 52 | } 53 | 54 | protected: 55 | virtual void draw (const BUtilities::Area<>& area) override 56 | { 57 | if ((!cairoSurface()) || (cairo_surface_status (cairoSurface()) != CAIRO_STATUS_SUCCESS)) return; 58 | 59 | // Draw super class widget elements first 60 | Widget::draw (area); 61 | 62 | const double x0 = getXOffset (); 63 | const double y0 = getYOffset (); 64 | const double h = getEffectiveHeight (); 65 | const double w = getEffectiveWidth (); 66 | const double d = (w < h ? w : h); 67 | const double xc = x0 + 0.5 * w; 68 | const double yc = y0 + 0.5 * h; 69 | 70 | // Draw scale only if it is not a null widget 71 | if (d > 0) 72 | { 73 | cairoplus_surface_clear (cairoSurface()); 74 | cairo_t* cr = cairo_create (cairoSurface()); 75 | 76 | if (cairo_status (cr) == CAIRO_STATUS_SUCCESS) 77 | { 78 | // Limit cairo-drawing area 79 | cairo_rectangle (cr, area.getX (), area.getY (), area.getWidth (), area.getHeight ()); 80 | cairo_clip (cr); 81 | 82 | BStyles::Color fg = getFgColors()[getStatus()]; 83 | fg.illuminate (BStyles::Color::normalLighted); 84 | 85 | cairo_set_line_width (cr, 0.0); 86 | cairo_set_source_rgba (cr, CAIRO_RGBA (fg)); 87 | cairo_arc (cr,xc, yc, 0.125 * d, 0.0, 2.0 * M_PI); 88 | cairo_close_path (cr); 89 | cairo_fill (cr); 90 | } 91 | cairo_destroy (cr); 92 | } 93 | } 94 | }; 95 | 96 | #endif /* DOT_HPP_ */ 97 | -------------------------------------------------------------------------------- /src/Limit.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef LIMIT_HPP_ 22 | #define LIMIT_HPP_ 23 | 24 | #include 25 | 26 | struct Limit 27 | { 28 | float min; 29 | float max; 30 | float step; 31 | 32 | float validate (float value) const 33 | { 34 | if (max <= min) return min; 35 | if (value <= min) return min; 36 | if (value >= max) return max; 37 | if (step == 0) return value; 38 | float newValue = (step > 0 ? min + round ((value - min) / step) * step : max - round ((max - value) / step) * step); 39 | return (newValue >= min ? (newValue <= max ? newValue : max) : min); 40 | } 41 | }; 42 | 43 | #endif /* LIMIT_HPP_ */ 44 | -------------------------------------------------------------------------------- /src/Ports.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef PORTS_HPP_ 22 | #define PORTS_HPP_ 23 | 24 | enum BAngrPortIndex 25 | { 26 | CONTROL = 0, 27 | NOTIFY = 1, 28 | AUDIO_IN_1 = 2, 29 | AUDIO_IN_2 = 3, 30 | AUDIO_OUT_1 = 4, 31 | AUDIO_OUT_2 = 5, 32 | 33 | CONTROLLERS = 6, 34 | BYPASS = 0, 35 | DRY_WET = 1, 36 | SPEED = 2, 37 | SPEED_RANGE = 3, 38 | SPEED_TYPE = 4, 39 | SPEED_AMOUNT= 5, 40 | SPIN = 6, 41 | SPIN_RANGE = 7, 42 | SPIN_TYPE = 8, 43 | SPIN_AMOUNT = 9, 44 | FX = 10, 45 | NR_FX = 4, 46 | 47 | PARAM_GAIN = 0, 48 | PARAM_FIRST = 1, 49 | PARAM_LAST = 2, 50 | PARAM_NUKE = 3, 51 | PARAM_MIX = 4, 52 | PARAM_PAN = 5, 53 | NR_PARAMS = 6, 54 | 55 | NR_CONTROLLERS = FX + NR_FX * NR_PARAMS 56 | }; 57 | 58 | enum BAngrFlexibilityIndex 59 | { 60 | RANDOM = 0, 61 | LEVEL = 1, 62 | LOWS = 2, 63 | MIDS = 3, 64 | HIGHS = 4, 65 | NR_FLEX = 5 66 | }; 67 | 68 | #endif /* PORTS_HPP_ */ 69 | -------------------------------------------------------------------------------- /src/Urids.hpp: -------------------------------------------------------------------------------- 1 | /* B.Angr 2 | * Dynamic distorted bandpass filter plugin 3 | * 4 | * Copyright (C) 2021 by Sven Jähnichen 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef URIDS_HPP_ 22 | #define URIDS_HPP_ 23 | 24 | #include 25 | #include 26 | #include 27 | #include "lv2/lv2plug.in/ns/ext/patch/patch.h" 28 | #include "Definitions.hpp" 29 | 30 | struct BAngrURIs 31 | { 32 | LV2_URID atom_URID; 33 | LV2_URID atom_Float; 34 | LV2_URID atom_Object; 35 | LV2_URID atom_Blank; 36 | LV2_URID atom_eventTransfer; 37 | LV2_URID patch_Set; 38 | LV2_URID patch_property; 39 | LV2_URID patch_value; 40 | LV2_URID bangr_cursorOn; 41 | LV2_URID bangr_cursorOff; 42 | LV2_URID bangr_xcursor; 43 | LV2_URID bangr_ycursor; 44 | }; 45 | 46 | inline void getURIs (LV2_URID_Map* m, BAngrURIs* uris) 47 | { 48 | uris->atom_URID = m->map(m->handle, LV2_ATOM__URID); 49 | uris->atom_Float = m->map(m->handle, LV2_ATOM__Float); 50 | uris->atom_Object = m->map(m->handle, LV2_ATOM__Object); 51 | uris->atom_Blank = m->map(m->handle, LV2_ATOM__Blank); 52 | uris->atom_eventTransfer = m->map(m->handle, LV2_ATOM__eventTransfer); 53 | uris->patch_Set = m->map(m->handle, LV2_PATCH__Set); 54 | uris->patch_property = m->map(m->handle, LV2_PATCH__property); 55 | uris->patch_value = m->map(m->handle, LV2_PATCH__value); 56 | uris->bangr_cursorOn = m->map(m->handle, BANGR_URI "#cursorOn"); 57 | uris->bangr_cursorOff = m->map(m->handle, BANGR_URI "#cursorOff"); 58 | uris->bangr_xcursor = m->map(m->handle, BANGR_URI "#xcursor"); 59 | uris->bangr_ycursor = m->map(m->handle, BANGR_URI "#ycursor"); 60 | } 61 | 62 | #endif /* URIDS_HPP_ */ 63 | --------------------------------------------------------------------------------