├── .gitignore ├── .gitattributes ├── visualize_zeroes.js ├── LICENSE ├── README.md └── Polyphase Oversampling - Comparisons.maxpat /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /visualize_zeroes.js: -------------------------------------------------------------------------------- 1 | // Declare a global variable for the buffer 2 | var myBuffer = new Buffer("visualize"); 3 | 4 | // Define epsilon for floating-point comparison 5 | var epsilon = 1e-10; //32bit is 1e-38 6 | 7 | // Function to count zero values in the buffer 8 | function countZeros() { 9 | var zeroCount = 0; 10 | var length = myBuffer.framecount(); // Assuming 1 channel buffer 11 | 12 | // Loop through each sample in the buffer 13 | for (var i = 0; i < length; i++) { 14 | var sampleValue = myBuffer.peek(0, i); 15 | 16 | // Check if sample value is practically zero 17 | if (Math.abs(sampleValue) < epsilon) { 18 | zeroCount++; 19 | } 20 | } 21 | 22 | // Output the count of zero values 23 | post("Number of zero values within epsilon: " + zeroCount + "\n"); 24 | } 25 | 26 | // Call countZeros function when bang received 27 | function bang() { 28 | countZeros(); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2023] [Robert Johannes Koster] 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Oversampling Techniques for Max For Live Devices 2 | 3 | ## Overview 4 | 5 | This repository showcases three oversampling examples in gen~ that can be utilised within Max For Live devices. I have worked extensively to try and optimize these as much as possible. The examples provided are a 4x FIR Oversampling, an optimized 3x FIR Oversampling, and a 2x IIR Oversampling method. All methods implement polyphase filtering and an 'ideal' compromise to the number of taps. 6 | 7 | ### 4x FIR Oversampling 8 | 9 | The most aliasing rejection and highest CPU usage. 9 samples latency, kaiser window (beta 7), cutoff approx 20khz. 10 | 11 | ### 3x FIR Oversampling (Optimized) 12 | 13 | Moderate aliasing rejection and CPU usage. 10 samples latency, kaiser window (beta 4), nyquist cutoff. It has been optimized by skipping near zero coefficients. 14 | 15 | ### 2x IIR Oversampling (Not Linear Phase) 16 | 17 | Moderate aliasing rejection and very low CPU usage. This would be highly recommended for scenarios where linear phase is of no importance. 18 | 19 | ## Utilization in Max For Live Devices 20 | 21 | Integrating these oversampling methods into Max For Live devices is straightforward if you are familiar with gen~. I plan to provide neat and tidy functions as source code with an example using these new assets in the near future. 22 | For now it is simply a Max Patcher with examples for comparison of aliasing rejection and CPU usage including notes on how you can adapt each method to your liking. 23 | 24 | By leveraging these oversampling techniques, developers can significantly improve the audio quality of their Max For Live devices with a choice of methods to best suit their specific needs and constraints. 25 | 26 | If you find this useful, consider donating; https://www.paypal.com/paypalme/groovmekanik 27 | 28 | Huge thanks to Wilson Ryan (aka quail on Discord) for his help and examples! 29 | 30 | ## Feedback / Improvements 31 | 32 | Let me know if theres anything that could be improved or you find something interesting when using these OS methods. Thanks! 33 | -------------------------------------------------------------------------------- /Polyphase Oversampling - Comparisons.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 5, 7 | "revision" : 6, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 117.0, 97.0, 1274.0, 827.0 ], 14 | "bglocked" : 0, 15 | "openinpresentation" : 0, 16 | "default_fontsize" : 12.0, 17 | "default_fontface" : 0, 18 | "default_fontname" : "Arial", 19 | "gridonopen" : 1, 20 | "gridsize" : [ 15.0, 15.0 ], 21 | "gridsnaponopen" : 1, 22 | "objectsnaponopen" : 1, 23 | "statusbarvisible" : 2, 24 | "toolbarvisible" : 1, 25 | "lefttoolbarpinned" : 0, 26 | "toptoolbarpinned" : 0, 27 | "righttoolbarpinned" : 0, 28 | "bottomtoolbarpinned" : 0, 29 | "toolbars_unpinned_last_save" : 0, 30 | "tallnewobj" : 0, 31 | "boxanimatetime" : 200, 32 | "enablehscroll" : 1, 33 | "enablevscroll" : 1, 34 | "devicewidth" : 0.0, 35 | "description" : "", 36 | "digest" : "", 37 | "tags" : "", 38 | "style" : "", 39 | "subpatcher_template" : "", 40 | "assistshowspatchername" : 0, 41 | "boxes" : [ { 42 | "box" : { 43 | "id" : "obj-32", 44 | "maxclass" : "newobj", 45 | "numinlets" : 1, 46 | "numoutlets" : 1, 47 | "outlettype" : [ "" ], 48 | "patcher" : { 49 | "fileversion" : 1, 50 | "appversion" : { 51 | "major" : 8, 52 | "minor" : 5, 53 | "revision" : 6, 54 | "architecture" : "x64", 55 | "modernui" : 1 56 | } 57 | , 58 | "classnamespace" : "box", 59 | "rect" : [ 952.0, 385.0, 640.0, 480.0 ], 60 | "bglocked" : 0, 61 | "openinpresentation" : 0, 62 | "default_fontsize" : 12.0, 63 | "default_fontface" : 0, 64 | "default_fontname" : "Arial", 65 | "gridonopen" : 1, 66 | "gridsize" : [ 15.0, 15.0 ], 67 | "gridsnaponopen" : 1, 68 | "objectsnaponopen" : 1, 69 | "statusbarvisible" : 2, 70 | "toolbarvisible" : 1, 71 | "lefttoolbarpinned" : 0, 72 | "toptoolbarpinned" : 0, 73 | "righttoolbarpinned" : 0, 74 | "bottomtoolbarpinned" : 0, 75 | "toolbars_unpinned_last_save" : 0, 76 | "tallnewobj" : 0, 77 | "boxanimatetime" : 200, 78 | "enablehscroll" : 1, 79 | "enablevscroll" : 1, 80 | "devicewidth" : 0.0, 81 | "description" : "", 82 | "digest" : "", 83 | "tags" : "", 84 | "style" : "", 85 | "subpatcher_template" : "", 86 | "assistshowspatchername" : 0, 87 | "visible" : 1, 88 | "boxes" : [ { 89 | "box" : { 90 | "id" : "obj-5", 91 | "maxclass" : "message", 92 | "numinlets" : 2, 93 | "numoutlets" : 1, 94 | "outlettype" : [ "" ], 95 | "patching_rect" : [ 94.0, 134.0, 91.0, 22.0 ], 96 | "text" : "cpumeasure $1" 97 | } 98 | 99 | } 100 | , { 101 | "box" : { 102 | "fontname" : "Arial", 103 | "fontsize" : 13.0, 104 | "id" : "obj-48", 105 | "maxclass" : "newobj", 106 | "numinlets" : 2, 107 | "numoutlets" : 1, 108 | "outlettype" : [ "bang" ], 109 | "patching_rect" : [ 224.333326041698456, 100.0, 78.0, 23.0 ], 110 | "text" : "qmetro 100" 111 | } 112 | 113 | } 114 | , { 115 | "box" : { 116 | "fontname" : "Arial", 117 | "fontsize" : 13.0, 118 | "id" : "obj-49", 119 | "maxclass" : "message", 120 | "numinlets" : 2, 121 | "numoutlets" : 1, 122 | "outlettype" : [ "" ], 123 | "patching_rect" : [ 224.333326041698456, 130.0, 51.0, 23.0 ], 124 | "text" : "getcpu" 125 | } 126 | 127 | } 128 | , { 129 | "box" : { 130 | "comment" : "", 131 | "id" : "obj-28", 132 | "index" : 1, 133 | "maxclass" : "inlet", 134 | "numinlets" : 0, 135 | "numoutlets" : 1, 136 | "outlettype" : [ "int" ], 137 | "patching_rect" : [ 131.166670041698467, 40.0, 30.0, 30.0 ] 138 | } 139 | 140 | } 141 | , { 142 | "box" : { 143 | "comment" : "", 144 | "id" : "obj-30", 145 | "index" : 1, 146 | "maxclass" : "outlet", 147 | "numinlets" : 1, 148 | "numoutlets" : 0, 149 | "patching_rect" : [ 131.166670041698467, 213.0, 30.0, 30.0 ] 150 | } 151 | 152 | } 153 | ], 154 | "lines" : [ { 155 | "patchline" : { 156 | "destination" : [ "obj-48", 0 ], 157 | "order" : 0, 158 | "source" : [ "obj-28", 0 ] 159 | } 160 | 161 | } 162 | , { 163 | "patchline" : { 164 | "destination" : [ "obj-5", 0 ], 165 | "order" : 1, 166 | "source" : [ "obj-28", 0 ] 167 | } 168 | 169 | } 170 | , { 171 | "patchline" : { 172 | "destination" : [ "obj-49", 0 ], 173 | "source" : [ "obj-48", 0 ] 174 | } 175 | 176 | } 177 | , { 178 | "patchline" : { 179 | "destination" : [ "obj-30", 0 ], 180 | "source" : [ "obj-49", 0 ] 181 | } 182 | 183 | } 184 | , { 185 | "patchline" : { 186 | "destination" : [ "obj-30", 0 ], 187 | "source" : [ "obj-5", 0 ] 188 | } 189 | 190 | } 191 | ] 192 | } 193 | , 194 | "patching_rect" : [ 86.666673958301544, 163.0, 125.0, 22.0 ], 195 | "saved_object_attributes" : { 196 | "description" : "", 197 | "digest" : "", 198 | "globalpatchername" : "", 199 | "tags" : "" 200 | } 201 | , 202 | "text" : "p measure-cpu-usage" 203 | } 204 | 205 | } 206 | , { 207 | "box" : { 208 | "bgcolor" : [ 0.215686274509804, 0.215686274509804, 0.215686274509804, 1.0 ], 209 | "id" : "obj-27", 210 | "linecount" : 3, 211 | "maxclass" : "comment", 212 | "numinlets" : 1, 213 | "numoutlets" : 0, 214 | "patching_rect" : [ 713.666674000000057, 569.0, 297.0, 47.0 ], 215 | "text" : "4x FIR case does use considerable CPU but is still applicable for use within a max for live device across numerous tracks within a live set.", 216 | "textcolor" : [ 1.0, 0.0, 0.0, 1.0 ] 217 | } 218 | 219 | } 220 | , { 221 | "box" : { 222 | "bgcolor" : [ 0.215686274509804, 0.215686274509804, 0.215686274509804, 1.0 ], 223 | "id" : "obj-26", 224 | "linecount" : 3, 225 | "maxclass" : "comment", 226 | "numinlets" : 1, 227 | "numoutlets" : 0, 228 | "patching_rect" : [ 713.666674000000057, 520.0, 297.0, 47.0 ], 229 | "text" : "3x FIR case uses considerably more CPU for minimal improvements in terms of aliasing, but is linear phase and highly optimized by skipping 'zeroes'", 230 | "textcolor" : [ 0.0, 1.0, 0.082352941176471, 1.0 ] 231 | } 232 | 233 | } 234 | , { 235 | "box" : { 236 | "bgcolor" : [ 0.0, 0.0, 0.0, 0.0 ], 237 | "id" : "obj-25", 238 | "linecount" : 2, 239 | "maxclass" : "comment", 240 | "numinlets" : 1, 241 | "numoutlets" : 0, 242 | "patching_rect" : [ 302.666673958301544, 795.0, 381.0, 33.0 ], 243 | "text" : "4x FIR oversampling - The least amount of aliasing and most attenuation near nyquist", 244 | "textcolor" : [ 1.0, 0.0, 0.0, 1.0 ] 245 | } 246 | 247 | } 248 | , { 249 | "box" : { 250 | "bgcolor" : [ 0.0, 0.0, 0.0, 0.0 ], 251 | "id" : "obj-21", 252 | "linecount" : 2, 253 | "maxclass" : "comment", 254 | "numinlets" : 1, 255 | "numoutlets" : 0, 256 | "patching_rect" : [ 302.666673958301544, 759.0, 381.0, 33.0 ], 257 | "text" : "3x FIR oversampling - aliases are lower or higher in dB than the 2x IIR case and has slightly more attenuation near nyquist", 258 | "textcolor" : [ 0.203921568627451, 1.0, 0.0, 1.0 ] 259 | } 260 | 261 | } 262 | , { 263 | "box" : { 264 | "bgcolor" : [ 0.0, 0.0, 0.0, 0.0 ], 265 | "id" : "obj-6", 266 | "linecount" : 2, 267 | "maxclass" : "comment", 268 | "numinlets" : 1, 269 | "numoutlets" : 0, 270 | "patching_rect" : [ 302.666673958301544, 723.5, 381.0, 33.0 ], 271 | "text" : "2x IIR oversampling - considerably less aliasing with majority of it being below 75dB", 272 | "textcolor" : [ 0.0, 0.83921568627451, 1.0, 1.0 ] 273 | } 274 | 275 | } 276 | , { 277 | "box" : { 278 | "bgcolor" : [ 0.0, 0.0, 0.0, 0.0 ], 279 | "id" : "obj-5", 280 | "maxclass" : "comment", 281 | "numinlets" : 1, 282 | "numoutlets" : 0, 283 | "patching_rect" : [ 302.666673958301544, 701.5, 381.0, 20.0 ], 284 | "text" : "Not oversampled - folds back into the signal numerous times", 285 | "textcolor" : [ 0.631372549019608, 0.631372549019608, 0.631372549019608, 1.0 ] 286 | } 287 | 288 | } 289 | , { 290 | "box" : { 291 | "bgcolor" : [ 0.0, 0.0, 0.0, 0.0 ], 292 | "id" : "obj-13", 293 | "maxclass" : "comment", 294 | "numinlets" : 1, 295 | "numoutlets" : 0, 296 | "patching_rect" : [ 302.666673958301544, 679.5, 381.0, 20.0 ], 297 | "text" : "Spectrumdraw~ shows the amplitude of the aliased partials.", 298 | "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ] 299 | } 300 | 301 | } 302 | , { 303 | "box" : { 304 | "id" : "obj-7", 305 | "maxclass" : "newobj", 306 | "numinlets" : 1, 307 | "numoutlets" : 1, 308 | "outlettype" : [ "signal" ], 309 | "patcher" : { 310 | "fileversion" : 1, 311 | "appversion" : { 312 | "major" : 8, 313 | "minor" : 5, 314 | "revision" : 6, 315 | "architecture" : "x64", 316 | "modernui" : 1 317 | } 318 | , 319 | "classnamespace" : "box", 320 | "rect" : [ 0.0, 0.0, 640.0, 480.0 ], 321 | "bglocked" : 0, 322 | "openinpresentation" : 0, 323 | "default_fontsize" : 12.0, 324 | "default_fontface" : 0, 325 | "default_fontname" : "Arial", 326 | "gridonopen" : 1, 327 | "gridsize" : [ 15.0, 15.0 ], 328 | "gridsnaponopen" : 1, 329 | "objectsnaponopen" : 1, 330 | "statusbarvisible" : 2, 331 | "toolbarvisible" : 1, 332 | "lefttoolbarpinned" : 0, 333 | "toptoolbarpinned" : 0, 334 | "righttoolbarpinned" : 0, 335 | "bottomtoolbarpinned" : 0, 336 | "toolbars_unpinned_last_save" : 0, 337 | "tallnewobj" : 0, 338 | "boxanimatetime" : 200, 339 | "enablehscroll" : 1, 340 | "enablevscroll" : 1, 341 | "devicewidth" : 0.0, 342 | "description" : "", 343 | "digest" : "", 344 | "tags" : "", 345 | "style" : "", 346 | "subpatcher_template" : "", 347 | "assistshowspatchername" : 0, 348 | "boxes" : [ { 349 | "box" : { 350 | "id" : "obj-26", 351 | "maxclass" : "newobj", 352 | "numinlets" : 1, 353 | "numoutlets" : 1, 354 | "outlettype" : [ "signal" ], 355 | "patching_rect" : [ 50.0, 100.0, 31.0, 22.0 ], 356 | "text" : "sig~" 357 | } 358 | 359 | } 360 | , { 361 | "box" : { 362 | "id" : "obj-3", 363 | "maxclass" : "newobj", 364 | "numinlets" : 2, 365 | "numoutlets" : 1, 366 | "outlettype" : [ "signal" ], 367 | "patching_rect" : [ 50.0, 135.0, 94.0, 22.0 ], 368 | "text" : "index~ visualize" 369 | } 370 | 371 | } 372 | , { 373 | "box" : { 374 | "comment" : "", 375 | "id" : "obj-5", 376 | "index" : 1, 377 | "maxclass" : "inlet", 378 | "numinlets" : 0, 379 | "numoutlets" : 1, 380 | "outlettype" : [ "" ], 381 | "patching_rect" : [ 50.0, 40.0, 30.0, 30.0 ] 382 | } 383 | 384 | } 385 | , { 386 | "box" : { 387 | "comment" : "", 388 | "id" : "obj-6", 389 | "index" : 1, 390 | "maxclass" : "outlet", 391 | "numinlets" : 1, 392 | "numoutlets" : 0, 393 | "patching_rect" : [ 50.0, 217.0, 30.0, 30.0 ] 394 | } 395 | 396 | } 397 | ], 398 | "lines" : [ { 399 | "patchline" : { 400 | "destination" : [ "obj-3", 0 ], 401 | "source" : [ "obj-26", 0 ] 402 | } 403 | 404 | } 405 | , { 406 | "patchline" : { 407 | "destination" : [ "obj-6", 0 ], 408 | "source" : [ "obj-3", 0 ] 409 | } 410 | 411 | } 412 | , { 413 | "patchline" : { 414 | "destination" : [ "obj-26", 0 ], 415 | "source" : [ "obj-5", 0 ] 416 | } 417 | 418 | } 419 | ] 420 | } 421 | , 422 | "patching_rect" : [ 528.333336979150772, 1023.0, 78.0, 22.0 ], 423 | "saved_object_attributes" : { 424 | "description" : "", 425 | "digest" : "", 426 | "globalpatchername" : "", 427 | "tags" : "" 428 | } 429 | , 430 | "text" : "p view-coeffs" 431 | } 432 | 433 | } 434 | , { 435 | "box" : { 436 | "id" : "obj-4", 437 | "linecount" : 4, 438 | "maxclass" : "comment", 439 | "numinlets" : 1, 440 | "numoutlets" : 0, 441 | "patching_rect" : [ 505.833336979150772, 879.0, 157.0, 60.0 ], 442 | "text" : "in codebox we can address the non zero coefficeints directly rather than leaving it to the 'for' loop", 443 | "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ] 444 | } 445 | 446 | } 447 | , { 448 | "box" : { 449 | "id" : "obj-2", 450 | "linecount" : 8, 451 | "maxclass" : "comment", 452 | "numinlets" : 1, 453 | "numoutlets" : 0, 454 | "patching_rect" : [ 63.333336979150772, 993.5, 155.0, 114.0 ], 455 | "text" : "the javascript below iterates through every coefficient in the 'visualize' buffer and checks if its below a threshold (epsilon) and prints the number of coefficients that meet this condition to the console", 456 | "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ] 457 | } 458 | 459 | } 460 | , { 461 | "box" : { 462 | "id" : "obj-1", 463 | "linecount" : 21, 464 | "maxclass" : "comment", 465 | "numinlets" : 1, 466 | "numoutlets" : 0, 467 | "patching_rect" : [ 713.666674000000057, 679.5, 599.0, 288.0 ], 468 | "text" : "MIT License\n\nCopyright (c) [2023] [Robert Johannes Koster]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE." 469 | } 470 | 471 | } 472 | , { 473 | "box" : { 474 | "id" : "obj-69", 475 | "linecount" : 4, 476 | "maxclass" : "message", 477 | "numinlets" : 2, 478 | "numoutlets" : 1, 479 | "outlettype" : [ "" ], 480 | "patching_rect" : [ 39.0, 766.0, 125.0, 62.0 ], 481 | "text" : ";\rmax launchbrowser https://robertkgm.gumroad.com/l/gmaclip" 482 | } 483 | 484 | } 485 | , { 486 | "box" : { 487 | "id" : "obj-66", 488 | "linecount" : 2, 489 | "maxclass" : "comment", 490 | "numinlets" : 1, 491 | "numoutlets" : 0, 492 | "patching_rect" : [ 39.0, 731.0, 261.0, 33.0 ], 493 | "text" : "Feel free to donate by purchasing one of my devices " 494 | } 495 | 496 | } 497 | , { 498 | "box" : { 499 | "id" : "obj-65", 500 | "linecount" : 3, 501 | "maxclass" : "comment", 502 | "numinlets" : 1, 503 | "numoutlets" : 0, 504 | "patching_rect" : [ 39.0, 679.5, 261.0, 47.0 ], 505 | "text" : "Polyphase Oversampling Examples\n(Robert Koster // Fixation Studios) 061123\nHuge thanks to Quail for his help and examples" 506 | } 507 | 508 | } 509 | , { 510 | "box" : { 511 | "id" : "obj-62", 512 | "maxclass" : "newobj", 513 | "numinlets" : 1, 514 | "numoutlets" : 1, 515 | "outlettype" : [ "" ], 516 | "patching_rect" : [ 118.0, 127.0, 70.0, 22.0 ], 517 | "text" : "loadmess 1" 518 | } 519 | 520 | } 521 | , { 522 | "box" : { 523 | "id" : "obj-61", 524 | "maxclass" : "newobj", 525 | "numinlets" : 3, 526 | "numoutlets" : 1, 527 | "outlettype" : [ "" ], 528 | "patcher" : { 529 | "fileversion" : 1, 530 | "appversion" : { 531 | "major" : 8, 532 | "minor" : 5, 533 | "revision" : 6, 534 | "architecture" : "x64", 535 | "modernui" : 1 536 | } 537 | , 538 | "classnamespace" : "box", 539 | "rect" : [ 59.0, 106.0, 640.0, 480.0 ], 540 | "bglocked" : 0, 541 | "openinpresentation" : 0, 542 | "default_fontsize" : 12.0, 543 | "default_fontface" : 0, 544 | "default_fontname" : "Arial", 545 | "gridonopen" : 1, 546 | "gridsize" : [ 15.0, 15.0 ], 547 | "gridsnaponopen" : 1, 548 | "objectsnaponopen" : 1, 549 | "statusbarvisible" : 2, 550 | "toolbarvisible" : 1, 551 | "lefttoolbarpinned" : 0, 552 | "toptoolbarpinned" : 0, 553 | "righttoolbarpinned" : 0, 554 | "bottomtoolbarpinned" : 0, 555 | "toolbars_unpinned_last_save" : 0, 556 | "tallnewobj" : 0, 557 | "boxanimatetime" : 200, 558 | "enablehscroll" : 1, 559 | "enablevscroll" : 1, 560 | "devicewidth" : 0.0, 561 | "description" : "", 562 | "digest" : "", 563 | "tags" : "", 564 | "style" : "", 565 | "subpatcher_template" : "", 566 | "assistshowspatchername" : 0, 567 | "boxes" : [ { 568 | "box" : { 569 | "id" : "obj-3", 570 | "maxclass" : "message", 571 | "numinlets" : 2, 572 | "numoutlets" : 1, 573 | "outlettype" : [ "" ], 574 | "patching_rect" : [ 192.0, 184.0, 61.0, 22.0 ], 575 | "text" : "peakreset" 576 | } 577 | 578 | } 579 | , { 580 | "box" : { 581 | "id" : "obj-1", 582 | "maxclass" : "newobj", 583 | "numinlets" : 2, 584 | "numoutlets" : 1, 585 | "outlettype" : [ "bang" ], 586 | "patching_rect" : [ 192.0, 143.0, 126.0, 22.0 ], 587 | "text" : "metro 3000 @active 1" 588 | } 589 | 590 | } 591 | , { 592 | "box" : { 593 | "id" : "obj-55", 594 | "maxclass" : "newobj", 595 | "numinlets" : 3, 596 | "numoutlets" : 1, 597 | "outlettype" : [ "" ], 598 | "patching_rect" : [ 55.333326041698456, 143.0, 74.0, 22.0 ], 599 | "text" : "pack 0. 0. 0." 600 | } 601 | 602 | } 603 | , { 604 | "box" : { 605 | "fontname" : "Arial", 606 | "fontsize" : 13.0, 607 | "id" : "obj-54", 608 | "maxclass" : "newobj", 609 | "numinlets" : 2, 610 | "numoutlets" : 2, 611 | "outlettype" : [ "", "" ], 612 | "patching_rect" : [ 200.0, 100.0, 66.0, 23.0 ], 613 | "text" : "route cpu" 614 | } 615 | 616 | } 617 | , { 618 | "box" : { 619 | "fontname" : "Arial", 620 | "fontsize" : 13.0, 621 | "id" : "obj-53", 622 | "maxclass" : "newobj", 623 | "numinlets" : 2, 624 | "numoutlets" : 2, 625 | "outlettype" : [ "", "" ], 626 | "patching_rect" : [ 132.0, 100.0, 66.0, 23.0 ], 627 | "text" : "route cpu" 628 | } 629 | 630 | } 631 | , { 632 | "box" : { 633 | "fontname" : "Arial", 634 | "fontsize" : 13.0, 635 | "id" : "obj-47", 636 | "maxclass" : "newobj", 637 | "numinlets" : 2, 638 | "numoutlets" : 2, 639 | "outlettype" : [ "", "" ], 640 | "patching_rect" : [ 50.0, 100.0, 66.0, 23.0 ], 641 | "text" : "route cpu" 642 | } 643 | 644 | } 645 | , { 646 | "box" : { 647 | "comment" : "", 648 | "id" : "obj-56", 649 | "index" : 1, 650 | "maxclass" : "inlet", 651 | "numinlets" : 0, 652 | "numoutlets" : 1, 653 | "outlettype" : [ "" ], 654 | "patching_rect" : [ 49.999952041698407, 40.0, 30.0, 30.0 ] 655 | } 656 | 657 | } 658 | , { 659 | "box" : { 660 | "comment" : "", 661 | "id" : "obj-57", 662 | "index" : 2, 663 | "maxclass" : "inlet", 664 | "numinlets" : 0, 665 | "numoutlets" : 1, 666 | "outlettype" : [ "" ], 667 | "patching_rect" : [ 131.999952041698407, 40.0, 30.0, 30.0 ] 668 | } 669 | 670 | } 671 | , { 672 | "box" : { 673 | "comment" : "", 674 | "id" : "obj-58", 675 | "index" : 3, 676 | "maxclass" : "inlet", 677 | "numinlets" : 0, 678 | "numoutlets" : 1, 679 | "outlettype" : [ "" ], 680 | "patching_rect" : [ 199.999952041698407, 40.0, 30.0, 30.0 ] 681 | } 682 | 683 | } 684 | , { 685 | "box" : { 686 | "comment" : "", 687 | "id" : "obj-59", 688 | "index" : 1, 689 | "maxclass" : "outlet", 690 | "numinlets" : 1, 691 | "numoutlets" : 0, 692 | "patching_rect" : [ 55.333326041698456, 225.0, 30.0, 30.0 ] 693 | } 694 | 695 | } 696 | ], 697 | "lines" : [ { 698 | "patchline" : { 699 | "destination" : [ "obj-3", 0 ], 700 | "source" : [ "obj-1", 0 ] 701 | } 702 | 703 | } 704 | , { 705 | "patchline" : { 706 | "destination" : [ "obj-59", 0 ], 707 | "source" : [ "obj-3", 0 ] 708 | } 709 | 710 | } 711 | , { 712 | "patchline" : { 713 | "destination" : [ "obj-55", 0 ], 714 | "source" : [ "obj-47", 0 ] 715 | } 716 | 717 | } 718 | , { 719 | "patchline" : { 720 | "destination" : [ "obj-55", 1 ], 721 | "source" : [ "obj-53", 0 ] 722 | } 723 | 724 | } 725 | , { 726 | "patchline" : { 727 | "destination" : [ "obj-55", 2 ], 728 | "source" : [ "obj-54", 0 ] 729 | } 730 | 731 | } 732 | , { 733 | "patchline" : { 734 | "destination" : [ "obj-59", 0 ], 735 | "source" : [ "obj-55", 0 ] 736 | } 737 | 738 | } 739 | , { 740 | "patchline" : { 741 | "destination" : [ "obj-47", 0 ], 742 | "source" : [ "obj-56", 0 ] 743 | } 744 | 745 | } 746 | , { 747 | "patchline" : { 748 | "destination" : [ "obj-53", 0 ], 749 | "source" : [ "obj-57", 0 ] 750 | } 751 | 752 | } 753 | , { 754 | "patchline" : { 755 | "destination" : [ "obj-54", 0 ], 756 | "source" : [ "obj-58", 0 ] 757 | } 758 | 759 | } 760 | ] 761 | } 762 | , 763 | "patching_rect" : [ 713.666674000000057, 221.666664659976959, 75.0, 22.0 ], 764 | "saved_object_attributes" : { 765 | "description" : "", 766 | "digest" : "", 767 | "globalpatchername" : "", 768 | "tags" : "" 769 | } 770 | , 771 | "text" : "p cpu-usage" 772 | } 773 | 774 | } 775 | , { 776 | "box" : { 777 | "id" : "obj-51", 778 | "maxclass" : "toggle", 779 | "numinlets" : 1, 780 | "numoutlets" : 1, 781 | "outlettype" : [ "int" ], 782 | "parameter_enable" : 0, 783 | "patching_rect" : [ 86.666673958301544, 127.0, 24.0, 24.0 ] 784 | } 785 | 786 | } 787 | , { 788 | "box" : { 789 | "id" : "obj-45", 790 | "linecount" : 3, 791 | "maxclass" : "comment", 792 | "numinlets" : 1, 793 | "numoutlets" : 0, 794 | "patching_rect" : [ 63.333336979150772, 881.0, 153.0, 47.0 ], 795 | "text" : "3x OS case (skipping near zeroe values for greater optimization)", 796 | "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ] 797 | } 798 | 799 | } 800 | , { 801 | "box" : { 802 | "bgcolor" : [ 1.0, 1.0, 1.0, 1.0 ], 803 | "id" : "obj-44", 804 | "linecount" : 4, 805 | "maxclass" : "comment", 806 | "numinlets" : 1, 807 | "numoutlets" : 0, 808 | "patching_rect" : [ 239.833336979150772, 27.666671574115753, 293.0, 60.0 ], 809 | "text" : "Things to play with for FIR cases are; \n- number of taps (and therefore loop iterations)\n- cutoff frequency \n- windowing" 810 | } 811 | 812 | } 813 | , { 814 | "box" : { 815 | "id" : "obj-11", 816 | "linecount" : 4, 817 | "maxclass" : "comment", 818 | "numinlets" : 1, 819 | "numoutlets" : 0, 820 | "patching_rect" : [ 239.833336979150772, 87.5, 293.0, 60.0 ], 821 | "text" : "in both FIR cases more taps/loop iterations yield slightly better aliasing rejection with approx 10 iterations being the point at which improvements decrease" 822 | } 823 | 824 | } 825 | , { 826 | "box" : { 827 | "id" : "obj-40", 828 | "linecount" : 3, 829 | "maxclass" : "comment", 830 | "numinlets" : 1, 831 | "numoutlets" : 0, 832 | "patching_rect" : [ 239.833336979150772, 149.5, 293.0, 47.0 ], 833 | "text" : "greater OS ratio and lower cutoff can yield slightly more aliasing rejection each (to a point - usually requires adjustments to windowing)" 834 | } 835 | 836 | } 837 | , { 838 | "box" : { 839 | "bgcolor" : [ 0.105882352941176, 0.572549019607843, 0.094117647058824, 1.0 ], 840 | "id" : "obj-36", 841 | "maxclass" : "newobj", 842 | "numinlets" : 1, 843 | "numoutlets" : 2, 844 | "outlettype" : [ "signal", "" ], 845 | "patcher" : { 846 | "fileversion" : 1, 847 | "appversion" : { 848 | "major" : 8, 849 | "minor" : 5, 850 | "revision" : 6, 851 | "architecture" : "x64", 852 | "modernui" : 1 853 | } 854 | , 855 | "classnamespace" : "dsp.gen", 856 | "rect" : [ 593.0, 106.0, 1082.0, 869.0 ], 857 | "bglocked" : 0, 858 | "openinpresentation" : 0, 859 | "default_fontsize" : 12.0, 860 | "default_fontface" : 0, 861 | "default_fontname" : "Arial", 862 | "gridonopen" : 1, 863 | "gridsize" : [ 15.0, 15.0 ], 864 | "gridsnaponopen" : 1, 865 | "objectsnaponopen" : 1, 866 | "statusbarvisible" : 2, 867 | "toolbarvisible" : 1, 868 | "lefttoolbarpinned" : 0, 869 | "toptoolbarpinned" : 0, 870 | "righttoolbarpinned" : 0, 871 | "bottomtoolbarpinned" : 0, 872 | "toolbars_unpinned_last_save" : 0, 873 | "tallnewobj" : 0, 874 | "boxanimatetime" : 200, 875 | "enablehscroll" : 1, 876 | "enablevscroll" : 1, 877 | "devicewidth" : 0.0, 878 | "description" : "", 879 | "digest" : "", 880 | "tags" : "", 881 | "style" : "", 882 | "subpatcher_template" : "", 883 | "assistshowspatchername" : 0, 884 | "boxes" : [ { 885 | "box" : { 886 | "id" : "obj-6", 887 | "maxclass" : "newobj", 888 | "numinlets" : 0, 889 | "numoutlets" : 2, 890 | "outlettype" : [ "", "" ], 891 | "patching_rect" : [ 843.0, 14.0, 138.0, 22.0 ], 892 | "text" : "buffer visualize visualize" 893 | } 894 | 895 | } 896 | , { 897 | "box" : { 898 | "code" : "//windowing functions (kaiser is adjustable)\nblackman(x,N) {\r\n\t//similar to kaiser (beta 9)\n\treturn 0.42 - 0.5*cos(2*pi*x/(N-1)) + 0.08*cos(4*pi*x/(N-1));\n}\r\nhann(x,N) {\r\n\t//similar to kaiser (beta 6)\r\n\treturn 0.5 * (1 - cos(2*pi*x/(N-1)));\r\n}\r\nhamming(x, N) {\r\n\t//similar to kaiser (beta 5) but with less ripple - most ideal in many cases\n return 0.54 - 0.46 * cos(2 * pi * x / (N - 1));\n}\r\nI0(x) {\r\n\t// Approximation of zeroth-order modified Bessel for Kaiser window\n sum = 1.0;\n term = 1.0;\n for (n = 1; n <= 10; n+=1) { //10 iterations (more = better approx. but made no measureable difference)\n term *= x*x / (4*n*n);\n sum += term;\n }\n return sum;\n}\nkaiser(i, N, beta) {\n // beta should be 0.1 - 10.0 (4.0 is the steepest with minor passband ripple)\r\n\t// this is good if filter cutoff is at nyquist (like 3x case)\n I0_beta = I0(beta);\n return I0(beta * sqrt(1 - pow((2*i/(N-1) - 1), 2))) / I0_beta;\n}\r\n\r\nsinc(x) {\r\n\tif (x != 0) { return sin(x*pi)/(x*pi); } \r\n\telse { return 1; }\r\n}\r\n// the impulse response (# of taps)\r\nData coeff(33); //23 taps after skipping 'zeroes'\r\n\r\n// the input history to convolve with (taps / srRatio)\r\nDelay input(11);\r\n\r\n//processed input for final convolution\r\nDelay processed1(11);\r\nDelay processed2(11);\r\nDelay processed3(11);\r\n\r\nsrRatio = 3; //OS amount - hard coded to 3\r\n\r\n//calculate coefficients\r\ntotal = 0;\r\nif (elapsed == 0) {\r\n\t//fc = filter cutoff / (samplerate * srRatio) -- set at nyquist to make use of zero coefficients\r\n\tfc = (samplerate/2) / (samplerate * srRatio);\r\n\tN = dim(coeff);\r\n\t//sinc with kaiser window\r\n\tfor(i=0;i", 901 | "fontsize" : 12.0, 902 | "id" : "obj-5", 903 | "maxclass" : "codebox", 904 | "numinlets" : 1, 905 | "numoutlets" : 1, 906 | "outlettype" : [ "" ], 907 | "patching_rect" : [ 50.0, 55.0, 931.0, 684.0 ] 908 | } 909 | 910 | } 911 | , { 912 | "box" : { 913 | "id" : "obj-1", 914 | "maxclass" : "newobj", 915 | "numinlets" : 0, 916 | "numoutlets" : 1, 917 | "outlettype" : [ "" ], 918 | "patching_rect" : [ 50.0, 14.0, 28.0, 22.0 ], 919 | "text" : "in 1" 920 | } 921 | 922 | } 923 | , { 924 | "box" : { 925 | "id" : "obj-4", 926 | "maxclass" : "newobj", 927 | "numinlets" : 1, 928 | "numoutlets" : 0, 929 | "patching_rect" : [ 50.0, 765.0, 35.0, 22.0 ], 930 | "text" : "out 1" 931 | } 932 | 933 | } 934 | ], 935 | "lines" : [ { 936 | "patchline" : { 937 | "destination" : [ "obj-5", 0 ], 938 | "source" : [ "obj-1", 0 ] 939 | } 940 | 941 | } 942 | , { 943 | "patchline" : { 944 | "destination" : [ "obj-4", 0 ], 945 | "source" : [ "obj-5", 0 ] 946 | } 947 | 948 | } 949 | ] 950 | } 951 | , 952 | "patching_rect" : [ 247.555557986100553, 221.666664659976959, 207.0, 22.0 ], 953 | "text" : "gen~ @title FIR3xOS @dumpoutlet 2" 954 | } 955 | 956 | } 957 | , { 958 | "box" : { 959 | "bgcolor" : [ 0.701960784313725, 0.196078431372549, 0.196078431372549, 1.0 ], 960 | "id" : "obj-8", 961 | "maxclass" : "newobj", 962 | "numinlets" : 1, 963 | "numoutlets" : 2, 964 | "outlettype" : [ "signal", "" ], 965 | "patcher" : { 966 | "fileversion" : 1, 967 | "appversion" : { 968 | "major" : 8, 969 | "minor" : 5, 970 | "revision" : 6, 971 | "architecture" : "x64", 972 | "modernui" : 1 973 | } 974 | , 975 | "classnamespace" : "dsp.gen", 976 | "rect" : [ 986.0, 192.0, 783.0, 869.0 ], 977 | "bglocked" : 0, 978 | "openinpresentation" : 0, 979 | "default_fontsize" : 12.0, 980 | "default_fontface" : 0, 981 | "default_fontname" : "Arial", 982 | "gridonopen" : 1, 983 | "gridsize" : [ 15.0, 15.0 ], 984 | "gridsnaponopen" : 1, 985 | "objectsnaponopen" : 1, 986 | "statusbarvisible" : 2, 987 | "toolbarvisible" : 1, 988 | "lefttoolbarpinned" : 0, 989 | "toptoolbarpinned" : 0, 990 | "righttoolbarpinned" : 0, 991 | "bottomtoolbarpinned" : 0, 992 | "toolbars_unpinned_last_save" : 0, 993 | "tallnewobj" : 0, 994 | "boxanimatetime" : 200, 995 | "enablehscroll" : 1, 996 | "enablevscroll" : 1, 997 | "devicewidth" : 0.0, 998 | "description" : "", 999 | "digest" : "", 1000 | "tags" : "", 1001 | "style" : "", 1002 | "subpatcher_template" : "", 1003 | "assistshowspatchername" : 0, 1004 | "boxes" : [ { 1005 | "box" : { 1006 | "code" : "//windowing functions (kaiser is adjustable)\nblackman(x,N) {\r\n\t//similar to kaiser (beta 9)\n\treturn 0.42 - 0.5*cos(2*pi*x/(N-1)) + 0.08*cos(4*pi*x/(N-1));\n}\r\nhann(x,N) {\r\n\t//similar to kaiser (beta 6)\r\n\treturn 0.5 * (1 - cos(2*pi*x/(N-1)));\r\n}\r\nhamming(x, N) {\r\n\t//similar to kaiser (beta 5) but with less ripple - most ideal in many cases\n return 0.54 - 0.46 * cos(2 * pi * x / (N - 1));\n}\r\nI0(x) {\r\n\t// Approximation of zeroth-order modified Bessel for Kaiser window\n sum = 1.0;\n term = 1.0;\n for (n = 1; n <= 10; n+=1) { //10 iterations (more = better approx. but made no measureable difference)\n term *= x*x / (4*n*n);\n sum += term;\n }\n return sum;\n}\nkaiser(i, N, beta) {\n // beta should be 0.1 - 10.0 (4.0 is the steepest with minor passband ripple)\r\n\t// this is good if filter cutoff is at nyquist (like 3x case)\n I0_beta = I0(beta);\n return I0(beta * sqrt(1 - pow((2*i/(N-1) - 1), 2))) / I0_beta;\n}\r\n\r\nsinc(x) {\r\n\tif (x != 0) { return sin(x*pi)/(x*pi); } \r\n\telse { return 1; }\r\n}\r\n// the impulse response (# of taps)\r\nData coeff(40);\r\n\r\n// the input history to convolve with (taps / srRatio)\r\nDelay input(10);\r\n\r\n//processed input for final convolution\r\nDelay processed1(10);\r\nDelay processed2(10);\r\nDelay processed3(10);\r\nDelay processed4(10);\r\n\r\nsrRatio = 4; // OS amount - hard coded to 4;\r\n\r\n//calculate coefficients\r\ntotal = 0;\r\nif (elapsed == 0) {\r\n\t//fc = cutoff frequency / (samplerate * srRatio) -- samplerate/2.4 = 20khz at 48khz\r\n\tfc = samplerate/2.4 / (samplerate * srRatio);\r\n\tN = dim(coeff);\r\n\t//sinc with kaiser window\r\n\tfor(i=0;i", 1009 | "fontsize" : 12.0, 1010 | "id" : "obj-5", 1011 | "maxclass" : "codebox", 1012 | "numinlets" : 1, 1013 | "numoutlets" : 1, 1014 | "outlettype" : [ "" ], 1015 | "patching_rect" : [ 50.0, 55.0, 931.0, 684.0 ] 1016 | } 1017 | 1018 | } 1019 | , { 1020 | "box" : { 1021 | "id" : "obj-1", 1022 | "maxclass" : "newobj", 1023 | "numinlets" : 0, 1024 | "numoutlets" : 1, 1025 | "outlettype" : [ "" ], 1026 | "patching_rect" : [ 50.0, 14.0, 28.0, 22.0 ], 1027 | "text" : "in 1" 1028 | } 1029 | 1030 | } 1031 | , { 1032 | "box" : { 1033 | "id" : "obj-4", 1034 | "maxclass" : "newobj", 1035 | "numinlets" : 1, 1036 | "numoutlets" : 0, 1037 | "patching_rect" : [ 50.0, 765.0, 35.0, 22.0 ], 1038 | "text" : "out 1" 1039 | } 1040 | 1041 | } 1042 | ], 1043 | "lines" : [ { 1044 | "patchline" : { 1045 | "destination" : [ "obj-5", 0 ], 1046 | "source" : [ "obj-1", 0 ] 1047 | } 1048 | 1049 | } 1050 | , { 1051 | "patchline" : { 1052 | "destination" : [ "obj-4", 0 ], 1053 | "source" : [ "obj-5", 0 ] 1054 | } 1055 | 1056 | } 1057 | ] 1058 | } 1059 | , 1060 | "patching_rect" : [ 39.0, 221.666664659976959, 207.0, 22.0 ], 1061 | "text" : "gen~ @title FIR4xOS @dumpoutlet 2" 1062 | } 1063 | 1064 | } 1065 | , { 1066 | "box" : { 1067 | "id" : "obj-60", 1068 | "linecount" : 2, 1069 | "maxclass" : "comment", 1070 | "numinlets" : 1, 1071 | "numoutlets" : 0, 1072 | "patching_rect" : [ 224.333336979150772, 1149.0, 279.0, 33.0 ], 1073 | "text" : "nyquist cf with odd taps generally contains, taps/srRatio -1, near zero value coefficients", 1074 | "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ], 1075 | "textjustification" : 1 1076 | } 1077 | 1078 | } 1079 | , { 1080 | "box" : { 1081 | "fontface" : 0, 1082 | "fontname" : "Arial", 1083 | "fontsize" : 12.0, 1084 | "id" : "obj-41", 1085 | "maxclass" : "number~", 1086 | "mode" : 2, 1087 | "numinlets" : 2, 1088 | "numoutlets" : 2, 1089 | "outlettype" : [ "signal", "float" ], 1090 | "patching_rect" : [ 528.333336979150772, 1059.5, 94.0, 22.0 ], 1091 | "sig" : 0.0 1092 | } 1093 | 1094 | } 1095 | , { 1096 | "box" : { 1097 | "id" : "obj-35", 1098 | "maxclass" : "button", 1099 | "numinlets" : 1, 1100 | "numoutlets" : 1, 1101 | "outlettype" : [ "bang" ], 1102 | "parameter_enable" : 0, 1103 | "patching_rect" : [ 79.333336979150772, 1121.5, 24.0, 24.0 ] 1104 | } 1105 | 1106 | } 1107 | , { 1108 | "box" : { 1109 | "id" : "obj-31", 1110 | "maxclass" : "newobj", 1111 | "numinlets" : 1, 1112 | "numoutlets" : 1, 1113 | "outlettype" : [ "" ], 1114 | "patching_rect" : [ 79.333336979150772, 1154.5, 121.0, 22.0 ], 1115 | "saved_object_attributes" : { 1116 | "filename" : "visualize_zeroes.js", 1117 | "parameter_enable" : 0 1118 | } 1119 | , 1120 | "text" : "js visualize_zeroes.js" 1121 | } 1122 | 1123 | } 1124 | , { 1125 | "box" : { 1126 | "id" : "obj-29", 1127 | "linecount" : 6, 1128 | "maxclass" : "comment", 1129 | "numinlets" : 1, 1130 | "numoutlets" : 0, 1131 | "patching_rect" : [ 528.333336979150772, 1089.666664659976959, 110.0, 87.0 ], 1132 | "text" : "starting from tap 1 (zero based) and counting in 3s all taps except the middle one are 'zeroes'", 1133 | "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ] 1134 | } 1135 | 1136 | } 1137 | , { 1138 | "box" : { 1139 | "id" : "obj-24", 1140 | "maxclass" : "live.dial", 1141 | "numinlets" : 1, 1142 | "numoutlets" : 2, 1143 | "outlettype" : [ "", "float" ], 1144 | "parameter_enable" : 1, 1145 | "patching_rect" : [ 528.333336979150772, 967.5, 41.0, 48.0 ], 1146 | "saved_attribute_attributes" : { 1147 | "textcolor" : { 1148 | "expression" : "" 1149 | } 1150 | , 1151 | "valueof" : { 1152 | "parameter_longname" : "live.dial", 1153 | "parameter_mmax" : 33.0, 1154 | "parameter_shortname" : "index", 1155 | "parameter_type" : 0, 1156 | "parameter_unitstyle" : 0 1157 | } 1158 | 1159 | } 1160 | , 1161 | "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ], 1162 | "varname" : "live.dial" 1163 | } 1164 | 1165 | } 1166 | , { 1167 | "box" : { 1168 | "buffername" : "visualize", 1169 | "id" : "obj-23", 1170 | "maxclass" : "waveform~", 1171 | "numinlets" : 5, 1172 | "numoutlets" : 6, 1173 | "outlettype" : [ "float", "float", "float", "float", "list", "" ], 1174 | "patching_rect" : [ 219.333336979150772, 937.0, 284.0, 210.0 ], 1175 | "setunit" : 1, 1176 | "vzoom" : 0.25 1177 | } 1178 | 1179 | } 1180 | , { 1181 | "box" : { 1182 | "id" : "obj-19", 1183 | "maxclass" : "newobj", 1184 | "numinlets" : 1, 1185 | "numoutlets" : 2, 1186 | "outlettype" : [ "float", "bang" ], 1187 | "patching_rect" : [ 280.333336979150772, 898.5, 163.0, 22.0 ], 1188 | "text" : "buffer~ visualize @samps 33" 1189 | } 1190 | 1191 | } 1192 | , { 1193 | "box" : { 1194 | "id" : "obj-14", 1195 | "linecount" : 10, 1196 | "maxclass" : "comment", 1197 | "numinlets" : 1, 1198 | "numoutlets" : 0, 1199 | "patching_rect" : [ 534.833336979150772, 27.666671574115753, 297.0, 141.0 ], 1200 | "text" : "Memory operations (of which there are more of in FIR cases as OS ratio increases) affects CPU considerably. Further OS amounts are possible but may yield diminishing returns when considering CPU usage.\n\nAll of these examples are a compromise between efficiency and aliasing rejection. Tuning FIR oversampling is highly reliant on the number of taps which is a major factor of CPU usage." 1201 | } 1202 | 1203 | } 1204 | , { 1205 | "box" : { 1206 | "bgcolor" : [ 0.482352941176471, 0.47843137254902, 0.47843137254902, 1.0 ], 1207 | "id" : "obj-9", 1208 | "maxclass" : "newobj", 1209 | "numinlets" : 1, 1210 | "numoutlets" : 1, 1211 | "outlettype" : [ "signal" ], 1212 | "patching_rect" : [ 664.666673958301544, 221.666664659976959, 39.0, 22.0 ], 1213 | "text" : "tanh~" 1214 | } 1215 | 1216 | } 1217 | , { 1218 | "box" : { 1219 | "bgcolor" : [ 0.215686274509804, 0.215686274509804, 0.215686274509804, 1.0 ], 1220 | "id" : "obj-12", 1221 | "linecount" : 3, 1222 | "maxclass" : "comment", 1223 | "numinlets" : 1, 1224 | "numoutlets" : 0, 1225 | "patching_rect" : [ 713.666674000000057, 471.0, 293.0, 47.0 ], 1226 | "text" : "2x IIR oversampling case is incredibly good for the computational cost and would be my recommendation if linear phase is of no concern", 1227 | "textcolor" : [ 0.0, 1.0, 0.909803921568627, 1.0 ] 1228 | } 1229 | 1230 | } 1231 | , { 1232 | "box" : { 1233 | "bgcolor" : [ 0.117647058823529, 0.498039215686275, 0.592156862745098, 1.0 ], 1234 | "id" : "obj-42", 1235 | "maxclass" : "newobj", 1236 | "numinlets" : 1, 1237 | "numoutlets" : 2, 1238 | "outlettype" : [ "signal", "" ], 1239 | "patcher" : { 1240 | "fileversion" : 1, 1241 | "appversion" : { 1242 | "major" : 8, 1243 | "minor" : 5, 1244 | "revision" : 6, 1245 | "architecture" : "x64", 1246 | "modernui" : 1 1247 | } 1248 | , 1249 | "classnamespace" : "dsp.gen", 1250 | "rect" : [ 634.0, 53.0, 1252.0, 976.0 ], 1251 | "bglocked" : 0, 1252 | "openinpresentation" : 0, 1253 | "default_fontsize" : 12.0, 1254 | "default_fontface" : 0, 1255 | "default_fontname" : "Arial", 1256 | "gridonopen" : 1, 1257 | "gridsize" : [ 15.0, 15.0 ], 1258 | "gridsnaponopen" : 1, 1259 | "objectsnaponopen" : 1, 1260 | "statusbarvisible" : 2, 1261 | "toolbarvisible" : 1, 1262 | "lefttoolbarpinned" : 0, 1263 | "toptoolbarpinned" : 0, 1264 | "righttoolbarpinned" : 0, 1265 | "bottomtoolbarpinned" : 0, 1266 | "toolbars_unpinned_last_save" : 3, 1267 | "tallnewobj" : 0, 1268 | "boxanimatetime" : 200, 1269 | "enablehscroll" : 1, 1270 | "enablevscroll" : 1, 1271 | "devicewidth" : 0.0, 1272 | "description" : "", 1273 | "digest" : "", 1274 | "tags" : "", 1275 | "style" : "", 1276 | "subpatcher_template" : "darkerPatch", 1277 | "assistshowspatchername" : 0, 1278 | "boxes" : [ { 1279 | "box" : { 1280 | "id" : "obj-8", 1281 | "maxclass" : "comment", 1282 | "numinlets" : 1, 1283 | "numoutlets" : 0, 1284 | "patching_rect" : [ 485.0, 379.0, 540.0, 20.0 ], 1285 | "text" : "I'll tidy all of this up later but for now it provides context for the other examples" 1286 | } 1287 | 1288 | } 1289 | , { 1290 | "box" : { 1291 | "id" : "obj-7", 1292 | "linecount" : 23, 1293 | "maxclass" : "comment", 1294 | "numinlets" : 1, 1295 | "numoutlets" : 0, 1296 | "patching_rect" : [ 485.0, 48.0, 646.0, 315.0 ], 1297 | "text" : "// Copyright 2023 Wilson Ryan.\n// \n// Author: Wilson Ryan (awryanz@gmail.com)\n// \n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n// \n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n// \n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n// \n// See http://creativecommons.org/licenses/MIT/ for more information." 1298 | } 1299 | 1300 | } 1301 | , { 1302 | "box" : { 1303 | "id" : "obj-5", 1304 | "maxclass" : "comment", 1305 | "numinlets" : 1, 1306 | "numoutlets" : 0, 1307 | "patching_rect" : [ 512.0, 937.0, 418.0, 20.0 ], 1308 | "text" : "very little difference between them - most attenuation selected" 1309 | } 1310 | 1311 | } 1312 | , { 1313 | "box" : { 1314 | "id" : "obj-4", 1315 | "linecount" : 13, 1316 | "maxclass" : "comment", 1317 | "numinlets" : 1, 1318 | "numoutlets" : 0, 1319 | "patching_rect" : [ 508.0, 483.0, 418.0, 181.0 ], 1320 | "text" : "9th order 2nd polynomial (0.292 stopband edge) middle ground\n\nDenominator Polynomials, path-0\n (a0 Z^2 + a1 Z^1 + a2)\n\n 1.000000000000000 0 0.089253711304174\n 1.000000000000000 0 0.575959051072397\n\nDenominator Polynomials, path-1\n (b0 Z^2 + b1 Z^1 + b2)\n\n 1.000000000000000 0 0.309716121757601\n 1.000000000000000 0 0.849978818907740" 1321 | } 1322 | 1323 | } 1324 | , { 1325 | "box" : { 1326 | "id" : "obj-3", 1327 | "linecount" : 13, 1328 | "maxclass" : "comment", 1329 | "numinlets" : 1, 1330 | "numoutlets" : 0, 1331 | "patching_rect" : [ 508.0, 717.0, 418.0, 181.0 ], 1332 | "text" : "9th order 2nd polynomial (0.284 stopband edge) book example - steep\n\nDenominator Polynomials, path-0\n (a0 Z^2 + a1 Z^1 + a2)\n\n 1.000000000000000 0 0.101467517561744\n 1.000000000000000 0 0.612422841852054\n\nDenominator Polynomials, path-1\n (b0 Z^2 + b1 Z^1 + b2)\n\n 1.000000000000000 0 0.342095596082430\n 1.000000000000000 0 0.867647439459746" 1333 | } 1334 | 1335 | } 1336 | , { 1337 | "box" : { 1338 | "id" : "obj-39", 1339 | "maxclass" : "newobj", 1340 | "numinlets" : 1, 1341 | "numoutlets" : 1, 1342 | "outlettype" : [ "" ], 1343 | "patching_rect" : [ 253.0, 446.0, 32.0, 22.0 ], 1344 | "text" : "tanh" 1345 | } 1346 | 1347 | } 1348 | , { 1349 | "box" : { 1350 | "id" : "obj-38", 1351 | "maxclass" : "newobj", 1352 | "numinlets" : 1, 1353 | "numoutlets" : 1, 1354 | "outlettype" : [ "" ], 1355 | "patching_rect" : [ 161.0, 452.0, 32.0, 22.0 ], 1356 | "text" : "tanh" 1357 | } 1358 | 1359 | } 1360 | , { 1361 | "box" : { 1362 | "id" : "obj-15", 1363 | "maxclass" : "newobj", 1364 | "numinlets" : 1, 1365 | "numoutlets" : 1, 1366 | "outlettype" : [ "" ], 1367 | "patching_rect" : [ 1429.0, 621.0, 32.0, 22.0 ], 1368 | "text" : "tanh" 1369 | } 1370 | 1371 | } 1372 | , { 1373 | "box" : { 1374 | "id" : "obj-19", 1375 | "linecount" : 13, 1376 | "maxclass" : "comment", 1377 | "numinlets" : 1, 1378 | "numoutlets" : 0, 1379 | "patching_rect" : [ 60.0, 483.0, 418.0, 181.0 ], 1380 | "text" : "9th order 2nd polynomial (0.3 stopband edge) most attenuation\n\nDenominator Polynomials, path-0\n (a0 Z^2 + a1 Z^1 + a2)\n\n 1.000000000000000 0 0.079866426202558\n 1.000000000000000 0 0.545323651182583\n\nDenominator Polynomials, path-1\n (b0 Z^2 + b1 Z^1 + b2)\n\n 1.000000000000000 0 0.283829344898100\n 1.000000000000000 0 0.834411891201724" 1381 | } 1382 | 1383 | } 1384 | , { 1385 | "box" : { 1386 | "code" : "allpass (x, a) {\r\n\tHistory x1, y1(0);\r\n\t\r\n\ty = x1 + (x - y1) * a;\r\n\t\r\n\tx1 = x;\r\n\ty1 = y;\r\n\t\r\n\treturn y;\t\r\n}\r\n\r\nHistory y1(0);\r\n\r\npath1_1 = allpass(in1, 0.283829344898100);\r\noutput1 = allpass(path1_1, 0.834411891201724);\r\n\r\npath2_1 = allpass(in2, 0.079866426202558);\r\noutput2 = allpass(path2_1, 0.545323651182583);\r\n\r\nout1 = (output1 + y1) * 0.5;\r\n\r\ny1 = output2;\r\n", 1387 | "fontface" : 0, 1388 | "fontname" : "", 1389 | "fontsize" : 12.0, 1390 | "id" : "obj-6", 1391 | "maxclass" : "codebox", 1392 | "numinlets" : 2, 1393 | "numoutlets" : 1, 1394 | "outlettype" : [ "" ], 1395 | "patching_rect" : [ 50.0, 725.0, 417.0, 407.0 ] 1396 | } 1397 | 1398 | } 1399 | , { 1400 | "box" : { 1401 | "code" : "allpass (x, a) {\r\n\tHistory x1, y1(0);\r\n\t\r\n\ty = x1 + (x - y1) * a;\r\n\t\r\n\tx1 = x;\r\n\ty1 = y;\r\n\t\r\n\treturn y;\t\r\n}\r\n\r\nHistory x1(0);\r\n\r\nx = in1;\r\n\r\npath1_1 = allpass(x1, 0.079866426202558);\r\nout1 = allpass(path1_1, 0.545323651182583);\r\n\r\npath2_1 = allpass(x, 0.283829344898100);\r\nout2 = allpass(path2_1, 0.834411891201724);\r\n\r\nx1 = x;", 1402 | "fontface" : 0, 1403 | "fontname" : "", 1404 | "fontsize" : 12.0, 1405 | "id" : "obj-2", 1406 | "maxclass" : "codebox", 1407 | "numinlets" : 1, 1408 | "numoutlets" : 2, 1409 | "outlettype" : [ "", "" ], 1410 | "patching_rect" : [ 50.0, 44.0, 417.0, 373.0 ] 1411 | } 1412 | 1413 | } 1414 | , { 1415 | "box" : { 1416 | "id" : "obj-51", 1417 | "maxclass" : "newobj", 1418 | "numinlets" : 1, 1419 | "numoutlets" : 0, 1420 | "patching_rect" : [ 50.0, 959.0, 35.0, 22.0 ], 1421 | "text" : "out 1" 1422 | } 1423 | 1424 | } 1425 | , { 1426 | "box" : { 1427 | "id" : "obj-1", 1428 | "maxclass" : "newobj", 1429 | "numinlets" : 0, 1430 | "numoutlets" : 1, 1431 | "outlettype" : [ "" ], 1432 | "patching_rect" : [ 50.0, 14.0, 28.0, 22.0 ], 1433 | "text" : "in 1" 1434 | } 1435 | 1436 | } 1437 | ], 1438 | "lines" : [ { 1439 | "patchline" : { 1440 | "destination" : [ "obj-2", 0 ], 1441 | "source" : [ "obj-1", 0 ] 1442 | } 1443 | 1444 | } 1445 | , { 1446 | "patchline" : { 1447 | "destination" : [ "obj-38", 0 ], 1448 | "source" : [ "obj-2", 0 ] 1449 | } 1450 | 1451 | } 1452 | , { 1453 | "patchline" : { 1454 | "destination" : [ "obj-39", 0 ], 1455 | "source" : [ "obj-2", 1 ] 1456 | } 1457 | 1458 | } 1459 | , { 1460 | "patchline" : { 1461 | "destination" : [ "obj-6", 0 ], 1462 | "source" : [ "obj-38", 0 ] 1463 | } 1464 | 1465 | } 1466 | , { 1467 | "patchline" : { 1468 | "destination" : [ "obj-6", 1 ], 1469 | "source" : [ "obj-39", 0 ] 1470 | } 1471 | 1472 | } 1473 | , { 1474 | "patchline" : { 1475 | "destination" : [ "obj-51", 0 ], 1476 | "source" : [ "obj-6", 0 ] 1477 | } 1478 | 1479 | } 1480 | ], 1481 | "accentcolor" : [ 0.2, 0.2, 0.2, 1.0 ], 1482 | "textcolor" : [ 0.925490196078431, 0.925490196078431, 0.925490196078431, 1.0 ], 1483 | "bgcolor" : [ 0.156862745098039, 0.156862745098039, 0.156862745098039, 1.0 ], 1484 | "editing_bgcolor" : [ 0.223529411764706, 0.223529411764706, 0.223529411764706, 1.0 ], 1485 | "saved_attribute_attributes" : { 1486 | "locked_bgcolor" : { 1487 | "expression" : "themecolor.live_lcd_bg" 1488 | } 1489 | 1490 | } 1491 | 1492 | } 1493 | , 1494 | "patching_rect" : [ 456.111115972201048, 221.666664659976959, 188.0, 22.0 ], 1495 | "text" : "gen~ @t IIR2xOS @dumpoutlet 2" 1496 | } 1497 | 1498 | } 1499 | , { 1500 | "box" : { 1501 | "id" : "obj-18", 1502 | "maxclass" : "newobj", 1503 | "numinlets" : 2, 1504 | "numoutlets" : 1, 1505 | "outlettype" : [ "signal" ], 1506 | "patching_rect" : [ 39.0, 90.0, 29.5, 22.0 ], 1507 | "text" : "+~" 1508 | } 1509 | 1510 | } 1511 | , { 1512 | "box" : { 1513 | "id" : "obj-17", 1514 | "maxclass" : "newobj", 1515 | "numinlets" : 2, 1516 | "numoutlets" : 1, 1517 | "outlettype" : [ "signal" ], 1518 | "patching_rect" : [ 134.0, 90.0, 30.0, 22.0 ], 1519 | "text" : "*~ 5" 1520 | } 1521 | 1522 | } 1523 | , { 1524 | "box" : { 1525 | "id" : "obj-16", 1526 | "maxclass" : "newobj", 1527 | "numinlets" : 2, 1528 | "numoutlets" : 1, 1529 | "outlettype" : [ "signal" ], 1530 | "patching_rect" : [ 134.0, 52.0, 63.0, 22.0 ], 1531 | "text" : "cycle~ 0.1" 1532 | } 1533 | 1534 | } 1535 | , { 1536 | "box" : { 1537 | "id" : "obj-15", 1538 | "maxclass" : "newobj", 1539 | "numinlets" : 1, 1540 | "numoutlets" : 1, 1541 | "outlettype" : [ "signal" ], 1542 | "patching_rect" : [ 39.0, 52.0, 58.0, 22.0 ], 1543 | "text" : "sig~ 990." 1544 | } 1545 | 1546 | } 1547 | , { 1548 | "box" : { 1549 | "amprange" : [ -120.0, 0.0 ], 1550 | "bgcolor" : [ 0.0, 0.0, 0.0, 1.0 ], 1551 | "color" : [ 1.0, 0.047058823529412, 0.047058823529412, 1.0 ], 1552 | "color2" : [ 0.0, 1.0, 0.0, 1.0 ], 1553 | "color3" : [ 0.019607843137255, 0.984313725490196, 1.0, 1.0 ], 1554 | "color4" : [ 1.0, 1.0, 1.0, 0.5 ], 1555 | "curvestyle" : 3, 1556 | "fftsize" : 5, 1557 | "fontface" : 0, 1558 | "fontname" : "Arial", 1559 | "fontsize" : 12.0, 1560 | "freqgrid" : 6, 1561 | "freqlabels" : 4, 1562 | "freqrange" : [ 40.0, 26000.0 ], 1563 | "gridcolor" : [ 0.4, 0.4, 0.4, 0.0 ], 1564 | "id" : "obj-10", 1565 | "interval" : 16.600000000000001, 1566 | "linearmode" : 1, 1567 | "maxclass" : "spectrumdraw~", 1568 | "numinlets" : 4, 1569 | "numoutlets" : 1, 1570 | "outlettype" : [ "" ], 1571 | "patching_rect" : [ 39.0, 263.666664659976959, 644.666673958301544, 392.000006914138794 ], 1572 | "peakhold" : 400.0, 1573 | "thickness" : 1.08, 1574 | "thickness2" : 1.08 1575 | } 1576 | 1577 | } 1578 | , { 1579 | "box" : { 1580 | "id" : "obj-38", 1581 | "maxclass" : "newobj", 1582 | "numinlets" : 2, 1583 | "numoutlets" : 1, 1584 | "outlettype" : [ "signal" ], 1585 | "patching_rect" : [ 39.0, 163.0, 30.0, 22.0 ], 1586 | "text" : "*~ 4" 1587 | } 1588 | 1589 | } 1590 | , { 1591 | "box" : { 1592 | "id" : "obj-20", 1593 | "maxclass" : "newobj", 1594 | "numinlets" : 2, 1595 | "numoutlets" : 1, 1596 | "outlettype" : [ "signal" ], 1597 | "patching_rect" : [ 39.0, 121.0, 37.0, 22.0 ], 1598 | "text" : "saw~" 1599 | } 1600 | 1601 | } 1602 | , { 1603 | "box" : { 1604 | "id" : "obj-39", 1605 | "maxclass" : "panel", 1606 | "numinlets" : 1, 1607 | "numoutlets" : 0, 1608 | "patching_rect" : [ 63.333336979150772, 879.0, 598.0, 310.0 ] 1609 | } 1610 | 1611 | } 1612 | , { 1613 | "box" : { 1614 | "angle" : 270.0, 1615 | "bgcolor" : [ 0.0, 0.0, 0.0, 1.0 ], 1616 | "id" : "obj-3", 1617 | "maxclass" : "panel", 1618 | "mode" : 0, 1619 | "numinlets" : 1, 1620 | "numoutlets" : 0, 1621 | "patching_rect" : [ 302.666673958301544, 679.5, 381.0, 148.5 ], 1622 | "proportion" : 0.5 1623 | } 1624 | 1625 | } 1626 | , { 1627 | "box" : { 1628 | "candicane2" : [ 0.094117647058824, 0.980392156862745, 0.0, 1.0 ], 1629 | "candicane3" : [ 0.0, 1.0, 0.980392156862745, 1.0 ], 1630 | "candycane" : 3, 1631 | "drawpeaks" : 1, 1632 | "id" : "obj-52", 1633 | "ignoreclick" : 1, 1634 | "maxclass" : "multislider", 1635 | "numinlets" : 1, 1636 | "numoutlets" : 2, 1637 | "outlettype" : [ "", "" ], 1638 | "parameter_enable" : 0, 1639 | "parameter_mappable" : 0, 1640 | "patching_rect" : [ 713.666674000000057, 284.0, 290.0, 185.0 ], 1641 | "setminmax" : [ 0.0, 0.100000001490116 ], 1642 | "setstyle" : 1, 1643 | "size" : 3, 1644 | "slidercolor" : [ 1.0, 0.0, 0.0, 1.0 ], 1645 | "spacing" : 20, 1646 | "thickness" : 1 1647 | } 1648 | 1649 | } 1650 | ], 1651 | "lines" : [ { 1652 | "patchline" : { 1653 | "destination" : [ "obj-18", 0 ], 1654 | "source" : [ "obj-15", 0 ] 1655 | } 1656 | 1657 | } 1658 | , { 1659 | "patchline" : { 1660 | "destination" : [ "obj-17", 0 ], 1661 | "source" : [ "obj-16", 0 ] 1662 | } 1663 | 1664 | } 1665 | , { 1666 | "patchline" : { 1667 | "destination" : [ "obj-18", 1 ], 1668 | "source" : [ "obj-17", 0 ] 1669 | } 1670 | 1671 | } 1672 | , { 1673 | "patchline" : { 1674 | "destination" : [ "obj-20", 0 ], 1675 | "source" : [ "obj-18", 0 ] 1676 | } 1677 | 1678 | } 1679 | , { 1680 | "patchline" : { 1681 | "destination" : [ "obj-38", 0 ], 1682 | "source" : [ "obj-20", 0 ] 1683 | } 1684 | 1685 | } 1686 | , { 1687 | "patchline" : { 1688 | "destination" : [ "obj-7", 0 ], 1689 | "source" : [ "obj-24", 0 ] 1690 | } 1691 | 1692 | } 1693 | , { 1694 | "patchline" : { 1695 | "destination" : [ "obj-36", 0 ], 1696 | "order" : 1, 1697 | "source" : [ "obj-32", 0 ] 1698 | } 1699 | 1700 | } 1701 | , { 1702 | "patchline" : { 1703 | "destination" : [ "obj-42", 0 ], 1704 | "order" : 0, 1705 | "source" : [ "obj-32", 0 ] 1706 | } 1707 | 1708 | } 1709 | , { 1710 | "patchline" : { 1711 | "destination" : [ "obj-8", 0 ], 1712 | "order" : 2, 1713 | "source" : [ "obj-32", 0 ] 1714 | } 1715 | 1716 | } 1717 | , { 1718 | "patchline" : { 1719 | "destination" : [ "obj-31", 0 ], 1720 | "source" : [ "obj-35", 0 ] 1721 | } 1722 | 1723 | } 1724 | , { 1725 | "patchline" : { 1726 | "destination" : [ "obj-10", 1 ], 1727 | "source" : [ "obj-36", 0 ] 1728 | } 1729 | 1730 | } 1731 | , { 1732 | "patchline" : { 1733 | "destination" : [ "obj-61", 1 ], 1734 | "source" : [ "obj-36", 1 ] 1735 | } 1736 | 1737 | } 1738 | , { 1739 | "patchline" : { 1740 | "destination" : [ "obj-36", 0 ], 1741 | "order" : 2, 1742 | "source" : [ "obj-38", 0 ] 1743 | } 1744 | 1745 | } 1746 | , { 1747 | "patchline" : { 1748 | "destination" : [ "obj-42", 0 ], 1749 | "order" : 1, 1750 | "source" : [ "obj-38", 0 ] 1751 | } 1752 | 1753 | } 1754 | , { 1755 | "patchline" : { 1756 | "destination" : [ "obj-8", 0 ], 1757 | "order" : 3, 1758 | "source" : [ "obj-38", 0 ] 1759 | } 1760 | 1761 | } 1762 | , { 1763 | "patchline" : { 1764 | "destination" : [ "obj-9", 0 ], 1765 | "order" : 0, 1766 | "source" : [ "obj-38", 0 ] 1767 | } 1768 | 1769 | } 1770 | , { 1771 | "patchline" : { 1772 | "destination" : [ "obj-10", 2 ], 1773 | "source" : [ "obj-42", 0 ] 1774 | } 1775 | 1776 | } 1777 | , { 1778 | "patchline" : { 1779 | "destination" : [ "obj-61", 2 ], 1780 | "source" : [ "obj-42", 1 ] 1781 | } 1782 | 1783 | } 1784 | , { 1785 | "patchline" : { 1786 | "destination" : [ "obj-32", 0 ], 1787 | "source" : [ "obj-51", 0 ] 1788 | } 1789 | 1790 | } 1791 | , { 1792 | "patchline" : { 1793 | "destination" : [ "obj-52", 0 ], 1794 | "source" : [ "obj-61", 0 ] 1795 | } 1796 | 1797 | } 1798 | , { 1799 | "patchline" : { 1800 | "destination" : [ "obj-51", 0 ], 1801 | "source" : [ "obj-62", 0 ] 1802 | } 1803 | 1804 | } 1805 | , { 1806 | "patchline" : { 1807 | "destination" : [ "obj-41", 0 ], 1808 | "source" : [ "obj-7", 0 ] 1809 | } 1810 | 1811 | } 1812 | , { 1813 | "patchline" : { 1814 | "destination" : [ "obj-10", 0 ], 1815 | "source" : [ "obj-8", 0 ] 1816 | } 1817 | 1818 | } 1819 | , { 1820 | "patchline" : { 1821 | "destination" : [ "obj-61", 0 ], 1822 | "source" : [ "obj-8", 1 ] 1823 | } 1824 | 1825 | } 1826 | , { 1827 | "patchline" : { 1828 | "destination" : [ "obj-10", 3 ], 1829 | "source" : [ "obj-9", 0 ] 1830 | } 1831 | 1832 | } 1833 | ], 1834 | "parameters" : { 1835 | "obj-24" : [ "live.dial", "index", 0 ], 1836 | "parameterbanks" : { 1837 | "0" : { 1838 | "index" : 0, 1839 | "name" : "", 1840 | "parameters" : [ "-", "-", "-", "-", "-", "-", "-", "-" ] 1841 | } 1842 | 1843 | } 1844 | , 1845 | "inherited_shortname" : 1 1846 | } 1847 | , 1848 | "dependency_cache" : [ { 1849 | "name" : "spectrumdraw~.mxo", 1850 | "type" : "iLaX" 1851 | } 1852 | , { 1853 | "name" : "visualize_zeroes.js", 1854 | "bootpath" : "~/Documents/GitHub/m4l-oversampling", 1855 | "patcherrelativepath" : ".", 1856 | "type" : "TEXT", 1857 | "implicit" : 1 1858 | } 1859 | ], 1860 | "autosave" : 0, 1861 | "boxgroups" : [ { 1862 | "boxes" : [ "obj-3", "obj-21", "obj-25", "obj-6", "obj-5", "obj-13" ] 1863 | } 1864 | , { 1865 | "boxes" : [ "obj-39", "obj-29", "obj-23", "obj-60", "obj-41", "obj-7", "obj-24", "obj-2", "obj-31", "obj-4", "obj-45", "obj-19", "obj-35" ] 1866 | } 1867 | ] 1868 | } 1869 | 1870 | } 1871 | --------------------------------------------------------------------------------