├── examples ├── drumloop.wav ├── simple.maxpat ├── midside.maxpat ├── sdcard-minimal.maxpat └── multi_app.maxpat ├── .gitmodules ├── media └── oopsy_noise_engineering_versio.png ├── .gitignore ├── install.sh ├── package-info.json ├── init └── oopsy-objectmappings.txt ├── source ├── seed.bluemchen.json ├── test.sh ├── seed.nehcmeulb.json ├── seed.pod.json ├── daisy.pod.json ├── seed.versio.json ├── readme.md ├── daisy.patch.json ├── gen_dsp │ ├── genlib_exportfunctions.h │ └── genlib.h ├── daisy.petal.json ├── daisy.versio.json ├── daisy.patch_sm.json ├── changelog.md ├── daisy.field.json └── genlib_daisy.cpp ├── javascript ├── oopsy.node4max.js └── oopsy.snoop.js ├── LICENSE ├── code ├── oopsy.suggestions.gendsp ├── oopsy.gate.trig.gendsp ├── oopsy.ctrl.smooth2.gendsp ├── oopsy.cv2hz.gendsp ├── oopsy.gate.min.gendsp ├── oopsy.ctrl.smooth3.gendsp └── oopsy.midi.format.gendsp ├── README.md ├── help └── oopsy.maxhelp └── templates ├── oopsy_bluemchen.maxpat └── oopsy_nehcmeulb.maxpat /examples/drumloop.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-smith/oopsy/HEAD/examples/drumloop.wav -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "source/libdaisy"] 2 | path = source/libdaisy 3 | url = https://github.com/electro-smith/libDaisy.git 4 | -------------------------------------------------------------------------------- /media/oopsy_noise_engineering_versio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/electro-smith/oopsy/HEAD/media/oopsy_noise_engineering_versio.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | gen_dsp/ 3 | build/ 4 | source/build* 5 | notes/ 6 | graham/ 7 | examples/*.cpp 8 | examples/*.h 9 | examples/*.json 10 | help/*.cpp 11 | help/*.h 12 | help/*.json 13 | templates/*.cpp 14 | templates/*.h 15 | templates/*.json -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | start_dir=$PWD 3 | 4 | echo $start_dir 5 | 6 | echo "get submodules" 7 | git submodule update --init --recursive 8 | 9 | echo "rebuilding everything. . . " 10 | echo "only errors, and warnings will output. . . " 11 | echo "-------------------" 12 | sleep 1 13 | 14 | echo "rebuilding libdaisy" 15 | cd source 16 | cd libdaisy 17 | make clean | grep "warningr:\|error:" 18 | make -j4 | grep "warning:r\|error:" 19 | echo "done building libdaisy" 20 | -------------------------------------------------------------------------------- /package-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "author" : "Graham Wakefield", 3 | "authors" : [ ], 4 | "categories" : [ ], 5 | "description" : "A package to support exporting gen~ patchers for the Electro-Smith Daisy platforms", 6 | "displayname" : "", 7 | "extends" : "", 8 | "extensible" : 0, 9 | "homepatcher" : "oopsy-guide.maxpat", 10 | "max_version_max" : "none", 11 | "max_version_min" : "none", 12 | "name" : "Oopsy", 13 | "readme" : "", 14 | "tags" : [ "gen~", "code export", "Daisy", "Eurorack" ], 15 | "version" : "0.0.1", 16 | "versions" : null, 17 | "website" : "", 18 | "filelist" : { 19 | "externals" : [], 20 | "patchers" : [], 21 | "help" : [], 22 | "misc" : [], 23 | "extras" : [] 24 | } 25 | } -------------------------------------------------------------------------------- /init/oopsy-objectmappings.txt: -------------------------------------------------------------------------------- 1 | max definesubstitution oopsy.patch bpatcher @name oopsy.maxpat @args patch; 2 | max objectfile oopsy.patch oopsy.patch; 3 | max definesubstitution oopsy.field bpatcher @name oopsy.maxpat @args field; 4 | max objectfile oopsy.field oopsy.field; 5 | max definesubstitution oopsy.petal bpatcher @name oopsy.maxpat @args petal; 6 | max objectfile oopsy.petal oopsy.petal; 7 | max definesubstitution oopsy.pod bpatcher @name oopsy.maxpat @args pod; 8 | max objectfile oopsy.pod oopsy.pod; 9 | max definesubstitution oopsy.patch_sm bpatcher @name oopsy.maxpat @args patch_sm; 10 | max objectfile oopsy.patch_sm oopsy.patch_sm; 11 | max definesubstitution oopsy.bluemchen bpatcher @name oopsy.maxpat @args bluemchen; 12 | max objectfile oopsy.bluemchen oopsy.bluemchen; 13 | max definesubstitution oopsy.nehcmeulb bpatcher @name oopsy.maxpat @args nehcmeulb; 14 | max objectfile oopsy.nehcmeulb oopsy.nehcmeulb; 15 | -------------------------------------------------------------------------------- /source/seed.bluemchen.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"bluemchen", 3 | "max_apps": 8, 4 | "defines": { 5 | "OOPSY_TARGET_HAS_MIDI_INPUT": 1 6 | }, 7 | "display": { 8 | "driver": "daisy::SSD130xI2c64x32Driver", 9 | "dim": [64, 32] 10 | }, 11 | "components": { 12 | "cv1": { 13 | "component": "AnalogControl", 14 | "pin": 21, 15 | "flip": true 16 | }, 17 | "cv2": { 18 | "component": "AnalogControl", 19 | "pin": 18, 20 | "flip": true 21 | }, 22 | "knob1": { 23 | "component": "AnalogControl", 24 | "pin": 16 25 | }, 26 | "knob2": { 27 | "component": "AnalogControl", 28 | "pin": 15 29 | }, 30 | "encoder": { 31 | "component": "Encoder", 32 | "pin": {"a":27, "b":26, "click":28 }, 33 | "meta": [ 34 | "menu_hold = ${name}.TimeHeldMs();", 35 | "menu_click = ${name}.FallingEdge();", 36 | "menu_rotate = ${name}.Increment();" 37 | ] 38 | } 39 | }, 40 | "aliases": { 41 | } 42 | } -------------------------------------------------------------------------------- /source/test.sh: -------------------------------------------------------------------------------- 1 | rm -rf build_* && \ 2 | node oopsy.js ../templates/oopsy_patch.cpp patch && \ 3 | node oopsy.js ../templates/oopsy_field.cpp field && \ 4 | node oopsy.js ../templates/oopsy_petal.cpp petal && \ 5 | node oopsy.js ../templates/oopsy_pod.cpp pod && \ 6 | node oopsy.js ../templates/oopsy_versio.cpp versio && \ 7 | node oopsy.js ../templates/oopsy_pod.cpp seed.pod.json && \ 8 | node oopsy.js ../templates/oopsy_versio.cpp seed.versio.json && \ 9 | node oopsy.js ../templates/oopsy_bluemchen.cpp bluemchen && \ 10 | node oopsy.js ../templates/oopsy_nehcmeulb.cpp nehcmeulb && \ 11 | node oopsy.js ../examples/dattoro.cpp ../examples/gigaverb.cpp ../examples/crossover.cpp ../examples/midside.cpp && \ 12 | node oopsy.js ../examples/midi_noteouts.cpp ../examples/midi_drum_ins.cpp ../examples/midi_drum_outs.cpp ../examples/midi_control_ins.cpp ../examples/midi_control_outs.cpp ../examples/midi_transport_ins.cpp ../examples/midi_transport_outs.cpp && \ 13 | node oopsy.js ../examples/sdcard.cpp -------------------------------------------------------------------------------- /source/seed.nehcmeulb.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"nehcmeulb", 3 | "max_apps": 8, 4 | "defines": { 5 | "OOPSY_TARGET_HAS_MIDI_OUTPUT": 1 6 | }, 7 | "display": { 8 | "driver": "daisy::SSD130xI2c64x32Driver", 9 | "dim": [64, 32] 10 | }, 11 | "components": { 12 | "knob1": { 13 | "component": "AnalogControl", 14 | "pin": 16 15 | }, 16 | "knob2": { 17 | "component": "AnalogControl", 18 | "pin": 15 19 | }, 20 | "cv1": { 21 | "component": "AnalogControl", 22 | "pin": 21, 23 | "flip": true 24 | }, 25 | "cv2": { 26 | "component": "AnalogControl", 27 | "pin": 18, 28 | "flip": true 29 | }, 30 | "cvout": { 31 | "component": "CVOuts" 32 | }, 33 | "encoder": { 34 | "component": "Encoder", 35 | "pin": {"a":27, "b":26, "click":28 }, 36 | "meta": [ 37 | "menu_hold = ${name}.TimeHeldMs();", 38 | "menu_click = ${name}.FallingEdge();", 39 | "menu_rotate = ${name}.Increment();" 40 | ] 41 | } 42 | }, 43 | "aliases": { 44 | } 45 | } -------------------------------------------------------------------------------- /javascript/oopsy.node4max.js: -------------------------------------------------------------------------------- 1 | // Node4Max wrapper of the gen2daisy.node.js script 2 | 3 | const path = require("path"), 4 | os = require("os") 5 | const maxAPI = require("max-api"); 6 | const run = require(path.join(__dirname, "..", "source", "oopsy.js")); 7 | 8 | let msgs = [] 9 | 10 | // duplicate stdout here so we can filter it and display more useful things in Max: 11 | // dup stdout to our handler: 12 | process.stdout.write = (function() { 13 | const stdout_write = process.stdout.write; 14 | return function(str) { 15 | stdout_write.apply(process.stdout, arguments); 16 | let match 17 | if (match = str.match(/^oopsy (.*)/i)) { 18 | //maxAPI.outlet(match[1]) // Node was timing out here, so we set up an interval reader instead 19 | msgs.push(match[1]) 20 | } 21 | } 22 | })(); 23 | 24 | setInterval(function() { 25 | while (msgs.length) { 26 | maxAPI.outlet(msgs.pop()) 27 | } 28 | }, 250) 29 | 30 | try { 31 | run(...process.argv.slice(2)) 32 | 33 | } catch(e) { 34 | maxAPI.post(e.message ? e.message : e, maxAPI.POST_LEVELS.ERROR); 35 | } -------------------------------------------------------------------------------- /source/seed.pod.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"pod", 3 | "defines": { 4 | "OOPSY_TARGET_HAS_MIDI_INPUT": 1 5 | }, 6 | "components": { 7 | "sw1": { 8 | "component": "Switch", 9 | "pin": 27 10 | }, 11 | "sw2": { 12 | "component": "Switch", 13 | "pin": 28 14 | }, 15 | "knob1": { 16 | "component": "AnalogControl", 17 | "pin": 21 18 | }, 19 | "knob2": { 20 | "component": "AnalogControl", 21 | "pin": 15 22 | }, 23 | "encoder": { 24 | "component": "Encoder", 25 | "pin": {"a":26, "b":25, "click":13 } 26 | }, 27 | "led1": { 28 | "component": "RgbLed", 29 | "pin": {"r":20, "g":19, "b":18 } 30 | }, 31 | "led2": { 32 | "component": "RgbLed", 33 | "pin": {"r":17, "g":24, "b":23 } 34 | } 35 | }, 36 | "aliases": { 37 | "switch": "sw1", 38 | "button": "sw1", 39 | "switch1": "sw1", 40 | "button1": "sw1", 41 | "switch2": "sw2", 42 | "button2": "sw2", 43 | "enp": "encoder_press", 44 | "switch3": "encoder_press", 45 | "press": "encoder_press", 46 | "knob": "knob1", 47 | "ctrl": "knob1", 48 | "ctrl1": "knob1", 49 | "ctrl2": "knob2", 50 | "led": "led1" 51 | } 52 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Graham Wakefield 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 | -------------------------------------------------------------------------------- /source/daisy.pod.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_apps":1, 3 | "defines": { 4 | "OOPSY_TARGET_POD": 1, 5 | "OOPSY_TARGET_HAS_MIDI_INPUT": 1, 6 | "OOPSY_HAS_ENCODER": 1 7 | }, 8 | "inserts": [ 9 | { "where": "header", "code": "#include \"daisy_pod.h\"" }, 10 | { "where": "header", "code": "typedef daisy::DaisyPod Daisy;" }, 11 | { "where": "post_audio", "code": "hardware.UpdateLeds();" } 12 | ], 13 | "labels": { 14 | "params": { 15 | "knob1": "kn1", 16 | "knob2": "kn2", 17 | "sw1": "sw1", 18 | "sw2": "sw2", 19 | "sw3": "enp", 20 | "encoder": "enc", 21 | 22 | "ctrl1": "kn1", 23 | "ctrl2": "kn2", 24 | "switch1": "sw1", 25 | "switch2": "sw2", 26 | "switch3": "enp", 27 | "knob": "kn1", 28 | "ctrl": "kn1", 29 | "switch": "sw1", 30 | "press": "enp" 31 | }, 32 | "outs": { 33 | "led1": "led1", 34 | "led2": "led2", 35 | 36 | "led": "led1" 37 | }, 38 | "datas": {} 39 | }, 40 | "inputs": { 41 | "kn1": { 42 | "automap": true, 43 | "code": "hardware.GetKnobValue(hardware.KNOB_1);" 44 | }, 45 | "kn2": { 46 | "automap": true, 47 | "code": "hardware.GetKnobValue(hardware.KNOB_2);" 48 | }, 49 | "sw1": { 50 | "code": "(hardware.button1.Pressed()?1.f:0.f);" 51 | }, 52 | "sw2": { 53 | "code": "(hardware.button2.Pressed()?1.f:0.f);" 54 | }, 55 | "enc": { 56 | "code": "(hardware.encoder.Increment()*0.5f+0.5f);" 57 | }, 58 | "enp": { 59 | "code": "(hardware.encoder.Pressed());" 60 | } 61 | }, 62 | "outputs": { 63 | "led1": { 64 | "where": "audio", 65 | "code": "hardware.led1.Set(clamp(-$, 0.f, 1.f), clamp($, 0.f, 1.f), 0.f);" 66 | }, 67 | "led2": { 68 | "where": "audio", 69 | "code": "hardware.led2.Set(clamp(-$, 0.f, 1.f), clamp($, 0.f, 1.f), 0.f);" 70 | } 71 | }, 72 | "datahandlers": {} 73 | } -------------------------------------------------------------------------------- /source/seed.versio.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"versio", 3 | "defines": {}, 4 | "components": { 5 | "knob1": { 6 | "component": "AnalogControl", 7 | "pin": 21 8 | }, 9 | "knob2": { 10 | "component": "AnalogControl", 11 | "pin": 22 12 | }, 13 | "knob3": { 14 | "component": "AnalogControl", 15 | "pin": 28 16 | }, 17 | "knob4": { 18 | "component": "AnalogControl", 19 | "pin": 23 20 | }, 21 | "knob5": { 22 | "component": "AnalogControl", 23 | "pin": 16 24 | }, 25 | "knob6": { 26 | "component": "AnalogControl", 27 | "pin": 17 28 | }, 29 | "knob7": { 30 | "component": "AnalogControl", 31 | "pin": 19 32 | }, 33 | 34 | "button1": { 35 | "component": "Switch", 36 | "pin": 30 37 | }, 38 | "gate1": { 39 | "component": "GateIn", 40 | "pin": 24 41 | }, 42 | "sw1": { 43 | "component": "Switch3", 44 | "pin": {"a":6, "b":5 } 45 | }, 46 | "sw2": { 47 | "component": "Switch3", 48 | "pin": {"a":1, "b":0 } 49 | }, 50 | "led1": { 51 | "component": "RgbLed", 52 | "pin": {"r":10, "g":3, "b":4 } 53 | }, 54 | "led2": { 55 | "component": "RgbLed", 56 | "pin": {"r":12, "g":13, "b":11 } 57 | }, 58 | "led3": { 59 | "component": "RgbLed", 60 | "pin": {"r":25, "g":26, "b":14 } 61 | }, 62 | "led4": { 63 | "component": "RgbLed", 64 | "pin": {"r":29, "g":27, "b":15 } 65 | } 66 | }, 67 | "aliases": { 68 | "switch1": "sw1", 69 | "switch2": "sw2", 70 | 71 | "ctrl1": "knob1", 72 | "ctrl2": "knob2", 73 | "ctrl3": "knob3", 74 | "ctrl4": "knob4", 75 | "ctrl5": "knob5", 76 | "ctrl6": "knob6", 77 | "ctrl7": "knob7", 78 | "cv1": "knob1", 79 | "cv2": "knob2", 80 | "cv3": "knob3", 81 | "cv4": "knob4", 82 | "cv5": "knob5", 83 | "cv6": "knob6", 84 | "cv7": "knob7", 85 | 86 | "ctrl": "knob1", 87 | "cv": "knob1", 88 | "led": "led1", 89 | "gate": "gate1", 90 | "switch": "sw1", 91 | "knob": "knob1", 92 | "button": "button1", 93 | "tap": "button1", 94 | "fsu": "button1", 95 | "abc": "sw1", 96 | "xyz": "sw2" 97 | } 98 | } -------------------------------------------------------------------------------- /source/readme.md: -------------------------------------------------------------------------------- 1 | # Development notes 2 | 3 | The Daisy platform has quite a wide range of different features and capabilities. Gen~ code export makes very few assumptions about what it will be used for. In order to glue the two together, a simple drop-in C++ template isn't enough. Instead, Oopsy inspects the gen~ to identify desired features and a wrapper C++ code is generated to bridge the gen~ exported code with the selected Daisy platform features and API. 4 | 5 | This code generation is done using Node.js (the `oopsy.js` script). That way, it can be invoked both within Max (via node4max) or also at the command line: 6 | 7 | 1. A patcher-based interface for editing gen~ patchers with Daisy features, which can download to the device directly on each edit (if the device is ready to receive code). This uses a Max abstraction to configure the gen~ objects for export and invoke the Node.js script accordingly. 8 | 2. A command-line interface for converting gen~-exported cpp code to Daisy binaries (which is used by (1)). This interface was written using Node.js, and thus can be invoked in Max via [node.script]. 9 | 10 | ## MIDI 11 | 12 | MIDI input can be bursty and sparse. A [param] is not a good match for this, since it can only handle 1 value per block size (even at 1000Hz this might not be enough to capture really bursty midi). Instead we feed the raw midi bytes in via an [in] signal, one byte per sample. 13 | 14 | MIDI bytes are normalized to unit range (mapping 0-256 to 0.0-1.0) so that any accidental patching doesn't burn hardware (electrical or human). Testing locally verified that this reconstructs the integer values exactly. 15 | 16 | If no more midi data is available, the midi signal value will be a negative number (e.g. -0.1). 17 | 18 | Example patchers show how to turn this into everything from notes, CCs, wheel, clock, sysex dumps, etc... 19 | 20 | ## Memory 21 | 22 | Memory allocation for the exported gen~ code happens only when an app is loaded. 23 | 24 | Oopsy uses two pre-allocated blocks of memory, a smaller one in SRAM (around 500Kb) and a larger one in SDRAM (64Mb). Both memory blocks are reset when an app is loaded, so that each gen~ has the full blocks available. Generally SRAM seems to offer faster access, so allocations go to this block if they will fit, which is the case for most gen~ patchers and gen~ operators. Only `data` and `delay` operators with large contents that do not fit in SRAM will use the SDRAM block. 25 | 26 | The Daisy offers 128k for code size. Initial testing showed that the baseline for libdaisy and Oopsy is about 50-60k, and each app adds around 5-10k. -------------------------------------------------------------------------------- /source/daisy.patch.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_apps":8, 3 | "defines": { 4 | "OOPSY_TARGET_PATCH": 1, 5 | "OOPSY_TARGET_HAS_OLED": 1, 6 | "OOPSY_IO_COUNT": 4, 7 | "OOPSY_TARGET_HAS_MIDI_INPUT": 1, 8 | "OOPSY_TARGET_HAS_MIDI_OUTPUT": 1, 9 | "OOPSY_HAS_ENCODER": 1 10 | }, 11 | "inserts": [ 12 | { "where": "header", "code": "#include \"daisy_patch.h\"" }, 13 | { "where": "header", "code": "typedef daisy::DaisyPatch Daisy;" } 14 | ], 15 | "labels": { 16 | "params": { 17 | "knob1": "kn1", 18 | "knob2": "kn2", 19 | "knob3": "kn3", 20 | "knob4": "kn4", 21 | "gate1": "gt1", 22 | "gate2": "gt2", 23 | 24 | "knob": "kn1", 25 | "cv": "kn1", 26 | "cv1": "kn1", 27 | "cv2": "kn2", 28 | "cv3": "kn3", 29 | "cv4": "kn4", 30 | "ctrl": "kn1", 31 | "ctrl1": "kn1", 32 | "ctrl2": "kn2", 33 | "ctrl3": "kn3", 34 | "ctrl4": "kn4", 35 | "gate": "gt1" 36 | }, 37 | "outs": { 38 | "cv1": "cvout1", 39 | "cv2": "cvout2", 40 | "gate1": "gateout1", 41 | 42 | "cv": "cvout1", 43 | "gate": "gateout1" 44 | }, 45 | "datas": { 46 | "midi": "dsy_midi_out" 47 | } 48 | }, 49 | "inputs": { 50 | "kn1": { 51 | "automap": true, 52 | "code": "hardware.GetKnobValue(hardware.CTRL_1);" 53 | }, 54 | "kn2": { 55 | "automap": true, 56 | "code": "hardware.GetKnobValue(hardware.CTRL_2);" 57 | }, 58 | "kn3": { 59 | "automap": true, 60 | "code": "hardware.GetKnobValue(hardware.CTRL_3);" 61 | }, 62 | "kn4": { 63 | "automap": true, 64 | "code": "hardware.GetKnobValue(hardware.CTRL_4);" 65 | }, 66 | "gt1": { 67 | "code": "(hardware.gate_input[hardware.GATE_IN_1].State()?1.f:0.f);" 68 | }, 69 | "gt2": { 70 | "code": "(hardware.gate_input[hardware.GATE_IN_2].State()?1.f:0.f);" 71 | } 72 | }, 73 | "outputs": { 74 | "cvout1": { 75 | "where": "main", 76 | "code": "hardware.seed.dac.WriteValue(daisy::DacHandle::Channel::ONE, $ * 4095);" 77 | }, 78 | "cvout2": { 79 | "where": "main", 80 | "code": "hardware.seed.dac.WriteValue(daisy::DacHandle::Channel::TWO, $ * 4095);" 81 | }, 82 | "gateout1": { 83 | "where": "audio", 84 | "code": "dsy_gpio_write(&hardware.gate_output, $ > 0.f);" 85 | } 86 | }, 87 | "datahandlers": { 88 | "dsy_midi_out": { 89 | "where":"main", 90 | "init": "daisy.midi_nullData($)", 91 | "code": "daisy.midi_fromData($);" 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /source/gen_dsp/genlib_exportfunctions.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************************************************* 2 | Cycling '74 License for Max-Generated Code for Export 3 | Copyright (c) 2016 Cycling '74 4 | The code that Max generates automatically and that end users are capable of exporting and using, and any 5 | associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author 6 | and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a 7 | copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, 8 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the 10 | Software must contact the copyright owner to determine if a license for commercial use is available, and the 11 | terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries 12 | to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based 13 | upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or 14 | other business whether for-profit or non-profit so long as the use itself is not a commercialization of the 15 | materials or a use that generates or is intended to generate income, revenue, sales or profit. 16 | The above copyright notice and this license shall be included in all copies or substantial portions of the Software. 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 18 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | *******************************************************************************************************************/ 23 | 24 | #ifndef GENLIB_EXPORT_FUNCTIONS_H 25 | #define GENLIB_EXPORT_FUNCTIONS_H 1 26 | 27 | t_ptr genlib_sysmem_newptr(t_ptr_size size); 28 | t_ptr genlib_sysmem_newptrclear(t_ptr_size size); 29 | t_ptr genlib_sysmem_resizeptr(void *ptr, t_ptr_size newsize); 30 | t_ptr genlib_rsysmem_esizeptrclear(void *ptr, t_ptr_size newsize); 31 | t_ptr_size genlib_sysmem_ptrsize(void *ptr); 32 | void genlib_sysmem_freeptr(void *ptr); 33 | void genlib_sysmem_copyptr(const void *src, void *dst, t_ptr_size bytes); 34 | void genlib_report_error(const char *s); 35 | void genlib_report_message(const char *s); 36 | void genlib_set_zero64(t_sample *mem, long size); 37 | unsigned long genlib_ticks(); 38 | void genlib_init(); 39 | void genlib_info(); 40 | 41 | #endif // GENLIB_EXPORT_FUNCTIONS_H 42 | 43 | -------------------------------------------------------------------------------- /source/daisy.petal.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_apps":8, 3 | "defines": { 4 | "OOPSY_TARGET_PETAL": 1, 5 | "OOPSY_HAS_ENCODER": 1 6 | }, 7 | "inserts": [ 8 | { "where": "header", "code": "#include \"daisy_petal.h\"" }, 9 | { "where": "header", "code": "typedef daisy::DaisyPetal Daisy;" } 10 | ], 11 | "labels": { 12 | "params": { 13 | "knob1": "kn1", 14 | "knob2": "kn2", 15 | "knob3": "kn3", 16 | "knob4": "kn4", 17 | "knob5": "kn5", 18 | "knob6": "kn6", 19 | "sw1": "sw1", 20 | "sw2": "sw2", 21 | "sw3": "sw3", 22 | "sw4": "sw4", 23 | "sw5": "sw5", 24 | "sw6": "sw6", 25 | "sw7": "sw7", 26 | "exp1": "exp", 27 | 28 | "ctrl1": "kn1", 29 | "ctrl2": "kn2", 30 | "ctrl3": "kn3", 31 | "ctrl4": "kn4", 32 | "ctrl5": "kn5", 33 | "ctrl6": "kn6", 34 | "switch1": "sw1", 35 | "switch2": "sw2", 36 | "switch3": "sw3", 37 | "switch4": "sw4", 38 | "switch5": "sw5", 39 | "switch6": "sw6", 40 | "switch7": "sw7", 41 | "knob": "kn1", 42 | "ctrl": "kn1", 43 | "switch": "sw1", 44 | "exp": "exp", 45 | "expression": "exp" 46 | }, 47 | "outs": { 48 | "led1": "led1", 49 | "led2": "led2", 50 | "led3": "led3", 51 | "led4": "led4" 52 | }, 53 | "datas": {} 54 | }, 55 | "inputs": { 56 | "kn1": { 57 | "automap": true, 58 | "code": "hardware.GetKnobValue(hardware.KNOB_1);" 59 | }, 60 | "kn2": { 61 | "automap": true, 62 | "code": "hardware.GetKnobValue(hardware.KNOB_2);" 63 | }, 64 | "kn3": { 65 | "automap": true, 66 | "code": "hardware.GetKnobValue(hardware.KNOB_3);" 67 | }, 68 | "kn4": { 69 | "automap": true, 70 | "code": "hardware.GetKnobValue(hardware.KNOB_4);" 71 | }, 72 | "kn5": { 73 | "automap": true, 74 | "code": "hardware.GetKnobValue(hardware.KNOB_5);" 75 | }, 76 | "kn6": { 77 | "automap": true, 78 | "code": "hardware.GetKnobValue(hardware.KNOB_6);" 79 | }, 80 | "sw1": { 81 | "code": "(hardware.switches[0].Pressed()?1.f:0.f);" 82 | }, 83 | "sw2": { 84 | "code": "(hardware.switches[1].Pressed()?1.f:0.f);" 85 | }, 86 | "sw3": { 87 | "code": "(hardware.switches[2].Pressed()?1.f:0.f);" 88 | }, 89 | "sw4": { 90 | "code": "(hardware.switches[3].Pressed()?1.f:0.f);" 91 | }, 92 | "sw5": { 93 | "code": "(hardware.switches[4].Pressed()?1.f:0.f);" 94 | }, 95 | "sw6": { 96 | "code": "(hardware.switches[5].Pressed()?1.f:0.f);" 97 | }, 98 | "sw7": { 99 | "code": "(hardware.switches[6].Pressed()?1.f:0.f);" 100 | }, 101 | "exp": { 102 | "code": "(hardware.GetExpression());" 103 | } 104 | }, 105 | "outputs": { 106 | "led1": { 107 | "where": "display", 108 | "code": "hardware.SetFootswitchLed(daisy::DaisyPetal::FOOTSWITCH_LED_1, $);" 109 | }, 110 | "led2": { 111 | "where": "display", 112 | "code": "hardware.SetFootswitchLed(daisy::DaisyPetal::FOOTSWITCH_LED_2, $);" 113 | }, 114 | "led3": { 115 | "where": "display", 116 | "code": "hardware.SetFootswitchLed(daisy::DaisyPetal::FOOTSWITCH_LED_3, $);" 117 | }, 118 | "led4": { 119 | "where": "display", 120 | "code": "hardware.SetFootswitchLed(daisy::DaisyPetal::FOOTSWITCH_LED_4, $);" 121 | } 122 | }, 123 | "datahandlers": { 124 | } 125 | } -------------------------------------------------------------------------------- /source/daisy.versio.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_apps":1, 3 | "defines": { 4 | "OOPSY_TARGET_VERSIO": 1 5 | }, 6 | "inserts": [ 7 | { "where": "header", "code": "#include \"daisy_versio.h\"" }, 8 | { "where": "header", "code": "typedef daisy::DaisyVersio Daisy;" }, 9 | { "where": "post_audio", "code": "hardware.UpdateLeds();" } 10 | ], 11 | "labels": { 12 | "params": { 13 | "knob1": "kn1", 14 | "knob2": "kn2", 15 | "knob3": "kn3", 16 | "knob4": "kn4", 17 | "knob5": "kn5", 18 | "knob6": "kn6", 19 | "knob7": "kn7", 20 | "button1": "bt1", 21 | "sw1": "sw1", 22 | "sw2": "sw2", 23 | "gate1": "gt1", 24 | 25 | "cv1": "kn1", 26 | "cv2": "kn2", 27 | "cv3": "kn3", 28 | "cv4": "kn4", 29 | "cv5": "kn5", 30 | "cv6": "kn6", 31 | "cv7": "kn7", 32 | "ctrl1": "kn1", 33 | "ctrl2": "kn2", 34 | "ctrl3": "kn3", 35 | "ctrl4": "kn4", 36 | "ctrl5": "kn5", 37 | "ctrl6": "kn6", 38 | "ctrl7": "kn7", 39 | "switch1": "sw1", 40 | "switch2": "sw2", 41 | 42 | "knob": "kn1", 43 | "button": "bt1", 44 | "ctrl": "kn1", 45 | "cv": "kn1", 46 | "switch": "sw1", 47 | "gate": "gt1", 48 | 49 | "tap": "bt1", 50 | "fsu": "bt1", 51 | "abc": "sw1", 52 | "xyz": "sw2" 53 | }, 54 | "outs": { 55 | "led1": "led1", 56 | "led2": "led2", 57 | "led3": "led3", 58 | "led4": "led4" 59 | }, 60 | "datas": {} 61 | }, 62 | "inputs": { 63 | "kn1": { 64 | "automap": true, 65 | "code": "hardware.GetKnobValue(hardware.KNOB_0);" 66 | }, 67 | "kn2": { 68 | "automap": true, 69 | "code": "hardware.GetKnobValue(hardware.KNOB_1);" 70 | }, 71 | "kn3": { 72 | "automap": true, 73 | "code": "hardware.GetKnobValue(hardware.KNOB_2);" 74 | }, 75 | "kn4": { 76 | "automap": true, 77 | "code": "hardware.GetKnobValue(hardware.KNOB_3);" 78 | }, 79 | "kn5": { 80 | "automap": true, 81 | "code": "hardware.GetKnobValue(hardware.KNOB_4);" 82 | }, 83 | "kn6": { 84 | "automap": true, 85 | "code": "hardware.GetKnobValue(hardware.KNOB_5);" 86 | }, 87 | "kn7": { 88 | "automap": true, 89 | "code": "hardware.GetKnobValue(hardware.KNOB_6);" 90 | }, 91 | "sw1": { 92 | "code": "(hardware.sw[0].Read()/2.f);" 93 | }, 94 | "sw2": { 95 | "code": "(hardware.sw[1].Read()/2.f);" 96 | }, 97 | "bt1": { 98 | "code": "(hardware.tap.Pressed()?1.f:0.f);", 99 | "update": { 100 | "where": "audio", 101 | "code": "hardware.tap.Debounce();" 102 | } 103 | }, 104 | "gt1": { 105 | "code": "(hardware.Gate()?1.f:0.f);" 106 | } 107 | }, 108 | "outputs": { 109 | "led1": { 110 | "where": "audio", 111 | "code": "hardware.leds[0].Set(clamp(-$, 0.f, 1.f), clamp($, 0.f, 1.f), 0.f);" 112 | }, 113 | "led2": { 114 | "where": "audio", 115 | "code": "hardware.leds[1].Set(clamp(-$, 0.f, 1.f), clamp($, 0.f, 1.f), 0.f);" 116 | }, 117 | "led3": { 118 | "where": "audio", 119 | "code": "hardware.leds[2].Set(clamp(-$, 0.f, 1.f), clamp($, 0.f, 1.f), 0.f);" 120 | }, 121 | "led4": { 122 | "where": "audio", 123 | "code": "hardware.leds[3].Set(clamp(-$, 0.f, 1.f), clamp($, 0.f, 1.f), 0.f);" 124 | } 125 | }, 126 | "datahandlers": {} 127 | } -------------------------------------------------------------------------------- /code/oopsy.suggestions.gendsp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "dsp.gen", 13 | "rect" : [ 84.0, 103.0, 716.0, 697.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-5", 44 | "linecount" : 7, 45 | "maxclass" : "comment", 46 | "numinlets" : 1, 47 | "numoutlets" : 0, 48 | "patching_rect" : [ 50.0, 350.0, 404.0, 100.0 ], 49 | "presentation_linecount" : 7, 50 | "text" : "Since input gates are sampled at block rate, they will actually produce a step function. If you need a single-sample edge you can feed it through [change], which will give a 1 on a rising step or a -1 on a falling step. \n\nSometimes you only want triggers on transitions to non-zero values, e.g. converting a gate onset to a trig, or feeding an encoder into an [accum] for an endless rotary. This abstraction will achieve this:" 51 | } 52 | 53 | } 54 | , { 55 | "box" : { 56 | "id" : "obj-4", 57 | "maxclass" : "newobj", 58 | "numinlets" : 1, 59 | "numoutlets" : 1, 60 | "outlettype" : [ "" ], 61 | "patching_rect" : [ 50.0, 452.0, 86.0, 22.0 ], 62 | "text" : "oopsy.gate.trig" 63 | } 64 | 65 | } 66 | , { 67 | "box" : { 68 | "id" : "obj-3", 69 | "linecount" : 4, 70 | "maxclass" : "comment", 71 | "numinlets" : 1, 72 | "numoutlets" : 0, 73 | "patching_rect" : [ 50.0, 235.0, 404.0, 60.0 ], 74 | "text" : "Similarly, output gates that are shorter than 1ms may be missed, because of control-rate sampling. This subpatcher ensures even a single-sample click will be extended to the minimum gate duration for the hardware (1ms by default):" 75 | } 76 | 77 | } 78 | , { 79 | "box" : { 80 | "id" : "obj-2", 81 | "maxclass" : "newobj", 82 | "numinlets" : 1, 83 | "numoutlets" : 1, 84 | "outlettype" : [ "" ], 85 | "patching_rect" : [ 50.0, 297.0, 89.0, 22.0 ], 86 | "text" : "oopsy.gate.min" 87 | } 88 | 89 | } 90 | , { 91 | "box" : { 92 | "id" : "obj-1", 93 | "maxclass" : "newobj", 94 | "numinlets" : 1, 95 | "numoutlets" : 1, 96 | "outlettype" : [ "" ], 97 | "patching_rect" : [ 170.0, 166.5, 108.0, 22.0 ], 98 | "text" : "oopsy.ctrl.smooth3" 99 | } 100 | 101 | } 102 | , { 103 | "box" : { 104 | "id" : "obj-32", 105 | "maxclass" : "newobj", 106 | "numinlets" : 1, 107 | "numoutlets" : 1, 108 | "outlettype" : [ "" ], 109 | "patching_rect" : [ 50.0, 166.5, 108.0, 22.0 ], 110 | "text" : "oopsy.ctrl.smooth2" 111 | } 112 | 113 | } 114 | , { 115 | "box" : { 116 | "id" : "obj-22", 117 | "linecount" : 4, 118 | "maxclass" : "comment", 119 | "numinlets" : 1, 120 | "numoutlets" : 0, 121 | "patching_rect" : [ 50.0, 100.0, 404.0, 60.0 ], 122 | "text" : "Note that CV/knob inputs update at block-rate, which is by default 1ms for Daisy. You may want to add some filtering or smoothing to CVs, depending on how they are being used in the patch. Here are some options:" 123 | } 124 | 125 | } 126 | ], 127 | "lines" : [ ] 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /source/daisy.patch_sm.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_apps":8, 3 | "defines": { 4 | "OOPSY_TARGET_PATCH_SM": 1, 5 | "OOPSY_IO_COUNT": 2 6 | }, 7 | "inserts": [ 8 | { "where": "header", "code": "#include \"daisy_patch_sm.h\"" }, 9 | { "where": "header", "code": "typedef daisy::patch_sm::DaisyPatchSM Daisy;" }, 10 | { "where": "header", "code": "daisy::Switch sw_class;" }, 11 | { "where": "init", "code": "sw_class.Init(oopsy::daisy.hardware.B8, 1000);"}, 12 | { "where": "audio", "code": "sw_class.Debounce();" }, 13 | 14 | { "where": "header", "code": "daisy::Switch button_class;" }, 15 | { "where": "init", "code": "button_class.Init(oopsy::daisy.hardware.B7, 1000);"}, 16 | { "where": "audio", "code": "button_class.Debounce();" } 17 | ], 18 | "labels": { 19 | "params": { 20 | "knob1": "kn1", 21 | "knob2": "kn2", 22 | "knob3": "kn3", 23 | "knob4": "kn4", 24 | "gate1": "gt1", 25 | "gate2": "gt2", 26 | 27 | "sw": "sw", 28 | "sw1": "sw", 29 | "sw2": "button", 30 | "button": "button", 31 | "press": "button", 32 | 33 | "knob": "kn1", 34 | "cv": "kn1", 35 | "cv1": "kn1", 36 | "cv2": "kn2", 37 | "cv3": "kn3", 38 | "cv4": "kn4", 39 | "cv5": "cv5", 40 | "cv6": "cv6", 41 | "cv7": "cv7", 42 | "cv8": "cv8", 43 | 44 | "ctrl": "kn1", 45 | "ctrl1": "kn1", 46 | "ctrl2": "kn2", 47 | "ctrl3": "kn3", 48 | "ctrl4": "kn4", 49 | 50 | "gate": "gt1", 51 | 52 | "CV_1": "kn1", 53 | "CV_2": "kn2", 54 | "CV_3": "kn3", 55 | "CV_4": "kn4", 56 | "CV_5": "cv5", 57 | "CV_6": "cv6", 58 | "CV_7": "cv7", 59 | "CV_8": "cv8", 60 | 61 | "B7": "button", 62 | "B8": "sw", 63 | 64 | "B10": "gt1", 65 | "B9": "gt2", 66 | "gate_in_1": "gt1", 67 | "gate_in_2": "gt2" 68 | }, 69 | "outs": { 70 | "cvout1": "cvout1", 71 | "cvout2": "cvout2", 72 | 73 | "cv1": "cvout1", 74 | "cv2": "cvout2", 75 | "gate1": "gateout1", 76 | "gate2": "gateout2", 77 | 78 | "cv": "cvout1", 79 | "led": "cvout2", 80 | "gate": "gateout1", 81 | 82 | "CV_OUT_1": "cvout1", 83 | "C10": "cvout1", 84 | "CV_OUT_2": "cvout2", 85 | 86 | "B5": "gateout1", 87 | "B6": "gateout2", 88 | "gate_out_1": "gateout1", 89 | "gate_out_2": "gateout2" 90 | }, 91 | "datas": {} 92 | }, 93 | "inputs": { 94 | "kn1": { 95 | "automap": true, 96 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_1);" 97 | }, 98 | "kn2": { 99 | "automap": true, 100 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_2);" 101 | }, 102 | "kn3": { 103 | "automap": true, 104 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_3);" 105 | }, 106 | "kn4": { 107 | "automap": true, 108 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_4);" 109 | }, 110 | "cv5": { 111 | "automap": true, 112 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_5);" 113 | }, 114 | "cv6": { 115 | "automap": true, 116 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_6);" 117 | }, 118 | "cv7": { 119 | "automap": true, 120 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_7);" 121 | }, 122 | "cv8": { 123 | "automap": true, 124 | "code": "hardware.GetAdcValue(daisy::patch_sm::CV_8);" 125 | }, 126 | "gt1": { 127 | "code": "(hardware.gate_in_1.State()?1.f:0.f);" 128 | }, 129 | "gt2": { 130 | "code": "(hardware.gate_in_2.State()?1.f:0.f);" 131 | }, 132 | "button": { 133 | "code": "(button_class.Pressed() ? 1.f : 0.f);" 134 | }, 135 | "sw": { 136 | "code": "(sw_class.Pressed() ? 1.f : 0.f);" 137 | } 138 | }, 139 | "outputs": { 140 | "cvout1": { 141 | "where": "main", 142 | "code": "hardware.WriteCvOut(daisy::patch_sm::CV_OUT_1, $ * 5.f);" 143 | }, 144 | "cvout2": { 145 | "where": "main", 146 | "code": "hardware.WriteCvOut(daisy::patch_sm::CV_OUT_2, $ * 5.f);" 147 | }, 148 | "gateout1": { 149 | "where": "audio", 150 | "code": "dsy_gpio_write(&hardware.gate_out_1, $ > 0.f);" 151 | }, 152 | "gateout2": { 153 | "where": "audio", 154 | "code": "dsy_gpio_write(&hardware.gate_out_2, $ > 0.f);" 155 | } 156 | }, 157 | "datahandlers": {} 158 | } 159 | -------------------------------------------------------------------------------- /code/oopsy.gate.trig.gendsp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "dsp.gen", 13 | "rect" : [ 84.0, 103.0, 579.0, 331.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 | "fontname" : "Courier", 44 | "id" : "obj-5", 45 | "linecount" : 3, 46 | "maxclass" : "comment", 47 | "numinlets" : 1, 48 | "numoutlets" : 0, 49 | "patching_rect" : [ 124.0, 217.0, 409.0, 42.0 ], 50 | "text" : "e.g. \nINPUT: 0 0 0 0 1 1 1 1 0 0 0 0 -1 -1 -1 0 0 0 0\nOUTPUT: 0 0 0 0 1 0 0 0 0 0 0 0 -1 0 0 0 0 0 0" 51 | } 52 | 53 | } 54 | , { 55 | "box" : { 56 | "fontname" : "Geneva", 57 | "fontsize" : 10.0, 58 | "id" : "obj-3", 59 | "maxclass" : "newobj", 60 | "numinlets" : 1, 61 | "numoutlets" : 1, 62 | "outlettype" : [ "" ], 63 | "patching_rect" : [ 28.0, 87.5, 25.0, 21.0 ], 64 | "text" : "int" 65 | } 66 | 67 | } 68 | , { 69 | "box" : { 70 | "fontname" : "Arial", 71 | "id" : "obj-2", 72 | "linecount" : 10, 73 | "maxclass" : "comment", 74 | "numinlets" : 1, 75 | "numoutlets" : 0, 76 | "patching_rect" : [ 124.0, 58.0, 409.0, 141.0 ], 77 | "text" : "Converts any gate-like signal into a signed trig of its rising and falling edges. \n\nEncoders and switches output gates like 0, 1, and sometimes -1, but since they are sampled at block rate (normally 48 samples), this results in a step function. \n\nIf you want a single-sample trigger for these events, e.g. for routing an encoder into an [accum] for an endless rotary kind of behaviour, this simple circuit will do the job." 78 | } 79 | 80 | } 81 | , { 82 | "box" : { 83 | "fontname" : "Geneva", 84 | "fontsize" : 10.0, 85 | "id" : "obj-8", 86 | "maxclass" : "newobj", 87 | "numinlets" : 1, 88 | "numoutlets" : 1, 89 | "outlettype" : [ "" ], 90 | "patching_rect" : [ 46.5, 131.0, 54.0, 21.0 ], 91 | "text" : "change" 92 | } 93 | 94 | } 95 | , { 96 | "box" : { 97 | "fontname" : "Geneva", 98 | "fontsize" : 10.0, 99 | "id" : "obj-7", 100 | "maxclass" : "newobj", 101 | "numinlets" : 2, 102 | "numoutlets" : 1, 103 | "outlettype" : [ "" ], 104 | "patching_rect" : [ 28.0, 155.0, 35.0, 21.0 ], 105 | "text" : "eqp" 106 | } 107 | 108 | } 109 | , { 110 | "box" : { 111 | "id" : "obj-13", 112 | "maxclass" : "newobj", 113 | "numinlets" : 0, 114 | "numoutlets" : 1, 115 | "outlettype" : [ "" ], 116 | "patching_rect" : [ 28.0, 24.0, 154.0, 22.0 ], 117 | "text" : "in 1 gate-switch-or-encoder" 118 | } 119 | 120 | } 121 | , { 122 | "box" : { 123 | "id" : "obj-14", 124 | "maxclass" : "newobj", 125 | "numinlets" : 1, 126 | "numoutlets" : 0, 127 | "patching_rect" : [ 28.0, 268.0, 133.0, 22.0 ], 128 | "text" : "out 1 single-sample-trig" 129 | } 130 | 131 | } 132 | ], 133 | "lines" : [ { 134 | "patchline" : { 135 | "destination" : [ "obj-3", 0 ], 136 | "source" : [ "obj-13", 0 ] 137 | } 138 | 139 | } 140 | , { 141 | "patchline" : { 142 | "destination" : [ "obj-7", 0 ], 143 | "order" : 1, 144 | "source" : [ "obj-3", 0 ] 145 | } 146 | 147 | } 148 | , { 149 | "patchline" : { 150 | "destination" : [ "obj-8", 0 ], 151 | "order" : 0, 152 | "source" : [ "obj-3", 0 ] 153 | } 154 | 155 | } 156 | , { 157 | "patchline" : { 158 | "destination" : [ "obj-14", 0 ], 159 | "source" : [ "obj-7", 0 ] 160 | } 161 | 162 | } 163 | , { 164 | "patchline" : { 165 | "destination" : [ "obj-7", 1 ], 166 | "source" : [ "obj-8", 0 ] 167 | } 168 | 169 | } 170 | ] 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /source/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.5.0-beta 4 | 5 | - Targets: 6 | - Support for the Daisy Patch SM on the patch.Init() 7 | 8 | ## v0.4.0-beta 9 | 10 | - Params: 11 | - Params like "knob1_int_foo" or "knob2_bool_bar" will be locked to integer/bool values within their respective @min/@max ranges 12 | - MIDI: 13 | - API change: [out N midi*] no longer supported. Use [history midi_*_out] instead. Raw MIDI output was causing unpredictable behaviour and could overload the MIDI baud rate too easily. Better handlers for specific MIDI messages have been added instead. 14 | - Added support for a few [param] midi handling types such as midi_cc, midi_bend, midi_vel, midi_clock, etc. 15 | - Added support for history-based MIDI outputs: 16 | - [history midi_cc1_out], [history midi_cc11_ch2_out], etc.: 0..1 outputs midi CC (default channel 1) 17 | - [history midi_bend_out], [history midi_bend_ch2_out], etc.: -1..1 outputs midi CC (default channel 1) 18 | - [history midi_press_out], [history midi_press_ch2_out], etc.: 0..1 outputs midi channel pressure (default channel 1) 19 | - [history midi_program_out], [history midi_program_ch2_out], etc.: 0..127 outputs midi program change (default channel 1) 20 | - [history midi_drum36_out] etc.: 0..1 outputs note velocity on channel 10 21 | - [history midi_vel36_out], [history midi_vel36_ch2_out] etc.: 0..1 outputs note velocity (default channel 1) 22 | - [history midi_clock_out], [history midi_stop_out], [history midi_start_out], [history midi_continue_out], [history midi_reset_out], [history midi_sense_out]: rising edge gate outputs transport etc. midi messages 23 | - Added midi note output mechanics: 24 | - [history midi_note1_pitch_out] and [history midi_note1_vel_out] at minimum required to create a note out. Use note1, note2, noteN etc. to define your polyphony. 25 | - [history midi_note1_chan_out] and [history midi_note1_press_out] are optional for setting a midi channel (other than channel 1) and polyphonic pressure (aka polyphonic aftertouch) 26 | - Added [in N midithru], which works the same as [in N midi] (giving you raw bytes scaled by 1/256), but also passes all MIDI received in the hardware input through to the hardware output 27 | - Moved midi handling into app-level code to support custom midi handlers as [param]; raw midi handling not generated if not used 28 | - Fix: ensure program-change midi handling is generated for multi-app even when no apps used midi 29 | - Data/Buffer & SDCard: 30 | - [data foo_wav 512 2] will try to auto-load from "foo.wav" from the SDcard 31 | - [data foo 512 2] will try to auto-load from "foo.wav" from the SDcard if there is a "foo.wav" in the same folder as the Max patcher 32 | - gen~ cannot export patchers with [buffer]; oopsy now warns with messages like "consider replacing [buffer fooz] with [data fooz 10 1]" 33 | - Patcher UI: 34 | - Added "boost" option to Max and Node.js which boosts CPU frequency from 400 to 480MHz 35 | - Added "fastmath" option to Max and Node.js interfaces to replace transcendental functions with cheaper and smaller approximations 36 | - Added blocksize selection to Max and Node.js interfaces 37 | - Better error handling and messaging, also fixes endless node.script restart bug 38 | - Template patcher cosmetics 39 | - Code generation: 40 | - Oopsy checks for gcc/dfu-util in /opt/homebrew or /usr/local and flags an error if neither are found 41 | - Oopsy reports total binary size 42 | - Code generation now uses the xoshiro PRNG for [noise], to match MSP's [noise~] 43 | - Updates to makefiles to support SDcard and fix some compilation errors 44 | - Code generation cleanup 45 | - Targets: 46 | - Support for Noise Engineering's Versio, including all on-panel controls and LEDs, and template patch. 47 | - Param view added to Daisy Field; params not tweakable (because of no encoder) but at least visible 48 | - Added ability to select custom JSON config from within oopsy.maxpat via "browse" button or @target argument 49 | - Modified config JSON and genlib_daisy.h to create more flexibiity for custom Seed targets 50 | - OLED UI: 51 | - Removed endless menu rotation so that scrolling to beginning/end is easier 52 | - Custom seed projects 53 | - New JSON structure for more concise and flexible pin mappings 54 | 55 | ## v0.3.0-beta 56 | 57 | - Added OLED parameter view, displaying input mapping, current value, and ability to modify non-mapped params via encoder/switches 58 | - Added more IO channel options to OLED display 59 | - Multi-app binaries will switch app according to MIDI program-change messages 60 | - Samplerate selection (32/48/96kHz) in the oopsy interface 61 | - Dedicated continual MIDI outputs via e.g. [out 5 midi_cc1], [out 5 midi_cc1_ch3], [out 5 midi_drum36], etc. 62 | - Code generation cleanup 63 | ## v0.2.2-beta 64 | 65 | - Fixes for windows compatibility 66 | 67 | ## v0.2.1-beta 68 | 69 | - Automatic zeroing / normalling of unused audio outputs 70 | - Better automatic naming from template patches 71 | - Fix for parsing params declared with @default 72 | - Examples: 73 | - crossover filter 74 | - pulsar osc 75 | - mod FM osc 76 | - Updated for libdaisy board API (< do we want stuff like this that doesn't actual affect behavior in the changelog?) 77 | 78 | ## v0.2-beta 79 | 80 | - Initial public beta 81 | 82 | 83 | -------------------------------------------------------------------------------- /source/daisy.field.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_apps":8, 3 | "defines": { 4 | "OOPSY_TARGET_FIELD": 1, 5 | "OOPSY_TARGET_HAS_OLED": 1, 6 | "OOPSY_TARGET_HAS_MIDI_INPUT": 1, 7 | "OOPSY_TARGET_HAS_MIDI_OUTPUT": 1 8 | }, 9 | "inserts": [ 10 | { "where": "header", "code": "#include \"daisy_field.h\"" }, 11 | { "where": "header", "code": "typedef daisy::DaisyField Daisy;" } 12 | ], 13 | "labels": { 14 | "params": { 15 | "knob1": "kn1", 16 | "knob2": "kn2", 17 | "knob3": "kn3", 18 | "knob4": "kn4", 19 | "knob5": "kn5", 20 | "knob6": "kn6", 21 | "knob7": "kn7", 22 | "knob8": "kn8", 23 | "keyA1": "kB1", 24 | "keyA2": "kB2", 25 | "keyA3": "kB3", 26 | "keyA4": "kB4", 27 | "keyA5": "kB5", 28 | "keyA6": "kB6", 29 | "keyA7": "kB7", 30 | "keyA8": "kB8", 31 | "keyB1": "kA1", 32 | "keyB2": "kA2", 33 | "keyB3": "kA3", 34 | "keyB4": "kA4", 35 | "keyB5": "kA5", 36 | "keyB6": "kA6", 37 | "keyB7": "kA7", 38 | "keyB8": "kA8", 39 | "sw1": "sw1", 40 | "sw2": "sw2", 41 | "cv1": "cv1", 42 | "cv2": "cv2", 43 | "cv3": "cv3", 44 | "cv4": "cv4", 45 | "gate1": "gt1", 46 | 47 | "key1": "kA1", 48 | "key2": "kA2", 49 | "key3": "kA3", 50 | "key4": "kA4", 51 | "key5": "kA5", 52 | "key6": "kA6", 53 | "key7": "kA7", 54 | "key8": "kA8", 55 | "key9": "kB1", 56 | "key10": "kB2", 57 | "key11": "kB3", 58 | "key12": "kB4", 59 | "key13": "kB5", 60 | "key14": "kB6", 61 | "key15": "kB7", 62 | "key16": "kB8", 63 | "ctrl1": "kn1", 64 | "ctrl2": "kn2", 65 | "ctrl3": "kn3", 66 | "ctrl4": "kn4", 67 | "ctrl5": "kn5", 68 | "ctrl6": "kn6", 69 | "ctrl7": "kn7", 70 | "ctrl8": "kn8", 71 | "switch1": "sw1", 72 | "switch2": "sw2", 73 | 74 | "knob": "kn", 75 | "key": "kA1", 76 | "ctrl": "kn", 77 | "cv": "cv1", 78 | "gate": "gt1", 79 | "switch": "sw1" 80 | }, 81 | "outs": { 82 | "cv": "cvout1", 83 | "cv1": "cvout1", 84 | "cv2": "cvout2", 85 | "gate": "gateout1", 86 | "gate1": "gateout1" 87 | }, 88 | "datas": { 89 | "leds": "dsy_leds" 90 | } 91 | }, 92 | "inputs": { 93 | "kn1": { 94 | "automap": true, 95 | "code": "hardware.GetKnobValue(hardware.KNOB_1);" 96 | }, 97 | "kn2": { 98 | "automap": true, 99 | "code": "hardware.GetKnobValue(hardware.KNOB_2);" 100 | }, 101 | "kn3": { 102 | "automap": true, 103 | "code": "hardware.GetKnobValue(hardware.KNOB_3);" 104 | }, 105 | "kn4": { 106 | "automap": true, 107 | "code": "hardware.GetKnobValue(hardware.KNOB_4);" 108 | }, 109 | "kn5": { 110 | "automap": true, 111 | "code": "hardware.GetKnobValue(hardware.KNOB_5);" 112 | }, 113 | "kn6": { 114 | "automap": true, 115 | "code": "hardware.GetKnobValue(hardware.KNOB_6);" 116 | }, 117 | "kn7": { 118 | "automap": true, 119 | "code": "hardware.GetKnobValue(hardware.KNOB_7);" 120 | }, 121 | "kn8": { 122 | "automap": true, 123 | "code": "hardware.GetKnobValue(hardware.KNOB_8);" 124 | }, 125 | "kA1": { 126 | "code": "(hardware.KeyboardState(0)?1.f:0.f);" 127 | }, 128 | "kA2": { 129 | "code": "(hardware.KeyboardState(1)?1.f:0.f);" 130 | }, 131 | "kA3": { 132 | "code": "(hardware.KeyboardState(2)?1.f:0.f);" 133 | }, 134 | "kA4": { 135 | "code": "(hardware.KeyboardState(3)?1.f:0.f);" 136 | }, 137 | "kA5": { 138 | "code": "(hardware.KeyboardState(4)?1.f:0.f);" 139 | }, 140 | "kA6": { 141 | "code": "(hardware.KeyboardState(5)?1.f:0.f);" 142 | }, 143 | "kA7": { 144 | "code": "(hardware.KeyboardState(6)?1.f:0.f);" 145 | }, 146 | "kA8": { 147 | "code": "(hardware.KeyboardState(7)?1.f:0.f);" 148 | }, 149 | "kB1": { 150 | "code": "(hardware.KeyboardState(8)?1.f:0.f);" 151 | }, 152 | "kB2": { 153 | "code": "(hardware.KeyboardState(9)?1.f:0.f);" 154 | }, 155 | "kB3": { 156 | "code": "(hardware.KeyboardState(10)?1.f:0.f);" 157 | }, 158 | "kB4": { 159 | "code": "(hardware.KeyboardState(11)?1.f:0.f);" 160 | }, 161 | "kB5": { 162 | "code": "(hardware.KeyboardState(12)?1.f:0.f);" 163 | }, 164 | "kB6": { 165 | "code": "(hardware.KeyboardState(13)?1.f:0.f);" 166 | }, 167 | "kB7": { 168 | "code": "(hardware.KeyboardState(14)?1.f:0.f);" 169 | }, 170 | "kB8": { 171 | "code": "(hardware.KeyboardState(15)?1.f:0.f);" 172 | }, 173 | "sw1": { 174 | "code": "(hardware.GetSwitch(0)->Pressed()?1.f:0.f);" 175 | }, 176 | "sw2": { 177 | "code": "(hardware.GetSwitch(1)->Pressed()?1.f:0.f);" 178 | }, 179 | "cv1": { 180 | "code": "hardware.GetCvValue(0);" 181 | }, 182 | "cv2": { 183 | "code": "hardware.GetCvValue(1);" 184 | }, 185 | "cv3": { 186 | "code": "hardware.GetCvValue(2);" 187 | }, 188 | "cv4": { 189 | "code": "hardware.GetCvValue(3);" 190 | }, 191 | "gt1": { 192 | "code": "(hardware.gate_in.State()?1.f:0.f);" 193 | } 194 | }, 195 | "outputs": { 196 | "cvout1": { 197 | "where":"main", 198 | "code": "hardware.SetCvOut1($ * 4095);" 199 | }, 200 | "cvout2": { 201 | "where":"main", 202 | "code": "hardware.SetCvOut2($ * 4095);" 203 | }, 204 | "gateout1": { 205 | "where":"audio", 206 | "code": "dsy_gpio_write(&hardware.gate_out, $ > 0.f);" 207 | } 208 | }, 209 | "datahandlers": { 210 | "dsy_leds": { 211 | "where":"display", 212 | "code": "daisy.setFieldLedsFromData($);" 213 | } 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /javascript/oopsy.snoop.js: -------------------------------------------------------------------------------- 1 | 2 | autowatch = 1; 3 | inlets = 2; 4 | outlets = 3; 5 | 6 | var path = ""; 7 | var target = "patch"; 8 | var samplerate = "48kHz"; 9 | var blocksize = "48"; 10 | var boost = 1; 11 | var fastmath = 0; 12 | var sep = "/"; 13 | var dict = new Dict(); 14 | 15 | function bang() { 16 | configure(true); 17 | } 18 | 19 | function configure(doExport) { 20 | var pat = this.patcher.parentpatcher; 21 | var topmost_pat = pat; 22 | while (topmost_pat.parentpatcher) { 23 | topmost_pat = topmost_pat.parentpatcher; 24 | } 25 | if (!topmost_pat.filepath) { 26 | error("oopsy: your patcher needs to be saved first\n"); 27 | pat.message("write"); 28 | return false; 29 | } 30 | var export_path = extractFilepath(topmost_pat.filepath); 31 | // send message out to convert this path 32 | // response will update the variable `path`: 33 | outlet(2, export_path); 34 | 35 | var names = []; 36 | var cpps = []; 37 | var errors = 0; 38 | 39 | // find gen~ objects in a patcher: 40 | function find_gens(pat) { 41 | dict.clear(); 42 | var default_name = pat.name || "gen"; 43 | // iterate all gen~ objects in the patcher 44 | // to set their export name, path, and scripting name 45 | var obj = pat.firstobject; 46 | while (obj) { 47 | if (obj.maxclass.toString() == "patcher") { 48 | var subpat = obj.subpatcher() 49 | if (subpat) find_gens(subpat); 50 | 51 | } else if (obj.maxclass.toString() == "gen~") { 52 | var name = default_name; 53 | if (obj.getattr("title")) { 54 | name = obj.getattr("title").toString(); 55 | } else if (obj.getattr("gen")) { 56 | name = obj.getattr("gen").toString(); 57 | } 58 | // sanitize: 59 | name = safename(name); 60 | // sanitize via scripting name too: 61 | while (name != obj.varname.toString()) { 62 | // try to apply it: 63 | obj.varname = name; 64 | name = safename(obj.varname); 65 | } 66 | // ensure exportname matches: 67 | obj.message("exportname", name); 68 | // ensure each gen~ has an export path configured: 69 | obj.message("exportfolder", export_path); 70 | 71 | if (doExport) { 72 | obj.message("export_json"); 73 | 74 | // this might not work on the first pass, since it can take a little time. 75 | dict.import_json(obj.getattr("exportfolder") + obj.getattr("exportname") + ".json") 76 | 77 | var ast = JSON.parse(dict.stringify()) 78 | if (ast.class == "Module") { 79 | var nodes = ast.block.children; 80 | for (var i=0; i 0 && chans > 0) { 89 | var wavname = node.name + ".wav" 90 | // write out that file so it can be referenced: 91 | buffer.send("write", obj.getattr("exportfolder") + wavname); 92 | //post("found buffer mapped Data", node.name, bufname, wavname, frames, chans) 93 | } 94 | } else if (node.typename == "Buffer") { 95 | // find the corresponding buffer~: 96 | var bufname = obj.getattr(node.name) 97 | var buffer = new Buffer(bufname) 98 | var frames = buffer.framecount() 99 | var chans = buffer.channelcount() 100 | 101 | if (frames < 0 || chans < 0) { 102 | error("oopsy: can't find buffer~ "+bufname); 103 | return; 104 | } 105 | 106 | // write it out: 107 | //buffer.send("write", obj.getattr("exportfolder") + bufname + ".wav"); 108 | 109 | post("oopsy: consider replacing [buffer "+node.name+"] with [data "+node.name+" "+frames+" "+chans+"]\n"); 110 | if (node.name != bufname) { 111 | post("and set @"+node.name, bufname, "on the gen~\n"); 112 | } 113 | error("gen~ cannot export with [buffer] objects\n") 114 | errors = 1; 115 | return; 116 | } 117 | } 118 | } 119 | } 120 | 121 | if (doExport) { 122 | obj.message("exportcode"); 123 | } 124 | names.push(name); 125 | 126 | cpps.push(path + sep + name + ".cpp") 127 | } 128 | obj = obj.nextobject; 129 | } 130 | } 131 | find_gens(pat, names, cpps, export_path) 132 | 133 | if (errors) { 134 | post("oopsy: aborting due to errors\n") 135 | return; 136 | } else if (names.length < 1) { 137 | post("oopsy: didn't find any valid gen~ objects\n") 138 | return; 139 | } 140 | 141 | var name = names.join("_") 142 | outlet(1, name) 143 | 144 | var args = [target, samplerate, "block"+blocksize].concat(cpps); 145 | if (boost) args.push("boost"); 146 | if (fastmath) args.push("fastmath"); 147 | outlet(0, args) 148 | } 149 | 150 | // convert names to use only characters safe for variable names 151 | function safename(s) { 152 | if (/[^a-zA-Z\d_]/.test(s)) { 153 | return s.replace(/[^a-zA-Z\d_]/g, function(x) { 154 | return '_' + x.charCodeAt(0).toString(16); 155 | }); 156 | } else { 157 | return s; 158 | } 159 | } 160 | 161 | // get the containing folder from a filepath: 162 | function extractFilepath(path) { 163 | var x; 164 | x = path.lastIndexOf('/'); 165 | if (x >= 0) { // Unix-based path 166 | sep = "/" 167 | return path.substr(0, x+1); 168 | } 169 | x = path.lastIndexOf('\\'); 170 | if (x >= 0) { // Windows-based path 171 | sep = "\\" 172 | return path.substr(0, x+1); 173 | } 174 | return path; // just the filename 175 | } 176 | -------------------------------------------------------------------------------- /code/oopsy.ctrl.smooth2.gendsp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "dsp.gen", 13 | "rect" : [ 84.0, 103.0, 466.0, 288.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-15", 44 | "linecount" : 8, 45 | "maxclass" : "comment", 46 | "numinlets" : 1, 47 | "numoutlets" : 0, 48 | "patching_rect" : [ 304.0, 62.0, 150.0, 114.0 ], 49 | "text" : "A 2-pole lowpass filter at 10Hz seems to effectively silence noise from hardware input ADCs.\n\nBut a 10Hz filter might be too slow to respond, if so, try the smooth3 option." 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "fontname" : "Lato", 56 | "fontsize" : 12.0, 57 | "id" : "obj-8", 58 | "maxclass" : "newobj", 59 | "numinlets" : 3, 60 | "numoutlets" : 1, 61 | "outlettype" : [ "" ], 62 | "patching_rect" : [ 118.0, 193.0, 46.0, 23.0 ], 63 | "text" : "mix" 64 | } 65 | 66 | } 67 | , { 68 | "box" : { 69 | "fontname" : "Lato", 70 | "fontsize" : 12.0, 71 | "id" : "obj-9", 72 | "maxclass" : "newobj", 73 | "numinlets" : 1, 74 | "numoutlets" : 1, 75 | "outlettype" : [ "" ], 76 | "patching_rect" : [ 118.0, 153.0, 45.0, 23.0 ], 77 | "text" : "history" 78 | } 79 | 80 | } 81 | , { 82 | "box" : { 83 | "fontname" : "Lato", 84 | "fontsize" : 12.0, 85 | "id" : "obj-4", 86 | "maxclass" : "newobj", 87 | "numinlets" : 1, 88 | "numoutlets" : 0, 89 | "patching_rect" : [ 118.0, 239.0, 37.0, 23.0 ], 90 | "text" : "out 1" 91 | } 92 | 93 | } 94 | , { 95 | "box" : { 96 | "fontname" : "Lato", 97 | "fontsize" : 12.0, 98 | "id" : "obj-6", 99 | "maxclass" : "newobj", 100 | "numinlets" : 3, 101 | "numoutlets" : 1, 102 | "outlettype" : [ "" ], 103 | "patching_rect" : [ 44.0, 193.0, 46.0, 23.0 ], 104 | "text" : "mix" 105 | } 106 | 107 | } 108 | , { 109 | "box" : { 110 | "fontname" : "Lato", 111 | "fontsize" : 12.0, 112 | "id" : "obj-14", 113 | "maxclass" : "newobj", 114 | "numinlets" : 1, 115 | "numoutlets" : 1, 116 | "outlettype" : [ "" ], 117 | "patching_rect" : [ 44.0, 153.0, 45.0, 23.0 ], 118 | "text" : "history" 119 | } 120 | 121 | } 122 | , { 123 | "box" : { 124 | "fontname" : "Lato", 125 | "fontsize" : 12.0, 126 | "id" : "obj-5", 127 | "maxclass" : "newobj", 128 | "numinlets" : 0, 129 | "numoutlets" : 1, 130 | "outlettype" : [ "" ], 131 | "patching_rect" : [ 127.5, 84.0, 158.0, 23.0 ], 132 | "text" : "fastsin 10*twopi/samplerate" 133 | } 134 | 135 | } 136 | , { 137 | "box" : { 138 | "fontname" : "Lato", 139 | "fontsize" : 12.0, 140 | "id" : "obj-1", 141 | "maxclass" : "newobj", 142 | "numinlets" : 0, 143 | "numoutlets" : 1, 144 | "outlettype" : [ "" ], 145 | "patching_rect" : [ 57.5, 84.0, 28.0, 23.0 ], 146 | "text" : "in 1" 147 | } 148 | 149 | } 150 | ], 151 | "lines" : [ { 152 | "patchline" : { 153 | "destination" : [ "obj-6", 1 ], 154 | "source" : [ "obj-1", 0 ] 155 | } 156 | 157 | } 158 | , { 159 | "patchline" : { 160 | "destination" : [ "obj-6", 0 ], 161 | "source" : [ "obj-14", 0 ] 162 | } 163 | 164 | } 165 | , { 166 | "patchline" : { 167 | "destination" : [ "obj-6", 2 ], 168 | "midpoints" : [ 137.0, 121.5, 80.5, 121.5 ], 169 | "order" : 1, 170 | "source" : [ "obj-5", 0 ] 171 | } 172 | 173 | } 174 | , { 175 | "patchline" : { 176 | "destination" : [ "obj-8", 2 ], 177 | "midpoints" : [ 137.0, 122.5, 154.5, 122.5 ], 178 | "order" : 0, 179 | "source" : [ "obj-5", 0 ] 180 | } 181 | 182 | } 183 | , { 184 | "patchline" : { 185 | "destination" : [ "obj-14", 0 ], 186 | "midpoints" : [ 53.5, 222.0, 31.5, 222.0, 31.5, 141.0, 53.5, 141.0 ], 187 | "order" : 1, 188 | "source" : [ "obj-6", 0 ] 189 | } 190 | 191 | } 192 | , { 193 | "patchline" : { 194 | "destination" : [ "obj-8", 1 ], 195 | "order" : 0, 196 | "source" : [ "obj-6", 0 ] 197 | } 198 | 199 | } 200 | , { 201 | "patchline" : { 202 | "destination" : [ "obj-4", 0 ], 203 | "order" : 0, 204 | "source" : [ "obj-8", 0 ] 205 | } 206 | 207 | } 208 | , { 209 | "patchline" : { 210 | "destination" : [ "obj-9", 0 ], 211 | "midpoints" : [ 127.5, 222.0, 105.5, 222.0, 105.5, 141.0, 127.5, 141.0 ], 212 | "order" : 1, 213 | "source" : [ "obj-8", 0 ] 214 | } 215 | 216 | } 217 | , { 218 | "patchline" : { 219 | "destination" : [ "obj-8", 0 ], 220 | "source" : [ "obj-9", 0 ] 221 | } 222 | 223 | } 224 | ] 225 | } 226 | 227 | } 228 | -------------------------------------------------------------------------------- /code/oopsy.cv2hz.gendsp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "dsp.gen", 13 | "rect" : [ 742.0, 324.0, 764.0, 299.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-1", 44 | "maxclass" : "newobj", 45 | "numinlets" : 0, 46 | "numoutlets" : 1, 47 | "outlettype" : [ "" ], 48 | "patching_rect" : [ 536.0, 20.0, 71.0, 22.0 ], 49 | "text" : "in 2 register" 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-33", 56 | "linecount" : 2, 57 | "maxclass" : "comment", 58 | "numinlets" : 1, 59 | "numoutlets" : 0, 60 | "patching_rect" : [ 551.0, 50.0, 187.0, 33.0 ], 61 | "text" : "add integer here to shift register (default 3v = C4 MIDI 60" 62 | } 63 | 64 | } 65 | , { 66 | "box" : { 67 | "id" : "obj-29", 68 | "maxclass" : "comment", 69 | "numinlets" : 1, 70 | "numoutlets" : 0, 71 | "patching_rect" : [ 489.0, 121.0, 150.0, 20.0 ], 72 | "text" : "chroma rotate A->C (3/12)" 73 | } 74 | 75 | } 76 | , { 77 | "box" : { 78 | "id" : "obj-24", 79 | "maxclass" : "newobj", 80 | "numinlets" : 1, 81 | "numoutlets" : 1, 82 | "outlettype" : [ "" ], 83 | "patching_rect" : [ 444.0, 121.0, 42.0, 22.0 ], 84 | "text" : "+ 0.25" 85 | } 86 | 87 | } 88 | , { 89 | "box" : { 90 | "id" : "obj-25", 91 | "maxclass" : "newobj", 92 | "numinlets" : 0, 93 | "numoutlets" : 1, 94 | "outlettype" : [ "" ], 95 | "patching_rect" : [ 421.0, 121.0, 19.0, 22.0 ], 96 | "text" : "2" 97 | } 98 | 99 | } 100 | , { 101 | "box" : { 102 | "id" : "obj-26", 103 | "maxclass" : "newobj", 104 | "numinlets" : 2, 105 | "numoutlets" : 1, 106 | "outlettype" : [ "" ], 107 | "patching_rect" : [ 421.0, 150.0, 50.0, 22.0 ], 108 | "text" : "fastpow" 109 | } 110 | 111 | } 112 | , { 113 | "box" : { 114 | "id" : "obj-27", 115 | "maxclass" : "newobj", 116 | "numinlets" : 1, 117 | "numoutlets" : 1, 118 | "outlettype" : [ "" ], 119 | "patching_rect" : [ 421.0, 179.0, 40.0, 22.0 ], 120 | "text" : "* 27.5" 121 | } 122 | 123 | } 124 | , { 125 | "box" : { 126 | "id" : "obj-15", 127 | "linecount" : 13, 128 | "maxclass" : "comment", 129 | "numinlets" : 1, 130 | "numoutlets" : 0, 131 | "patching_rect" : [ 23.0, 20.0, 356.0, 181.0 ], 132 | "text" : "CV to Hz is somewhat arbitrary, with a variety of conventions in wide use. \n\nOne widespread convention is that adding one volt will increase pitch by one octave (every 2^1/12 volt is a semitone), which is implemented here. The base tuning of an integer voltage is mostly a \"C\", which is also implemented here, but see https://learningmodular.com/matching-octaves-in-your-modular to see how much the register can vary in hardware; 0v, 1v, 2v and 3v are all widespread tunings for MIDI note 60 (C4) for example.\n\nYou can shift the register simply by adding an integer to the input CV. Here we chose 3v == C4/MIDI 60 as a default." 133 | } 134 | 135 | } 136 | , { 137 | "box" : { 138 | "id" : "obj-41", 139 | "maxclass" : "newobj", 140 | "numinlets" : 2, 141 | "numoutlets" : 1, 142 | "outlettype" : [ "" ], 143 | "patching_rect" : [ 444.0, 72.0, 29.5, 22.0 ], 144 | "text" : "+" 145 | } 146 | 147 | } 148 | , { 149 | "box" : { 150 | "id" : "obj-40", 151 | "maxclass" : "comment", 152 | "numinlets" : 1, 153 | "numoutlets" : 0, 154 | "patching_rect" : [ 489.0, 179.0, 150.0, 20.0 ], 155 | "text" : "frequency of MIDI A0" 156 | } 157 | 158 | } 159 | , { 160 | "box" : { 161 | "id" : "obj-12", 162 | "maxclass" : "newobj", 163 | "numinlets" : 0, 164 | "numoutlets" : 1, 165 | "outlettype" : [ "" ], 166 | "patching_rect" : [ 444.0, 20.0, 75.0, 22.0 ], 167 | "text" : "in 1 pitch_cv" 168 | } 169 | 170 | } 171 | , { 172 | "box" : { 173 | "id" : "obj-13", 174 | "maxclass" : "newobj", 175 | "numinlets" : 1, 176 | "numoutlets" : 0, 177 | "patching_rect" : [ 421.0, 252.0, 53.0, 22.0 ], 178 | "text" : "out 1 Hz" 179 | } 180 | 181 | } 182 | ], 183 | "lines" : [ { 184 | "patchline" : { 185 | "destination" : [ "obj-41", 1 ], 186 | "midpoints" : [ 545.5, 54.0, 464.0, 54.0 ], 187 | "source" : [ "obj-1", 0 ] 188 | } 189 | 190 | } 191 | , { 192 | "patchline" : { 193 | "destination" : [ "obj-41", 0 ], 194 | "source" : [ "obj-12", 0 ] 195 | } 196 | 197 | } 198 | , { 199 | "patchline" : { 200 | "destination" : [ "obj-26", 1 ], 201 | "source" : [ "obj-24", 0 ] 202 | } 203 | 204 | } 205 | , { 206 | "patchline" : { 207 | "destination" : [ "obj-26", 0 ], 208 | "source" : [ "obj-25", 0 ] 209 | } 210 | 211 | } 212 | , { 213 | "patchline" : { 214 | "destination" : [ "obj-27", 0 ], 215 | "source" : [ "obj-26", 0 ] 216 | } 217 | 218 | } 219 | , { 220 | "patchline" : { 221 | "destination" : [ "obj-13", 0 ], 222 | "source" : [ "obj-27", 0 ] 223 | } 224 | 225 | } 226 | , { 227 | "patchline" : { 228 | "destination" : [ "obj-24", 0 ], 229 | "source" : [ "obj-41", 0 ] 230 | } 231 | 232 | } 233 | ] 234 | } 235 | 236 | } 237 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Oopsy: Gen~ to Daisy 2 | 3 | Exporting Max Gen patchers for the ElectroSmith Daisy hardware platforms. 4 | 5 | [![Oopsy on Youtube](https://img.youtube.com/vi/fbd1CASqUmI/0.jpg)](https://www.youtube.com/playlist?list=PLZbxc8QYjD1eJHJEjzDkNB_zshbnVN6CH) 6 | 7 | Each Daisy binary can hold several gen~ patcher "apps", which can be switched between using the encoder (or switches on the DaisyField). 8 | 9 | ## How gen~ features map to Daisy 10 | 11 | Mostly this works by adding an appropriate name to the `in`, `out`, and `param` objects, but many features will also auto-map without special naming. 12 | 13 | ### Audio 14 | 15 | Hardware voltages are mapped to gen~ -1..1 16 | 17 | - `in 1`, `in 2` (and `in 3`, `in 4` on the DaisyPatch) are the audio device inputs. 18 | - Unavailable inputs re-use existing inputs; e.g. if the hardware has only 2 audio inputs, `in 3` refers to the same data as `in 1`. 19 | - `out 1`, `out 2` (and `out 3`, `out 4` on the DaisyPatch) are the audio device outputs. 20 | - Any hardware outputs that are not explicitly mapped in the patcher will repeat other audio signals (a kind of "normalling"), e.g. if the patcher has no `out 2` then the hardware output 2 will have the same data as hardware output 1. 21 | - If the patcher generates *more* audio channels than the hardware supports, these audio signals will be lost. 22 | 23 | ### CV/Gate/Knobs/Switches etc. 24 | 25 | - `param cv1`, `param gate2`, `param ctrl3`, `param knob1`, `param key2`, `param knob_delay`, `param switch_enable` etc. will give you the CV and gate inputs, hardware knobs, keys, etc. Use `@min` and `@max` to remap normalized ranges as desired. 26 | - Oopsy will try to auto-map any other `param` objects to any unused Knob/CV inputs. 27 | - `out cv1`, `out gate2`, etc. will send the signal to corresponding CV or Gate outputs if the device has them. `` just needs to be an output channel number that isn't being used for anything else. 28 | - CV/gate inputs and outputs are sampled at block rate, which on the default configuration of the Daisy is every 48 samples = 1ms. Trigger/gates shorter than 1ms might be missed. CV inputs might want some smoothing or filtering to eliminate noise/stepping etc. -- some example subpatchers are included for this purpose. 29 | - CV output timing might be negatively affected by OLED and MIDI activity. 30 | - Hardware voltages of 0-5v are mapped to gen~ 0..1, which will be remapped for `param` objects with `@min` and/or `@max` attributes accordingly. 31 | - Gate outs will be high if the gen~ signal is greater than zero. Gate outs shorter than one blocksize (default 48 samples) might be missed, but example subpatchers are included for automatically extending triggers so that this doesn't happen. 32 | - Note that on the DaisyPatch, the CV and Knob inputs are the same: knobs can offset the input voltage range, but the result is still 0-5v => @min..@max 33 | 34 | ### MIDI 35 | 36 | For [MIDI input](https://github.com/electro-smith/oopsy/wiki/MIDI-Input) and [MIDI output](https://github.com/electro-smith/oopsy/wiki/MIDI-output) features, see the wiki pages documentation. 37 | 38 | ## Using from within Max 39 | 40 | Drop a new `oopsy.patch` / `oopsy.field` etc. as desired object into a Max patch that contains one or more `gen~` objects. Or, use the templates from **File > New from Template > Oopsy_X**. Make sure the Max patch is saved. 41 | 42 | - Every time the Max patch is saved, it will trigger code generation and compilation, and will try to upload to a Daisy device if one is attached. 43 | - You can also send `bang` to the `oopsy` bpatcher to manually trigger this. 44 | - All the gen~ objects in the patcher will be uploaded to the device as "apps" which you can switch between dynamically. 45 | ### Multi-App 46 | 47 | Oopsy supports flashing Patch, Field, and Petal with multiple apps -- by default it will include every gen~ object in the same patcher as your `oopsy` bpatcher. The method to select apps depends on the target: 48 | 49 | - **Patch**: Long-hold the encoder to enter mode selection; rotate until you get to the app menu, and release the encoder. The currently-loaded app is displayed in inverted text. Rotate the encoder to select an app (marked with `>`) and push to load it. 50 | - **Field**: Long-hold SW1 to enter mode selection; tap SW2 until you get to the app menu, and release SW1. The currently-loaded app is displayed in inverted text. Tap SW2 to select an app (marked with `>`) and push SW1 to load it. 51 | - **Petal**: Hold the encoder down to go app selection. The currently-loaded app is displayed as a white led, and blue leds indicate available app slots. Rotate the encoder to select the desired app and release to load it. 52 | 53 | ## Using from the command line via Node.js 54 | 55 | If you want to use Oopsy without having Max open, you'll also want to have [Node.js](https://nodejs.org/en/) installed. 56 | 57 | From the /source folder, run `oopsy.js`, telling it what hardware platform to build for, and pointing it to one or more cpp files that have been exported from gen~: 58 | 59 | ``` 60 | # for DaisyPatch: 61 | node oopsy.js patch ../examples/simple.cpp 62 | # for DaisyField: 63 | node oopsy.js field ../examples/simple.cpp 64 | # etc. 65 | ``` 66 | 67 | - If the Daisy is plugged in via USB and ready to accept firmware (the two tact switches on the Daisy Seed have been pressed) then the oopsy script will upload the binary to the hardware (otherwise you'll get the harmless "Error '74") 68 | - Up to eight cpp files can be mentioned in the arguments; they will all be loaded onto the Daisy, with a simple menu system to switch between them. Use long encoder press to go into mode selection, rotate until you get the app menu, and release. Now rotate the encoder to select the app, and short press the encoder to load it. (On the Patch, use SW1 long press to go into mode selection, SW2 to swich mode until you get the app menu, release SW1; then press SW2 to select app, and SW1 to load it.) 69 | - If the `watch` keyword is added to the oopsy.js arguments, it will re-run the process every time any of the cpp files change -- which is handy since gen~ will re-export on every edit. 70 | - For a custom hardware configuration (other than Patch/Field/Petal/Pod) you can specify a JSON file in the arguments. 71 | 72 | ## Installing 73 | 74 | See the instructions [on the support site](https://daisy.audio/tutorials/oopsy-dev-env/) 75 | 76 | ## Licensing 77 | 78 | Oopsy is open source under the MIT license. Code generated by Oopsy is also MIT-licensed. 79 | 80 | For details of the licensing terms of code exported from gen~ see https://support.cycling74.com/hc/en-us/articles/360050779193-Gen-Code-Export-Licensing-FAQ. 81 | 82 | ## Discussion 83 | 84 | - Electrosmith: https://forum.electro-smith.com/c/integrations/oopsy-max-msp-gen 85 | - Cycling '74: https://cycling74.com 86 | - MW: https://www.modwiggler.com/forum/viewtopic.php?f=16&t=242322 87 | 88 | ----- 89 | 90 | Oopsy was authored by [Graham](https://github.com/grrrwaaa) [Wakefield](http://alicelab.world) in 2020-2021. 91 | -------------------------------------------------------------------------------- /code/oopsy.gate.min.gendsp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "dsp.gen", 13 | "rect" : [ 84.0, 103.0, 658.0, 409.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-5", 44 | "maxclass" : "newobj", 45 | "numinlets" : 1, 46 | "numoutlets" : 1, 47 | "outlettype" : [ "" ], 48 | "patching_rect" : [ 108.25, 267.0, 70.0, 22.0 ], 49 | "text" : "mstosamps" 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-4", 56 | "maxclass" : "newobj", 57 | "numinlets" : 1, 58 | "numoutlets" : 1, 59 | "outlettype" : [ "" ], 60 | "patching_rect" : [ 108.25, 291.0, 89.0, 22.0 ], 61 | "text" : "max vectorsize" 62 | } 63 | 64 | } 65 | , { 66 | "box" : { 67 | "id" : "obj-3", 68 | "maxclass" : "newobj", 69 | "numinlets" : 0, 70 | "numoutlets" : 1, 71 | "outlettype" : [ "" ], 72 | "patching_rect" : [ 108.25, 243.0, 62.0, 22.0 ], 73 | "text" : "param ms" 74 | } 75 | 76 | } 77 | , { 78 | "box" : { 79 | "id" : "obj-1", 80 | "linecount" : 10, 81 | "maxclass" : "comment", 82 | "numinlets" : 1, 83 | "numoutlets" : 0, 84 | "patching_rect" : [ 376.25, 130.0, 230.0, 141.0 ], 85 | "text" : "This subpatcher will extend any short click or gate (positive non-zero values) at least one signal vector's worth.\n\nThis may be necessary to ensure that any very short gates are not 'missed' by the GPIO output handling of the hardware (or indeed by any other hardware unable to register very short gates). " 86 | } 87 | 88 | } 89 | , { 90 | "box" : { 91 | "id" : "obj-41", 92 | "linecount" : 4, 93 | "maxclass" : "comment", 94 | "numinlets" : 1, 95 | "numoutlets" : 0, 96 | "patching_rect" : [ 112.25, 319.0, 196.0, 60.0 ], 97 | "text" : "keep gate high until 1+ control vectors have passed. On Daisy with the default blockrate of 1kHz this implies 1ms." 98 | } 99 | 100 | } 101 | , { 102 | "box" : { 103 | "id" : "obj-40", 104 | "maxclass" : "comment", 105 | "numinlets" : 1, 106 | "numoutlets" : 0, 107 | "patching_rect" : [ 108.25, 195.0, 229.0, 20.0 ], 108 | "text" : "Reset sample counter on rising edge" 109 | } 110 | 111 | } 112 | , { 113 | "box" : { 114 | "id" : "obj-37", 115 | "maxclass" : "comment", 116 | "numinlets" : 1, 117 | "numoutlets" : 0, 118 | "patching_rect" : [ 108.25, 133.5, 229.0, 20.0 ], 119 | "text" : "Detect rising edge" 120 | } 121 | 122 | } 123 | , { 124 | "box" : { 125 | "id" : "obj-36", 126 | "maxclass" : "comment", 127 | "numinlets" : 1, 128 | "numoutlets" : 0, 129 | "patching_rect" : [ 108.25, 102.0, 229.0, 20.0 ], 130 | "text" : "Basic daisy gate logic (gate high if > 0)" 131 | } 132 | 133 | } 134 | , { 135 | "box" : { 136 | "id" : "obj-34", 137 | "maxclass" : "newobj", 138 | "numinlets" : 2, 139 | "numoutlets" : 1, 140 | "outlettype" : [ "" ], 141 | "patching_rect" : [ 50.0, 333.0, 29.5, 22.0 ], 142 | "text" : "<=" 143 | } 144 | 145 | } 146 | , { 147 | "box" : { 148 | "id" : "obj-32", 149 | "maxclass" : "newobj", 150 | "numinlets" : 1, 151 | "numoutlets" : 1, 152 | "outlettype" : [ "" ], 153 | "patching_rect" : [ 50.0, 195.0, 33.0, 22.0 ], 154 | "text" : "+= 1" 155 | } 156 | 157 | } 158 | , { 159 | "box" : { 160 | "id" : "obj-31", 161 | "maxclass" : "newobj", 162 | "numinlets" : 1, 163 | "numoutlets" : 1, 164 | "outlettype" : [ "" ], 165 | "patching_rect" : [ 50.0, 160.5, 26.0, 22.0 ], 166 | "text" : "> 0" 167 | } 168 | 169 | } 170 | , { 171 | "box" : { 172 | "id" : "obj-30", 173 | "maxclass" : "newobj", 174 | "numinlets" : 1, 175 | "numoutlets" : 1, 176 | "outlettype" : [ "" ], 177 | "patching_rect" : [ 50.0, 133.5, 48.0, 22.0 ], 178 | "text" : "change" 179 | } 180 | 181 | } 182 | , { 183 | "box" : { 184 | "id" : "obj-27", 185 | "maxclass" : "newobj", 186 | "numinlets" : 1, 187 | "numoutlets" : 1, 188 | "outlettype" : [ "" ], 189 | "patching_rect" : [ 50.0, 100.0, 26.0, 22.0 ], 190 | "text" : "> 0" 191 | } 192 | 193 | } 194 | , { 195 | "box" : { 196 | "id" : "obj-43", 197 | "maxclass" : "newobj", 198 | "numinlets" : 0, 199 | "numoutlets" : 1, 200 | "outlettype" : [ "" ], 201 | "patching_rect" : [ 50.0, 40.0, 28.0, 22.0 ], 202 | "text" : "in 1" 203 | } 204 | 205 | } 206 | , { 207 | "box" : { 208 | "id" : "obj-44", 209 | "maxclass" : "newobj", 210 | "numinlets" : 1, 211 | "numoutlets" : 0, 212 | "patching_rect" : [ 50.25, 357.0, 35.0, 22.0 ], 213 | "text" : "out 1" 214 | } 215 | 216 | } 217 | ], 218 | "lines" : [ { 219 | "patchline" : { 220 | "destination" : [ "obj-30", 0 ], 221 | "source" : [ "obj-27", 0 ] 222 | } 223 | 224 | } 225 | , { 226 | "patchline" : { 227 | "destination" : [ "obj-5", 0 ], 228 | "source" : [ "obj-3", 0 ] 229 | } 230 | 231 | } 232 | , { 233 | "patchline" : { 234 | "destination" : [ "obj-31", 0 ], 235 | "source" : [ "obj-30", 0 ] 236 | } 237 | 238 | } 239 | , { 240 | "patchline" : { 241 | "destination" : [ "obj-32", 0 ], 242 | "source" : [ "obj-31", 0 ] 243 | } 244 | 245 | } 246 | , { 247 | "patchline" : { 248 | "destination" : [ "obj-34", 0 ], 249 | "source" : [ "obj-32", 0 ] 250 | } 251 | 252 | } 253 | , { 254 | "patchline" : { 255 | "destination" : [ "obj-44", 0 ], 256 | "source" : [ "obj-34", 0 ] 257 | } 258 | 259 | } 260 | , { 261 | "patchline" : { 262 | "destination" : [ "obj-34", 1 ], 263 | "source" : [ "obj-4", 0 ] 264 | } 265 | 266 | } 267 | , { 268 | "patchline" : { 269 | "destination" : [ "obj-27", 0 ], 270 | "source" : [ "obj-43", 0 ] 271 | } 272 | 273 | } 274 | , { 275 | "patchline" : { 276 | "destination" : [ "obj-4", 0 ], 277 | "source" : [ "obj-5", 0 ] 278 | } 279 | 280 | } 281 | ], 282 | "autosave" : 0 283 | } 284 | 285 | } 286 | -------------------------------------------------------------------------------- /code/oopsy.ctrl.smooth3.gendsp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "dsp.gen", 13 | "rect" : [ 84.0, 103.0, 466.0, 288.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-15", 44 | "linecount" : 13, 45 | "maxclass" : "comment", 46 | "numinlets" : 1, 47 | "numoutlets" : 0, 48 | "patching_rect" : [ 304.0, 35.0, 150.0, 181.0 ], 49 | "text" : "A 3-pole lowpass filter at 30Hz seems to effectively silence any noise from hardware input ADCs.\n\nMost of the time this level of aggressive smoothing is probably unnecessary, but for some applications that are very sensitive (e.g. setting long delay line lengths) it might be needed." 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "fontname" : "Lato", 56 | "fontsize" : 12.0, 57 | "id" : "obj-11", 58 | "maxclass" : "newobj", 59 | "numinlets" : 3, 60 | "numoutlets" : 1, 61 | "outlettype" : [ "" ], 62 | "patching_rect" : [ 190.5, 193.0, 46.0, 23.0 ], 63 | "text" : "mix" 64 | } 65 | 66 | } 67 | , { 68 | "box" : { 69 | "fontname" : "Lato", 70 | "fontsize" : 12.0, 71 | "id" : "obj-12", 72 | "maxclass" : "newobj", 73 | "numinlets" : 1, 74 | "numoutlets" : 1, 75 | "outlettype" : [ "" ], 76 | "patching_rect" : [ 190.5, 153.0, 45.0, 23.0 ], 77 | "text" : "history" 78 | } 79 | 80 | } 81 | , { 82 | "box" : { 83 | "fontname" : "Lato", 84 | "fontsize" : 12.0, 85 | "id" : "obj-8", 86 | "maxclass" : "newobj", 87 | "numinlets" : 3, 88 | "numoutlets" : 1, 89 | "outlettype" : [ "" ], 90 | "patching_rect" : [ 118.0, 193.0, 46.0, 23.0 ], 91 | "text" : "mix" 92 | } 93 | 94 | } 95 | , { 96 | "box" : { 97 | "fontname" : "Lato", 98 | "fontsize" : 12.0, 99 | "id" : "obj-9", 100 | "maxclass" : "newobj", 101 | "numinlets" : 1, 102 | "numoutlets" : 1, 103 | "outlettype" : [ "" ], 104 | "patching_rect" : [ 118.0, 153.0, 45.0, 23.0 ], 105 | "text" : "history" 106 | } 107 | 108 | } 109 | , { 110 | "box" : { 111 | "fontname" : "Lato", 112 | "fontsize" : 12.0, 113 | "id" : "obj-4", 114 | "maxclass" : "newobj", 115 | "numinlets" : 1, 116 | "numoutlets" : 0, 117 | "patching_rect" : [ 190.5, 240.0, 37.0, 23.0 ], 118 | "text" : "out 1" 119 | } 120 | 121 | } 122 | , { 123 | "box" : { 124 | "fontname" : "Lato", 125 | "fontsize" : 12.0, 126 | "id" : "obj-6", 127 | "maxclass" : "newobj", 128 | "numinlets" : 3, 129 | "numoutlets" : 1, 130 | "outlettype" : [ "" ], 131 | "patching_rect" : [ 44.0, 193.0, 46.0, 23.0 ], 132 | "text" : "mix" 133 | } 134 | 135 | } 136 | , { 137 | "box" : { 138 | "fontname" : "Lato", 139 | "fontsize" : 12.0, 140 | "id" : "obj-14", 141 | "maxclass" : "newobj", 142 | "numinlets" : 1, 143 | "numoutlets" : 1, 144 | "outlettype" : [ "" ], 145 | "patching_rect" : [ 44.0, 153.0, 45.0, 23.0 ], 146 | "text" : "history" 147 | } 148 | 149 | } 150 | , { 151 | "box" : { 152 | "fontname" : "Lato", 153 | "fontsize" : 12.0, 154 | "id" : "obj-5", 155 | "maxclass" : "newobj", 156 | "numinlets" : 0, 157 | "numoutlets" : 1, 158 | "outlettype" : [ "" ], 159 | "patching_rect" : [ 127.5, 84.0, 158.0, 23.0 ], 160 | "text" : "fastsin 30*twopi/samplerate" 161 | } 162 | 163 | } 164 | , { 165 | "box" : { 166 | "fontname" : "Lato", 167 | "fontsize" : 12.0, 168 | "id" : "obj-1", 169 | "maxclass" : "newobj", 170 | "numinlets" : 0, 171 | "numoutlets" : 1, 172 | "outlettype" : [ "" ], 173 | "patching_rect" : [ 57.5, 84.0, 28.0, 23.0 ], 174 | "text" : "in 1" 175 | } 176 | 177 | } 178 | ], 179 | "lines" : [ { 180 | "patchline" : { 181 | "destination" : [ "obj-6", 1 ], 182 | "source" : [ "obj-1", 0 ] 183 | } 184 | 185 | } 186 | , { 187 | "patchline" : { 188 | "destination" : [ "obj-12", 0 ], 189 | "midpoints" : [ 200.0, 222.0, 178.0, 222.0, 178.0, 141.0, 200.0, 141.0 ], 190 | "order" : 1, 191 | "source" : [ "obj-11", 0 ] 192 | } 193 | 194 | } 195 | , { 196 | "patchline" : { 197 | "destination" : [ "obj-4", 0 ], 198 | "order" : 0, 199 | "source" : [ "obj-11", 0 ] 200 | } 201 | 202 | } 203 | , { 204 | "patchline" : { 205 | "destination" : [ "obj-11", 0 ], 206 | "source" : [ "obj-12", 0 ] 207 | } 208 | 209 | } 210 | , { 211 | "patchline" : { 212 | "destination" : [ "obj-6", 0 ], 213 | "source" : [ "obj-14", 0 ] 214 | } 215 | 216 | } 217 | , { 218 | "patchline" : { 219 | "destination" : [ "obj-11", 2 ], 220 | "midpoints" : [ 137.0, 123.5, 227.0, 123.5 ], 221 | "order" : 0, 222 | "source" : [ "obj-5", 0 ] 223 | } 224 | 225 | } 226 | , { 227 | "patchline" : { 228 | "destination" : [ "obj-6", 2 ], 229 | "midpoints" : [ 137.0, 121.5, 80.5, 121.5 ], 230 | "order" : 2, 231 | "source" : [ "obj-5", 0 ] 232 | } 233 | 234 | } 235 | , { 236 | "patchline" : { 237 | "destination" : [ "obj-8", 2 ], 238 | "midpoints" : [ 137.0, 122.5, 154.5, 122.5 ], 239 | "order" : 1, 240 | "source" : [ "obj-5", 0 ] 241 | } 242 | 243 | } 244 | , { 245 | "patchline" : { 246 | "destination" : [ "obj-14", 0 ], 247 | "midpoints" : [ 53.5, 222.0, 31.5, 222.0, 31.5, 141.0, 53.5, 141.0 ], 248 | "order" : 1, 249 | "source" : [ "obj-6", 0 ] 250 | } 251 | 252 | } 253 | , { 254 | "patchline" : { 255 | "destination" : [ "obj-8", 1 ], 256 | "order" : 0, 257 | "source" : [ "obj-6", 0 ] 258 | } 259 | 260 | } 261 | , { 262 | "patchline" : { 263 | "destination" : [ "obj-11", 1 ], 264 | "order" : 0, 265 | "source" : [ "obj-8", 0 ] 266 | } 267 | 268 | } 269 | , { 270 | "patchline" : { 271 | "destination" : [ "obj-9", 0 ], 272 | "midpoints" : [ 127.5, 222.0, 105.5, 222.0, 105.5, 141.0, 127.5, 141.0 ], 273 | "order" : 1, 274 | "source" : [ "obj-8", 0 ] 275 | } 276 | 277 | } 278 | , { 279 | "patchline" : { 280 | "destination" : [ "obj-8", 0 ], 281 | "source" : [ "obj-9", 0 ] 282 | } 283 | 284 | } 285 | ] 286 | } 287 | 288 | } 289 | -------------------------------------------------------------------------------- /source/genlib_daisy.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************************************************* 2 | Cycling '74 License for Max-Generated Code for Export 3 | Copyright (c) 2016 Cycling '74 4 | The code that Max generates automatically and that end users are capable of exporting and using, and any 5 | associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author 6 | and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a 7 | copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, 8 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the 10 | Software must contact the copyright owner to determine if a license for commercial use is available, and the 11 | terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries 12 | to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based 13 | upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or 14 | other business whether for-profit or non-profit so long as the use itself is not a commercialization of the 15 | materials or a use that generates or is intended to generate income, revenue, sales or profit. 16 | The above copyright notice and this license shall be included in all copies or substantial portions of the Software. 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 18 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | *******************************************************************************************************************/ 23 | 24 | #include "genlib.h" 25 | #include // not cstdlib (causes problems with ARM embedded compiler) 26 | #include 27 | #include 28 | 29 | #ifndef MSP_ON_CLANG 30 | # include 31 | #endif 32 | 33 | #include 34 | #define malloc_size malloc_usable_size 35 | 36 | // DATA_MAXIMUM_ELEMENTS * 8 bytes = 256 mb limit 37 | #define DATA_MAXIMUM_ELEMENTS (33554432) 38 | 39 | t_ptr genlib_sysmem_resizeptr(void *ptr, t_ptr_size newsize) { 40 | // this function only seems to get called by SineData if reset() happens a second time 41 | // this shouldn't ever happen, so we default to new allocation: 42 | return genlib_sysmem_newptr(newsize); 43 | } 44 | 45 | void genlib_sysmem_freeptr(void *ptr) { 46 | // nothing to do, we are not running memory management here 47 | } 48 | 49 | void genlib_set_zero64(t_sample *memory, long size) { 50 | long i; 51 | for (i = 0; i < size; i++, memory++) *memory = 0.; 52 | } 53 | 54 | // NEED THIS FOR WINDOWS: 55 | void *operator new(size_t size) { return genlib_sysmem_newptr(size); } 56 | void *operator new[](size_t size) { return genlib_sysmem_newptr(size); } 57 | void operator delete(void *p) throw() { genlib_sysmem_freeptr(p); } 58 | void operator delete[](void *p) throw() { genlib_sysmem_freeptr(p); } 59 | 60 | void *genlib_obtain_reference_from_string(const char *name) { 61 | return 0; // to be implemented 62 | } 63 | 64 | // the rest is stuff to isolate gensym, attrs, atoms, buffers etc. 65 | t_genlib_buffer *genlib_obtain_buffer_from_reference(void *ref) { 66 | return 0; // to be implemented 67 | } 68 | 69 | t_genlib_err genlib_buffer_edit_begin(t_genlib_buffer *b) { 70 | return 0; // to be implemented 71 | } 72 | 73 | t_genlib_err genlib_buffer_edit_end(t_genlib_buffer *b, long valid) { 74 | return 0; // to be implemented 75 | } 76 | 77 | t_genlib_err genlib_buffer_getinfo(t_genlib_buffer *b, t_genlib_buffer_info *info) { 78 | return 0; // to be implemented 79 | } 80 | 81 | char *genlib_reference_getname(void *ref) { 82 | return 0; // to be implemented 83 | } 84 | 85 | void genlib_buffer_dirty(t_genlib_buffer *b) { 86 | // to be implemented 87 | } 88 | 89 | t_genlib_err genlib_buffer_perform_begin(t_genlib_buffer *b) { 90 | return 0; // to be implemented 91 | } 92 | void genlib_buffer_perform_end(t_genlib_buffer *b) { 93 | // to be implemented 94 | } 95 | 96 | t_sample gen_msp_pow(t_sample value, t_sample power) { 97 | return pow(value, power); 98 | } 99 | 100 | void genlib_data_setbuffer(t_genlib_data *b, void *ref) { 101 | //genlib_report_error("not supported for export targets\n"); 102 | } 103 | 104 | typedef struct { 105 | t_genlib_data_info info; 106 | t_sample cursor; // used by Delay 107 | //t_symbol * name; 108 | } t_dsp_gen_data; 109 | 110 | t_genlib_data *genlib_obtain_data_from_reference(void *ref) { 111 | t_dsp_gen_data *self = (t_dsp_gen_data *)genlib_sysmem_newptr(sizeof(t_dsp_gen_data)); 112 | self->info.dim = 0; 113 | self->info.channels = 0; 114 | self->info.data = 0; 115 | self->cursor = 0; 116 | return (t_genlib_data *)self; 117 | } 118 | 119 | t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info) { 120 | t_dsp_gen_data *self = (t_dsp_gen_data *)b; 121 | info->dim = self->info.dim; 122 | info->channels = self->info.channels; 123 | info->data = self->info.data; 124 | return GENLIB_ERR_NONE; 125 | } 126 | 127 | void genlib_data_release(t_genlib_data *b) { 128 | t_dsp_gen_data *self = (t_dsp_gen_data *)b; 129 | if (self->info.data) { 130 | genlib_sysmem_freeptr(self->info.data); 131 | self->info.data = 0; 132 | } 133 | } 134 | 135 | long genlib_data_getcursor(t_genlib_data *b) { 136 | t_dsp_gen_data *self = (t_dsp_gen_data *)b; 137 | return long(self->cursor); 138 | } 139 | 140 | void genlib_data_setcursor(t_genlib_data *b, long cursor) { 141 | t_dsp_gen_data *self = (t_dsp_gen_data *)b; 142 | self->cursor = t_sample(cursor); 143 | } 144 | 145 | void genlib_data_resize(t_genlib_data *b, long s, long c) { 146 | t_dsp_gen_data *self = (t_dsp_gen_data *)b; 147 | 148 | size_t sz, oldsz, copysz; 149 | t_sample *old = 0; 150 | t_sample *replaced = 0; 151 | int i, j, copydim, copychannels, olddim, oldchannels; 152 | 153 | //printf("data resize %d %d\n", s, c); 154 | 155 | // cache old for copying: 156 | old = self->info.data; 157 | olddim = self->info.dim; 158 | oldchannels = self->info.channels; 159 | 160 | // limit [data] size: 161 | if (s * c > DATA_MAXIMUM_ELEMENTS) { 162 | s = DATA_MAXIMUM_ELEMENTS/c; 163 | genlib_report_message("warning: constraining [data] to < 256MB"); 164 | } 165 | // bytes required: 166 | sz = sizeof(t_sample) * s * c; 167 | oldsz = sizeof(t_sample) * olddim * oldchannels; 168 | 169 | if (old && sz == oldsz) { 170 | // no need to re-allocate, just resize 171 | // careful, audio thread may still be using it: 172 | if (s > olddim) { 173 | self->info.channels = c; 174 | self->info.dim = s; 175 | } else { 176 | self->info.dim = s; 177 | self->info.channels = c; 178 | } 179 | 180 | genlib_set_zero64(self->info.data, s * c); 181 | return; 182 | 183 | } else { 184 | 185 | // allocate new: 186 | replaced = (t_sample *)genlib_sysmem_newptr(sz); 187 | 188 | // check allocation: 189 | if (replaced == 0) { 190 | genlib_report_error("data: out of memory"); 191 | // try to reallocate with a default/minimal size instead: 192 | if (s > 512 || c > 1) { 193 | genlib_data_resize((t_genlib_data *)self, 512, 1); 194 | } else { 195 | // if this fails, then Max is kaput anyway... 196 | genlib_data_resize((t_genlib_data *)self, 4, 1); 197 | } 198 | return; 199 | } 200 | 201 | // fill with zeroes: 202 | genlib_set_zero64(replaced, s * c); 203 | 204 | // copy in old data: 205 | if (old) { 206 | // frames to copy: 207 | // clamped: 208 | copydim = olddim > s ? s : olddim; 209 | // use memcpy if channels haven't changed: 210 | if (c == oldchannels) { 211 | copysz = sizeof(t_sample) * copydim * c; 212 | //post("reset resize (same channels) %p %p, %d", self->info.data, old, copysz); 213 | memcpy(replaced, old, copysz); 214 | } else { 215 | // memcpy won't work if channels have changed, 216 | // because data is interleaved. 217 | // clamp channels copied: 218 | copychannels = oldchannels > c ? c : oldchannels; 219 | //post("reset resize (different channels) %p %p, %d %d", self->info.data, old, copydim, copychannels); 220 | for (i = 0; i < copydim; i++) { 221 | for (j = 0; j < copychannels; j++) { 222 | replaced[j + i * c] = old[j + i * oldchannels]; 223 | } 224 | } 225 | } 226 | } 227 | 228 | // now update info: 229 | if (old == 0) { 230 | self->info.data = replaced; 231 | self->info.dim = s; 232 | self->info.channels = c; 233 | } else { 234 | // need to be careful; the audio thread may still be using it 235 | // since dsp_gen_data is preserved through edits 236 | // the order of resizing has to be carefully done 237 | // to prevent indexing out of bounds 238 | // (or maybe I'm being too paranoid here...) 239 | if (oldsz > sz) { 240 | // shrink size first 241 | if (s > olddim) { 242 | self->info.channels = c; 243 | self->info.dim = s; 244 | } else { 245 | self->info.dim = s; 246 | self->info.channels = c; 247 | } 248 | self->info.data = replaced; 249 | } else { 250 | // shrink size after 251 | self->info.data = replaced; 252 | if (s > olddim) { 253 | self->info.channels = c; 254 | self->info.dim = s; 255 | } else { 256 | self->info.dim = s; 257 | self->info.channels = c; 258 | } 259 | } 260 | 261 | // done with old: 262 | genlib_sysmem_freeptr(old); 263 | 264 | } 265 | } 266 | } 267 | 268 | void genlib_reset_complete(void *data) {} 269 | 270 | size_t genlib_getstatesize(CommonState *cself, getparameter_method getmethod) { 271 | return 0; 272 | } 273 | 274 | short genlib_getstate(CommonState *cself, char *state, getparameter_method getmethod) { 275 | return 0; 276 | } 277 | 278 | short genlib_setstate(CommonState *cself, const char *state, setparameter_method setmethod) { 279 | return 0; 280 | } 281 | 282 | -------------------------------------------------------------------------------- /help/oopsy.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 429.0, 121.0, 640.0, 480.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-11", 44 | "linecount" : 4, 45 | "maxclass" : "comment", 46 | "numinlets" : 1, 47 | "numoutlets" : 0, 48 | "patching_rect" : [ 315.0, 271.0, 261.0, 60.0 ], 49 | "text" : "If the max patch has more than one gen~ object, all will be combined into a \"multi-app\" binary for the Daisy. Use the device encoder or switches to select the apps. " 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-10", 56 | "linecount" : 2, 57 | "maxclass" : "comment", 58 | "numinlets" : 1, 59 | "numoutlets" : 0, 60 | "patching_rect" : [ 315.0, 229.0, 259.0, 33.0 ], 61 | "text" : "If the device is plugged in via USB and ready to flash, oopsy will also try to flash it." 62 | } 63 | 64 | } 65 | , { 66 | "box" : { 67 | "bubble" : 1, 68 | "id" : "obj-7", 69 | "linecount" : 4, 70 | "maxclass" : "comment", 71 | "numinlets" : 1, 72 | "numoutlets" : 0, 73 | "patching_rect" : [ 300.0, 155.0, 278.0, 64.0 ], 74 | "text" : "Drop in an 'oopsy.patch' / 'oopsy.field' / 'oopsy.petal' etc. bpatcher in any Max patch with gen~ objects. Send it a bang (or save the patch) to compile!" 75 | } 76 | 77 | } 78 | , { 79 | "box" : { 80 | "bgmode" : 0, 81 | "border" : 0, 82 | "clickthrough" : 0, 83 | "enablehscroll" : 0, 84 | "enablevscroll" : 0, 85 | "id" : "obj-9", 86 | "lockeddragscroll" : 0, 87 | "maxclass" : "bpatcher", 88 | "name" : "oopsy.maxpat", 89 | "numinlets" : 1, 90 | "numoutlets" : 0, 91 | "offset" : [ 0.0, 0.0 ], 92 | "patching_rect" : [ 163.0, 155.0, 128.0, 128.0 ], 93 | "viewvisibility" : 1 94 | } 95 | 96 | } 97 | , { 98 | "box" : { 99 | "id" : "obj-5", 100 | "maxclass" : "newobj", 101 | "numinlets" : 2, 102 | "numoutlets" : 2, 103 | "outlettype" : [ "signal", "signal" ], 104 | "patcher" : { 105 | "fileversion" : 1, 106 | "appversion" : { 107 | "major" : 8, 108 | "minor" : 1, 109 | "revision" : 8, 110 | "architecture" : "x64", 111 | "modernui" : 1 112 | } 113 | , 114 | "classnamespace" : "dsp.gen", 115 | "rect" : [ 84.0, 103.0, 600.0, 450.0 ], 116 | "bglocked" : 0, 117 | "openinpresentation" : 0, 118 | "default_fontsize" : 12.0, 119 | "default_fontface" : 0, 120 | "default_fontname" : "Arial", 121 | "gridonopen" : 1, 122 | "gridsize" : [ 15.0, 15.0 ], 123 | "gridsnaponopen" : 1, 124 | "objectsnaponopen" : 1, 125 | "statusbarvisible" : 2, 126 | "toolbarvisible" : 1, 127 | "lefttoolbarpinned" : 0, 128 | "toptoolbarpinned" : 0, 129 | "righttoolbarpinned" : 0, 130 | "bottomtoolbarpinned" : 0, 131 | "toolbars_unpinned_last_save" : 0, 132 | "tallnewobj" : 0, 133 | "boxanimatetime" : 200, 134 | "enablehscroll" : 1, 135 | "enablevscroll" : 1, 136 | "devicewidth" : 0.0, 137 | "description" : "", 138 | "digest" : "", 139 | "tags" : "", 140 | "style" : "", 141 | "subpatcher_template" : "", 142 | "assistshowspatchername" : 0, 143 | "boxes" : [ { 144 | "box" : { 145 | "id" : "obj-10", 146 | "maxclass" : "newobj", 147 | "numinlets" : 0, 148 | "numoutlets" : 1, 149 | "outlettype" : [ "" ], 150 | "patching_rect" : [ 78.0, 192.0, 37.0, 22.0 ], 151 | "text" : "noise" 152 | } 153 | 154 | } 155 | , { 156 | "box" : { 157 | "id" : "obj-9", 158 | "maxclass" : "newobj", 159 | "numinlets" : 2, 160 | "numoutlets" : 1, 161 | "outlettype" : [ "" ], 162 | "patching_rect" : [ 62.0, 227.0, 29.5, 22.0 ], 163 | "text" : "*" 164 | } 165 | 166 | } 167 | , { 168 | "box" : { 169 | "id" : "obj-8", 170 | "maxclass" : "newobj", 171 | "numinlets" : 1, 172 | "numoutlets" : 2, 173 | "outlettype" : [ "", "" ], 174 | "patching_rect" : [ 165.0, 192.0, 36.0, 22.0 ], 175 | "text" : "cycle" 176 | } 177 | 178 | } 179 | , { 180 | "box" : { 181 | "id" : "obj-7", 182 | "maxclass" : "newobj", 183 | "numinlets" : 0, 184 | "numoutlets" : 1, 185 | "outlettype" : [ "" ], 186 | "patching_rect" : [ 62.0, 149.0, 62.0, 22.0 ], 187 | "text" : "param ctrl" 188 | } 189 | 190 | } 191 | , { 192 | "box" : { 193 | "id" : "obj-6", 194 | "maxclass" : "newobj", 195 | "numinlets" : 0, 196 | "numoutlets" : 1, 197 | "outlettype" : [ "" ], 198 | "patching_rect" : [ 165.0, 149.0, 188.0, 22.0 ], 199 | "text" : "param ctrl2 @min 200 @max 800" 200 | } 201 | 202 | } 203 | , { 204 | "box" : { 205 | "id" : "obj-5", 206 | "maxclass" : "newobj", 207 | "numinlets" : 1, 208 | "numoutlets" : 0, 209 | "patching_rect" : [ 142.0, 337.0, 35.0, 22.0 ], 210 | "text" : "out 2" 211 | } 212 | 213 | } 214 | , { 215 | "box" : { 216 | "id" : "obj-1", 217 | "maxclass" : "newobj", 218 | "numinlets" : 0, 219 | "numoutlets" : 1, 220 | "outlettype" : [ "" ], 221 | "patching_rect" : [ 33.0, 73.0, 28.0, 22.0 ], 222 | "text" : "in 1" 223 | } 224 | 225 | } 226 | , { 227 | "box" : { 228 | "id" : "obj-2", 229 | "maxclass" : "newobj", 230 | "numinlets" : 0, 231 | "numoutlets" : 1, 232 | "outlettype" : [ "" ], 233 | "patching_rect" : [ 142.0, 73.0, 28.0, 22.0 ], 234 | "text" : "in 2" 235 | } 236 | 237 | } 238 | , { 239 | "box" : { 240 | "id" : "obj-4", 241 | "maxclass" : "newobj", 242 | "numinlets" : 1, 243 | "numoutlets" : 0, 244 | "patching_rect" : [ 33.0, 337.0, 35.0, 22.0 ], 245 | "text" : "out 1" 246 | } 247 | 248 | } 249 | ], 250 | "lines" : [ { 251 | "patchline" : { 252 | "destination" : [ "obj-4", 0 ], 253 | "source" : [ "obj-1", 0 ] 254 | } 255 | 256 | } 257 | , { 258 | "patchline" : { 259 | "destination" : [ "obj-9", 1 ], 260 | "source" : [ "obj-10", 0 ] 261 | } 262 | 263 | } 264 | , { 265 | "patchline" : { 266 | "destination" : [ "obj-5", 0 ], 267 | "source" : [ "obj-2", 0 ] 268 | } 269 | 270 | } 271 | , { 272 | "patchline" : { 273 | "destination" : [ "obj-8", 0 ], 274 | "source" : [ "obj-6", 0 ] 275 | } 276 | 277 | } 278 | , { 279 | "patchline" : { 280 | "destination" : [ "obj-9", 0 ], 281 | "source" : [ "obj-7", 0 ] 282 | } 283 | 284 | } 285 | , { 286 | "patchline" : { 287 | "destination" : [ "obj-5", 0 ], 288 | "source" : [ "obj-8", 0 ] 289 | } 290 | 291 | } 292 | , { 293 | "patchline" : { 294 | "destination" : [ "obj-4", 0 ], 295 | "source" : [ "obj-9", 0 ] 296 | } 297 | 298 | } 299 | ] 300 | } 301 | , 302 | "patching_rect" : [ 13.0, 261.0, 88.0, 22.0 ], 303 | "saved_object_attributes" : { 304 | "exportfolder" : "Macintosh HD:/Users/grrrwaaa/Documents/Max 8/Packages/oopsy/help/", 305 | "exportname" : "oopsymaxhelp" 306 | } 307 | , 308 | "text" : "gen~", 309 | "varname" : "oopsymaxhelp" 310 | } 311 | 312 | } 313 | , { 314 | "box" : { 315 | "id" : "obj-4", 316 | "maxclass" : "comment", 317 | "numinlets" : 1, 318 | "numoutlets" : 0, 319 | "patching_rect" : [ 13.0, 48.0, 123.0, 20.0 ], 320 | "text" : "Daisy from gen~" 321 | } 322 | 323 | } 324 | , { 325 | "box" : { 326 | "fontname" : "Arial Bold Italic", 327 | "fontsize" : 24.0, 328 | "id" : "obj-2", 329 | "maxclass" : "comment", 330 | "numinlets" : 1, 331 | "numoutlets" : 0, 332 | "patching_rect" : [ 13.0, 13.0, 123.0, 33.0 ], 333 | "text" : "Oopsy" 334 | } 335 | 336 | } 337 | ], 338 | "lines" : [ ], 339 | "parameters" : { 340 | "obj-9::obj-32" : [ "live.text[2]", "FILTER", 0 ], 341 | "obj-9::obj-36" : [ "live.menu[1]", "live.menu", 0 ], 342 | "obj-9::obj-4" : [ "live.menu[2]", "live.menu", 0 ], 343 | "parameterbanks" : { 344 | 345 | } 346 | , 347 | "inherited_shortname" : 1 348 | } 349 | , 350 | "dependency_cache" : [ { 351 | "name" : "oopsy.maxpat", 352 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/patchers", 353 | "patcherrelativepath" : "../patchers", 354 | "type" : "JSON", 355 | "implicit" : 1 356 | } 357 | , { 358 | "name" : "oopsy.snoop.js", 359 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 360 | "patcherrelativepath" : "../javascript", 361 | "type" : "TEXT", 362 | "implicit" : 1 363 | } 364 | , { 365 | "name" : "oopsy.node4max.js", 366 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 367 | "patcherrelativepath" : "../javascript", 368 | "type" : "TEXT", 369 | "implicit" : 1 370 | } 371 | ], 372 | "autosave" : 0 373 | } 374 | 375 | } 376 | -------------------------------------------------------------------------------- /source/gen_dsp/genlib.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************************************************* 2 | Cycling '74 License for Max-Generated Code for Export 3 | Copyright (c) 2016 Cycling '74 4 | The code that Max generates automatically and that end users are capable of exporting and using, and any 5 | associated documentation files (the “Software”) is a work of authorship for which Cycling '74 is the author 6 | and owner for copyright purposes. A license is hereby granted, free of charge, to any person obtaining a 7 | copy of the Software (“Licensee”) to use, copy, modify, merge, publish, and distribute copies of the Software, 8 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 9 | The Software is licensed to Licensee only for non-commercial use. Users who wish to make commercial use of the 10 | Software must contact the copyright owner to determine if a license for commercial use is available, and the 11 | terms and conditions for same, which may include fees or royalties. For commercial use, please send inquiries 12 | to licensing@cycling74.com. The determination of whether a use is commercial use or non-commercial use is based 13 | upon the use, not the user. The Software may be used by individuals, institutions, governments, corporations, or 14 | other business whether for-profit or non-profit so long as the use itself is not a commercialization of the 15 | materials or a use that generates or is intended to generate income, revenue, sales or profit. 16 | The above copyright notice and this license shall be included in all copies or substantial portions of the Software. 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 18 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 20 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | *******************************************************************************************************************/ 23 | 24 | #ifndef GENLIB_H 25 | #define GENLIB_H 1 26 | 27 | // #if defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7) // embedded ARM cortex support 28 | // #define GENLIB_USE_ARMMATH 29 | // #define GENLIB_USE_FASTMATH 30 | // #endif // defined(ARM_MATH_CM4) || defined(ARM_MATH_CM7) 31 | 32 | #if defined (__arm__) // general ARM support 33 | #define GENLIB_USE_FLOAT32 34 | #endif 35 | 36 | //////////// genlib_common.h //////////// 37 | // common data structure header file -- this is the stuff required by the 38 | // common code and accessed by the export and max code 39 | 40 | #define DSP_GEN_MAX_SIGNALS 128 41 | 42 | #ifdef GENLIB_USE_FLOAT32 43 | typedef float t_sample; 44 | typedef float t_param; 45 | #else 46 | typedef double t_sample; 47 | typedef double t_param; 48 | #endif 49 | typedef char *t_ptr; 50 | 51 | typedef long t_genlib_err; 52 | typedef enum { 53 | GENLIB_ERR_NONE = 0, ///< No error 54 | GENLIB_ERR_GENERIC = -1, ///< Generic error 55 | GENLIB_ERR_INVALID_PTR = -2, ///< Invalid Pointer 56 | GENLIB_ERR_DUPLICATE = -3, ///< Duplicate 57 | GENLIB_ERR_OUT_OF_MEM = -4, ///< Out of memory 58 | GENLIB_ERR_LOOP_OVERFLOW = 100, // too many iterations of loops in perform() 59 | GENLIB_ERR_NULL_BUFFER = 101 // missing signal data in perform() 60 | } e_genlib_errorcodes; 61 | 62 | typedef enum { 63 | GENLIB_PARAMTYPE_FLOAT = 0, 64 | GENLIB_PARAMTYPE_SYM = 1 65 | } e_genlib_paramtypes; 66 | 67 | struct ParamInfo 68 | { 69 | t_param defaultvalue; 70 | void *defaultref; 71 | char hasinputminmax; 72 | char hasminmax; 73 | t_param inputmin, inputmax; 74 | t_param outputmin, outputmax; 75 | const char *name; 76 | const char *units; 77 | int paramtype; // 0 -> float64, 1 -> symbol (table name) 78 | t_param exp; // future, for scaling 79 | }; 80 | 81 | struct CommonState 82 | { 83 | t_sample sr; 84 | int vs; 85 | int numins; 86 | int numouts; 87 | const char **inputnames; 88 | const char **outputnames; 89 | int numparams; 90 | ParamInfo *params; 91 | 92 | void *parammap; // implementation-dependent 93 | void *api; // implementation-dependent 94 | }; 95 | 96 | // opaque interface to float32 buffer: 97 | typedef struct _genlib_buffer t_genlib_buffer; 98 | typedef struct { 99 | char b_name[256]; ///< name of the buffer 100 | float *b_samples; ///< stored with interleaved channels if multi-channel 101 | long b_frames; ///< number of sample frames (each one is sizeof(float) * b_nchans bytes) 102 | long b_nchans; ///< number of channels 103 | long b_size; ///< size of buffer in floats 104 | float b_sr; ///< sampling rate of the buffer 105 | long b_modtime; ///< last modified time ("dirty" method) 106 | long b_rfu[57]; ///< reserved for future use 107 | } t_genlib_buffer_info; 108 | 109 | // opaque interface to float64 buffer: 110 | typedef struct _genlib_data t_genlib_data; 111 | typedef struct { 112 | int dim, channels; 113 | t_sample * data; 114 | } t_genlib_data_info; 115 | 116 | typedef void (*setparameter_method) (CommonState *, long, t_param, void *); 117 | typedef void (*getparameter_method) (CommonState *, long, t_param *); 118 | 119 | 120 | //////////// genlib.h //////////// 121 | // genlib.h -- max (gen~) version 122 | 123 | #ifndef GEN_WINDOWS 124 | # ifndef _SIZE_T 125 | # define _SIZE_T 126 | typedef __typeof__(sizeof(int)) size_t; 127 | # endif 128 | #endif 129 | 130 | #ifndef __INT32_TYPE__ 131 | # define __INT32_TYPE__ int 132 | #endif 133 | 134 | #ifdef MSP_ON_CLANG 135 | // gen~ hosted: 136 | typedef unsigned __INT32_TYPE__ uint32_t; 137 | typedef unsigned __INT64_TYPE__ uint64_t; 138 | #else 139 | # ifdef __GNUC__ 140 | # include 141 | # endif 142 | #endif 143 | 144 | #define inf (__DBL_MAX__) 145 | #define GEN_UINT_MAX (4294967295) 146 | #define TWO_TO_32 (4294967296.0) 147 | 148 | #define C74_CONST const 149 | 150 | // max_types.h: 151 | #ifdef C74_X64 152 | typedef unsigned long long t_ptr_uint; 153 | typedef long long t_ptr_int; 154 | typedef double t_atom_float; 155 | typedef t_ptr_uint t_getbytes_size; 156 | #else 157 | typedef unsigned long t_ptr_uint; 158 | typedef long t_ptr_int; 159 | typedef float t_atom_float; 160 | typedef short t_getbytes_size; 161 | #endif // C74_X64 162 | 163 | typedef uint32_t t_uint32; 164 | typedef t_ptr_int t_atom_long; // the type that is an A_LONG in an atom 165 | 166 | typedef t_ptr_int t_int; ///< an integer @ingroup misc 167 | typedef t_ptr_uint t_ptr_size; ///< unsigned pointer-sized value for counting (like size_t) @ingroup misc 168 | typedef t_ptr_int t_atom_long; ///< the type that is an A_LONG in a #t_atom @ingroup misc 169 | typedef t_atom_long t_max_err; ///< an integer value suitable to be returned as an error code @ingroup misc 170 | 171 | extern "C" { 172 | extern t_sample gen_msp_pow (t_sample, t_sample); 173 | 174 | #ifdef MSP_ON_CLANG 175 | // TODO: remove (for debugging only) 176 | //int printf(const char *fmt, ...); 177 | 178 | // math.h: 179 | extern double acos(double); 180 | extern double asin(double); 181 | extern double atan(double); 182 | extern double atan2(double, double); 183 | extern double cos(double); 184 | extern double sin(double); 185 | extern double tan(double); 186 | extern double acosh(double); 187 | extern double asinh(double); 188 | extern double atanh(double); 189 | extern double cosh(double); 190 | extern double sinh(double); 191 | extern double tanh(double); 192 | extern double exp(double); 193 | extern double log(double); 194 | extern double log10(double); 195 | extern double fmod(double, double); 196 | extern double modf(double, double *); 197 | extern double fabs(double); 198 | extern double hypot(double, double); 199 | extern double pow(double, double); 200 | 201 | extern double sqrt(double); 202 | extern double ceil(double); 203 | extern double floor(double); 204 | extern double trunc(double); 205 | extern double round(double); 206 | extern int abs(int); 207 | 208 | extern char *strcpy(char *, const char *); 209 | #else 210 | # include // abs 211 | #endif // MSP_ON_CLANG 212 | 213 | 214 | // #if defined(GENLIB_USE_ARMMATH) // ARM embedded support 215 | // # include "arm_math.h" 216 | // # define sin(x) arm_sin_f32(x) 217 | // # define sinf(x) arm_sin_f32(x) 218 | // # define cos(x) arm_cos_f32(x) 219 | // # define cosf(x) arm_cos_f32(x) 220 | // # define sqrt(x) arm_sqrtf(x) 221 | // # define sqrtf(x) arm_sqrtf(x) 222 | // # define rand(...) arm_rand32() 223 | // # undef RAND_MAX 224 | // # define RAND_MAX UINT32_MAX 225 | // #endif // GENLIB_USE_ARMMATH 226 | 227 | #if defined(GENLIB_USE_FASTMATH) 228 | # include 229 | # define tan(x) fastertanfull(x) 230 | # define exp(x) fasterexp(x) 231 | # define log2(x) fasterlog2(x) 232 | # define pow(x,y) fasterpow(x,y) 233 | # define pow2(x) fasterpow2(x) 234 | # define atan2(x,y) fasteratan2(x,y) 235 | # define tanh(x) fastertanh(x) 236 | # if !defined(GENLIB_USE_ARMMATH) 237 | # define sin(x) fastersinfull(x) 238 | # define cos(x) fastercosfull(x) 239 | # endif 240 | #endif // GENLIB_USE_FASTMATH 241 | 242 | // string reference handling: 243 | void *genlib_obtain_reference_from_string(const char *name); 244 | char *genlib_reference_getname(void *ref); 245 | 246 | // buffer handling: 247 | t_genlib_buffer *genlib_obtain_buffer_from_reference(void *ref); 248 | t_genlib_err genlib_buffer_edit_begin(t_genlib_buffer *b); 249 | t_genlib_err genlib_buffer_edit_end(t_genlib_buffer *b, long valid); 250 | t_genlib_err genlib_buffer_getinfo(t_genlib_buffer *b, t_genlib_buffer_info *info); 251 | void genlib_buffer_dirty(t_genlib_buffer *b); 252 | t_genlib_err genlib_buffer_perform_begin(t_genlib_buffer *b); 253 | void genlib_buffer_perform_end(t_genlib_buffer *b); 254 | 255 | // data handling: 256 | t_genlib_data *genlib_obtain_data_from_reference(void *ref); 257 | t_genlib_err genlib_data_getinfo(t_genlib_data *b, t_genlib_data_info *info); 258 | void genlib_data_resize(t_genlib_data *b, long dim, long channels); 259 | void genlib_data_setbuffer(t_genlib_data *b, void *ref); 260 | void genlib_data_release(t_genlib_data *b); 261 | void genlib_data_setcursor(t_genlib_data *b, long cursor); 262 | long genlib_data_getcursor(t_genlib_data *b); 263 | 264 | // other notification: 265 | void genlib_reset_complete(void *data); 266 | 267 | // get/set state of parameters 268 | size_t genlib_getstatesize(CommonState *cself, getparameter_method getmethod); 269 | short genlib_getstate(CommonState *cself, char *state, getparameter_method getmethod); 270 | short genlib_setstate(CommonState *cself, const char *state, setparameter_method setmethod); 271 | 272 | }; // extern "C" 273 | 274 | #endif // GENLIB_H 275 | 276 | -------------------------------------------------------------------------------- /code/oopsy.midi.format.gendsp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "dsp.gen", 13 | "rect" : [ 124.0, 78.0, 959.0, 916.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-4", 44 | "linecount" : 32, 45 | "maxclass" : "comment", 46 | "numinlets" : 1, 47 | "numoutlets" : 0, 48 | "patching_rect" : [ 675.0, 132.0, 207.0, 435.0 ], 49 | "text" : "Comment out any MIDI handling in here that you don't need, to save on processor cycles. \n\nVelocity, pressure, and CC values are expected in 0..1 ranges. Bend is expected in -1..1 range. \nAll other inputs are expected as integers (midi note numbers, program/cc numbers, etc.\n\nTrig inputs should be single-sample duration to avoid spamming the midi buffers with too much data. \n\nThe channel input value is used by whichever event is being triggered. \n\nNote that this implementation will handle at most 1 note event per sample -- this is more than most hardware can respond to, but it does mean you may need to think about how to distribute chords over successive samples. Similar for CC values etc. \n\n\nThis is good enough for testing, but you might want to consider a different way of handling MIDI according to your needs. " 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-1", 56 | "maxclass" : "newobj", 57 | "numinlets" : 0, 58 | "numoutlets" : 1, 59 | "outlettype" : [ "" ], 60 | "patching_rect" : [ 643.410256410256693, 48.0, 80.0, 22.0 ], 61 | "text" : "in 15 channel" 62 | } 63 | 64 | } 65 | , { 66 | "box" : { 67 | "id" : "obj-35", 68 | "maxclass" : "newobj", 69 | "numinlets" : 0, 70 | "numoutlets" : 1, 71 | "outlettype" : [ "" ], 72 | "patching_rect" : [ 574.410256410256693, 73.0, 65.0, 22.0 ], 73 | "text" : "in 14 bend" 74 | } 75 | 76 | } 77 | , { 78 | "box" : { 79 | "id" : "obj-36", 80 | "maxclass" : "newobj", 81 | "numinlets" : 0, 82 | "numoutlets" : 1, 83 | "outlettype" : [ "" ], 84 | "patching_rect" : [ 558.410256410256579, 48.0, 81.0, 22.0 ], 85 | "text" : "in 13 bendtrig" 86 | } 87 | 88 | } 89 | , { 90 | "box" : { 91 | "id" : "obj-32", 92 | "maxclass" : "newobj", 93 | "numinlets" : 0, 94 | "numoutlets" : 1, 95 | "outlettype" : [ "" ], 96 | "patching_rect" : [ 469.571428571428669, 73.0, 83.0, 22.0 ], 97 | "text" : "in 12 program" 98 | } 99 | 100 | } 101 | , { 102 | "box" : { 103 | "id" : "obj-34", 104 | "maxclass" : "newobj", 105 | "numinlets" : 0, 106 | "numoutlets" : 1, 107 | "outlettype" : [ "" ], 108 | "patching_rect" : [ 454.571428571428555, 48.0, 98.0, 22.0 ], 109 | "text" : "in 11 programtrig" 110 | } 111 | 112 | } 113 | , { 114 | "box" : { 115 | "id" : "obj-29", 116 | "maxclass" : "newobj", 117 | "numinlets" : 0, 118 | "numoutlets" : 1, 119 | "outlettype" : [ "" ], 120 | "patching_rect" : [ 378.857142857142833, 97.0, 66.0, 22.0 ], 121 | "text" : "in 10 ccval" 122 | } 123 | 124 | } 125 | , { 126 | "box" : { 127 | "id" : "obj-30", 128 | "maxclass" : "newobj", 129 | "numinlets" : 0, 130 | "numoutlets" : 1, 131 | "outlettype" : [ "" ], 132 | "patching_rect" : [ 367.857142857142833, 73.0, 68.0, 22.0 ], 133 | "text" : "in 9 ccnum" 134 | } 135 | 136 | } 137 | , { 138 | "box" : { 139 | "id" : "obj-31", 140 | "maxclass" : "newobj", 141 | "numinlets" : 0, 142 | "numoutlets" : 1, 143 | "outlettype" : [ "" ], 144 | "patching_rect" : [ 367.857142857142833, 48.0, 61.0, 22.0 ], 145 | "text" : "in 8 cctrig" 146 | } 147 | 148 | } 149 | , { 150 | "box" : { 151 | "id" : "obj-28", 152 | "maxclass" : "newobj", 153 | "numinlets" : 0, 154 | "numoutlets" : 1, 155 | "outlettype" : [ "" ], 156 | "patching_rect" : [ 257.404761904761983, 73.0, 101.0, 22.0 ], 157 | "text" : "in 7 pressurenote" 158 | } 159 | 160 | } 161 | , { 162 | "box" : { 163 | "id" : "obj-20", 164 | "maxclass" : "newobj", 165 | "numinlets" : 0, 166 | "numoutlets" : 1, 167 | "outlettype" : [ "" ], 168 | "patching_rect" : [ 249.404761904761983, 48.0, 109.0, 22.0 ], 169 | "text" : "in 6 pressureispoly" 170 | } 171 | 172 | } 173 | , { 174 | "box" : { 175 | "id" : "obj-21", 176 | "maxclass" : "newobj", 177 | "numinlets" : 0, 178 | "numoutlets" : 1, 179 | "outlettype" : [ "" ], 180 | "patching_rect" : [ 163.071428571428584, 73.0, 78.0, 22.0 ], 181 | "text" : "in 5 pressure" 182 | } 183 | 184 | } 185 | , { 186 | "box" : { 187 | "id" : "obj-22", 188 | "maxclass" : "newobj", 189 | "numinlets" : 0, 190 | "numoutlets" : 1, 191 | "outlettype" : [ "" ], 192 | "patching_rect" : [ 151.071428571428584, 48.0, 95.0, 22.0 ], 193 | "text" : "in 4 pressuretrig" 194 | } 195 | 196 | } 197 | , { 198 | "box" : { 199 | "id" : "obj-17", 200 | "maxclass" : "newobj", 201 | "numinlets" : 0, 202 | "numoutlets" : 1, 203 | "outlettype" : [ "" ], 204 | "patching_rect" : [ 44.333333333333371, 97.0, 70.0, 22.0 ], 205 | "text" : "in 3 notevel" 206 | } 207 | 208 | } 209 | , { 210 | "box" : { 211 | "id" : "obj-16", 212 | "maxclass" : "newobj", 213 | "numinlets" : 0, 214 | "numoutlets" : 1, 215 | "outlettype" : [ "" ], 216 | "patching_rect" : [ 36.333333333333371, 73.0, 78.0, 22.0 ], 217 | "text" : "in 2 notenum" 218 | } 219 | 220 | } 221 | , { 222 | "box" : { 223 | "id" : "obj-15", 224 | "maxclass" : "newobj", 225 | "numinlets" : 0, 226 | "numoutlets" : 1, 227 | "outlettype" : [ "" ], 228 | "patching_rect" : [ 21.0, 48.0, 71.0, 22.0 ], 229 | "text" : "in 1 notetrig" 230 | } 231 | 232 | } 233 | , { 234 | "box" : { 235 | "code" : "History written, read;\nData outbuf(2048);\nchannel = wrap(int(in15-1), 0, 16);\nnotetrig, notenum, notevel = in1, in2, in3;\nif (notetrig) {\n\tpoke(outbuf, (144+channel)/256, written+1, boundmode=\"wrap\");\n\tpoke(outbuf, (notenum)/256, written+2, boundmode=\"wrap\");\n\tpoke(outbuf, (notevel*127)/256, written+3, boundmode=\"wrap\");\n\twritten += 3;\n}\npressuretrig, pressure, pressureispoly, pressurenote = in4, in5, in6, in7;\nif (pressuretrig && pressureispoly) {\n\tpoke(outbuf, (160+channel)/256, written+1, boundmode=\"wrap\");\n\tpoke(outbuf, (pressurenote)/256, written+2, boundmode=\"wrap\");\n\tpoke(outbuf, (pressure*127)/256, written+3, boundmode=\"wrap\");\n\twritten += 3;\n} else if (pressuretrig) {\n\tpoke(outbuf, (208+channel)/256, written+1, boundmode=\"wrap\");\n\tpoke(outbuf, (pressure*127)/256, written+2, boundmode=\"wrap\");\n\twritten += 2;\n}\ncctrig, ccnum, ccval = in8, in9, in10;\nif (cctrig) {\n\tpoke(outbuf, (176+channel)/256, written+1, boundmode=\"wrap\");\n\tpoke(outbuf, (ccnum)/256, written+2, boundmode=\"wrap\");\n\tpoke(outbuf, (ccval*127)/256, written+3, boundmode=\"wrap\");\n\twritten += 3;\n}\nprogramtrig, program = in11, in12;\nif (programtrig) {\n\tpoke(outbuf, (192+channel)/256, written+1, boundmode=\"wrap\");\n\tpoke(outbuf, (program)/256, written+2, boundmode=\"wrap\");\n\twritten += 2;\n}\nbendtrig, bend = in13, in14;\nif (bendtrig) {\n\tc = int(bend*8192)-8192;\n\tpoke(outbuf, (224+channel)/256, written+1, boundmode=\"wrap\");\n\tpoke(outbuf, (floor(c/128))/256, written+2, boundmode=\"wrap\");\n\tpoke(outbuf, (wrap(c, 0, 128))/256, written+3, boundmode=\"wrap\");\n\twritten += 3;\n}\n// TODO: sysex, clock, etc.\n\nwritten = wrap(written, 0, dim(outbuf));\nnewdata = (read != written);\nread = wrap(read + newdata, 0, dim(outbuf));\nout1 = newdata ? peek(outbuf, read) : -1;", 236 | "fontface" : 0, 237 | "fontname" : "", 238 | "fontsize" : 12.0, 239 | "id" : "obj-3", 240 | "maxclass" : "codebox", 241 | "numinlets" : 15, 242 | "numoutlets" : 1, 243 | "outlettype" : [ "" ], 244 | "patching_rect" : [ 21.0, 132.0, 626.0, 726.0 ] 245 | } 246 | 247 | } 248 | , { 249 | "box" : { 250 | "id" : "obj-13", 251 | "maxclass" : "newobj", 252 | "numinlets" : 1, 253 | "numoutlets" : 0, 254 | "patching_rect" : [ 21.0, 863.0, 89.0, 22.0 ], 255 | "text" : "out 1 midibytes" 256 | } 257 | 258 | } 259 | ], 260 | "lines" : [ { 261 | "patchline" : { 262 | "destination" : [ "obj-3", 14 ], 263 | "source" : [ "obj-1", 0 ] 264 | } 265 | 266 | } 267 | , { 268 | "patchline" : { 269 | "destination" : [ "obj-3", 0 ], 270 | "source" : [ "obj-15", 0 ] 271 | } 272 | 273 | } 274 | , { 275 | "patchline" : { 276 | "destination" : [ "obj-3", 1 ], 277 | "source" : [ "obj-16", 0 ] 278 | } 279 | 280 | } 281 | , { 282 | "patchline" : { 283 | "destination" : [ "obj-3", 2 ], 284 | "source" : [ "obj-17", 0 ] 285 | } 286 | 287 | } 288 | , { 289 | "patchline" : { 290 | "destination" : [ "obj-3", 5 ], 291 | "source" : [ "obj-20", 0 ] 292 | } 293 | 294 | } 295 | , { 296 | "patchline" : { 297 | "destination" : [ "obj-3", 4 ], 298 | "source" : [ "obj-21", 0 ] 299 | } 300 | 301 | } 302 | , { 303 | "patchline" : { 304 | "destination" : [ "obj-3", 3 ], 305 | "source" : [ "obj-22", 0 ] 306 | } 307 | 308 | } 309 | , { 310 | "patchline" : { 311 | "destination" : [ "obj-3", 6 ], 312 | "source" : [ "obj-28", 0 ] 313 | } 314 | 315 | } 316 | , { 317 | "patchline" : { 318 | "destination" : [ "obj-3", 9 ], 319 | "source" : [ "obj-29", 0 ] 320 | } 321 | 322 | } 323 | , { 324 | "patchline" : { 325 | "destination" : [ "obj-13", 0 ], 326 | "source" : [ "obj-3", 0 ] 327 | } 328 | 329 | } 330 | , { 331 | "patchline" : { 332 | "destination" : [ "obj-3", 8 ], 333 | "source" : [ "obj-30", 0 ] 334 | } 335 | 336 | } 337 | , { 338 | "patchline" : { 339 | "destination" : [ "obj-3", 7 ], 340 | "source" : [ "obj-31", 0 ] 341 | } 342 | 343 | } 344 | , { 345 | "patchline" : { 346 | "destination" : [ "obj-3", 11 ], 347 | "source" : [ "obj-32", 0 ] 348 | } 349 | 350 | } 351 | , { 352 | "patchline" : { 353 | "destination" : [ "obj-3", 10 ], 354 | "source" : [ "obj-34", 0 ] 355 | } 356 | 357 | } 358 | , { 359 | "patchline" : { 360 | "destination" : [ "obj-3", 13 ], 361 | "source" : [ "obj-35", 0 ] 362 | } 363 | 364 | } 365 | , { 366 | "patchline" : { 367 | "destination" : [ "obj-3", 12 ], 368 | "source" : [ "obj-36", 0 ] 369 | } 370 | 371 | } 372 | ], 373 | "autosave" : 0 374 | } 375 | 376 | } 377 | -------------------------------------------------------------------------------- /examples/simple.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 1006.0, 80.0, 640.0, 480.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 | "bgmode" : 0, 44 | "border" : 0, 45 | "clickthrough" : 0, 46 | "enablehscroll" : 0, 47 | "enablevscroll" : 0, 48 | "id" : "obj-9", 49 | "lockeddragscroll" : 0, 50 | "maxclass" : "bpatcher", 51 | "name" : "oopsy.maxpat", 52 | "numinlets" : 1, 53 | "numoutlets" : 0, 54 | "offset" : [ 0.0, 0.0 ], 55 | "patching_rect" : [ 108.5, 111.0, 128.0, 128.0 ], 56 | "viewvisibility" : 1 57 | } 58 | 59 | } 60 | , { 61 | "box" : { 62 | "id" : "obj-1", 63 | "maxclass" : "newobj", 64 | "numinlets" : 2, 65 | "numoutlets" : 2, 66 | "outlettype" : [ "signal", "signal" ], 67 | "patcher" : { 68 | "fileversion" : 1, 69 | "appversion" : { 70 | "major" : 8, 71 | "minor" : 1, 72 | "revision" : 8, 73 | "architecture" : "x64", 74 | "modernui" : 1 75 | } 76 | , 77 | "classnamespace" : "dsp.gen", 78 | "rect" : [ 1046.0, 312.0, 600.0, 450.0 ], 79 | "bglocked" : 0, 80 | "openinpresentation" : 0, 81 | "default_fontsize" : 12.0, 82 | "default_fontface" : 0, 83 | "default_fontname" : "Arial", 84 | "gridonopen" : 1, 85 | "gridsize" : [ 15.0, 15.0 ], 86 | "gridsnaponopen" : 1, 87 | "objectsnaponopen" : 1, 88 | "statusbarvisible" : 2, 89 | "toolbarvisible" : 1, 90 | "lefttoolbarpinned" : 0, 91 | "toptoolbarpinned" : 0, 92 | "righttoolbarpinned" : 0, 93 | "bottomtoolbarpinned" : 0, 94 | "toolbars_unpinned_last_save" : 0, 95 | "tallnewobj" : 0, 96 | "boxanimatetime" : 200, 97 | "enablehscroll" : 1, 98 | "enablevscroll" : 1, 99 | "devicewidth" : 0.0, 100 | "description" : "", 101 | "digest" : "", 102 | "tags" : "", 103 | "style" : "", 104 | "subpatcher_template" : "", 105 | "assistshowspatchername" : 0, 106 | "boxes" : [ { 107 | "box" : { 108 | "id" : "obj-11", 109 | "maxclass" : "newobj", 110 | "numinlets" : 0, 111 | "numoutlets" : 1, 112 | "outlettype" : [ "" ], 113 | "patching_rect" : [ 396.0, 188.0, 160.0, 22.0 ], 114 | "text" : "param foo @min -1 @max 1" 115 | } 116 | 117 | } 118 | , { 119 | "box" : { 120 | "id" : "obj-10", 121 | "maxclass" : "newobj", 122 | "numinlets" : 0, 123 | "numoutlets" : 1, 124 | "outlettype" : [ "" ], 125 | "patching_rect" : [ 275.5, 108.0, 79.0, 22.0 ], 126 | "text" : "param knob2" 127 | } 128 | 129 | } 130 | , { 131 | "box" : { 132 | "id" : "obj-9", 133 | "maxclass" : "newobj", 134 | "numinlets" : 0, 135 | "numoutlets" : 1, 136 | "outlettype" : [ "" ], 137 | "patching_rect" : [ 165.0, 108.0, 79.0, 22.0 ], 138 | "text" : "param knob1" 139 | } 140 | 141 | } 142 | , { 143 | "box" : { 144 | "id" : "obj-6", 145 | "maxclass" : "newobj", 146 | "numinlets" : 2, 147 | "numoutlets" : 1, 148 | "outlettype" : [ "" ], 149 | "patching_rect" : [ 232.0, 155.0, 47.0, 22.0 ], 150 | "text" : "mix 0.5" 151 | } 152 | 153 | } 154 | , { 155 | "box" : { 156 | "id" : "obj-3", 157 | "maxclass" : "newobj", 158 | "numinlets" : 2, 159 | "numoutlets" : 1, 160 | "outlettype" : [ "" ], 161 | "patching_rect" : [ 139.0, 167.5, 47.0, 22.0 ], 162 | "text" : "mix 0.5" 163 | } 164 | 165 | } 166 | , { 167 | "box" : { 168 | "id" : "obj-13", 169 | "maxclass" : "newobj", 170 | "numinlets" : 0, 171 | "numoutlets" : 1, 172 | "outlettype" : [ "" ], 173 | "patching_rect" : [ 232.0, 77.0, 65.0, 22.0 ], 174 | "text" : "param cv2" 175 | } 176 | 177 | } 178 | , { 179 | "box" : { 180 | "id" : "obj-14", 181 | "maxclass" : "newobj", 182 | "numinlets" : 0, 183 | "numoutlets" : 2, 184 | "outlettype" : [ "", "" ], 185 | "patching_rect" : [ 285.5, 200.0, 59.0, 22.0 ], 186 | "text" : "cycle 800" 187 | } 188 | 189 | } 190 | , { 191 | "box" : { 192 | "id" : "obj-15", 193 | "maxclass" : "newobj", 194 | "numinlets" : 2, 195 | "numoutlets" : 1, 196 | "outlettype" : [ "" ], 197 | "patching_rect" : [ 254.0, 233.0, 29.5, 22.0 ], 198 | "text" : "*" 199 | } 200 | 201 | } 202 | , { 203 | "box" : { 204 | "id" : "obj-12", 205 | "maxclass" : "newobj", 206 | "numinlets" : 0, 207 | "numoutlets" : 1, 208 | "outlettype" : [ "" ], 209 | "patching_rect" : [ 118.0, 77.0, 65.0, 22.0 ], 210 | "text" : "param cv1" 211 | } 212 | 213 | } 214 | , { 215 | "box" : { 216 | "id" : "obj-8", 217 | "maxclass" : "newobj", 218 | "numinlets" : 0, 219 | "numoutlets" : 1, 220 | "outlettype" : [ "" ], 221 | "patching_rect" : [ 178.5, 200.0, 37.0, 22.0 ], 222 | "text" : "noise" 223 | } 224 | 225 | } 226 | , { 227 | "box" : { 228 | "id" : "obj-7", 229 | "maxclass" : "newobj", 230 | "numinlets" : 2, 231 | "numoutlets" : 1, 232 | "outlettype" : [ "" ], 233 | "patching_rect" : [ 147.0, 233.0, 29.5, 22.0 ], 234 | "text" : "*" 235 | } 236 | 237 | } 238 | , { 239 | "box" : { 240 | "id" : "obj-5", 241 | "maxclass" : "newobj", 242 | "numinlets" : 1, 243 | "numoutlets" : 0, 244 | "patching_rect" : [ 86.0, 309.0, 35.0, 22.0 ], 245 | "text" : "out 2" 246 | } 247 | 248 | } 249 | , { 250 | "box" : { 251 | "id" : "obj-1", 252 | "maxclass" : "newobj", 253 | "numinlets" : 0, 254 | "numoutlets" : 1, 255 | "outlettype" : [ "" ], 256 | "patching_rect" : [ 39.0, 163.0, 28.0, 22.0 ], 257 | "text" : "in 1" 258 | } 259 | 260 | } 261 | , { 262 | "box" : { 263 | "id" : "obj-2", 264 | "maxclass" : "newobj", 265 | "numinlets" : 0, 266 | "numoutlets" : 1, 267 | "outlettype" : [ "" ], 268 | "patching_rect" : [ 86.0, 163.0, 28.0, 22.0 ], 269 | "text" : "in 2" 270 | } 271 | 272 | } 273 | , { 274 | "box" : { 275 | "id" : "obj-4", 276 | "maxclass" : "newobj", 277 | "numinlets" : 1, 278 | "numoutlets" : 0, 279 | "patching_rect" : [ 39.0, 309.0, 35.0, 22.0 ], 280 | "text" : "out 1" 281 | } 282 | 283 | } 284 | ], 285 | "lines" : [ { 286 | "patchline" : { 287 | "destination" : [ "obj-4", 0 ], 288 | "source" : [ "obj-1", 0 ] 289 | } 290 | 291 | } 292 | , { 293 | "patchline" : { 294 | "destination" : [ "obj-6", 1 ], 295 | "source" : [ "obj-10", 0 ] 296 | } 297 | 298 | } 299 | , { 300 | "patchline" : { 301 | "destination" : [ "obj-3", 0 ], 302 | "source" : [ "obj-12", 0 ] 303 | } 304 | 305 | } 306 | , { 307 | "patchline" : { 308 | "destination" : [ "obj-6", 0 ], 309 | "source" : [ "obj-13", 0 ] 310 | } 311 | 312 | } 313 | , { 314 | "patchline" : { 315 | "destination" : [ "obj-15", 1 ], 316 | "source" : [ "obj-14", 0 ] 317 | } 318 | 319 | } 320 | , { 321 | "patchline" : { 322 | "destination" : [ "obj-4", 0 ], 323 | "order" : 1, 324 | "source" : [ "obj-15", 0 ] 325 | } 326 | 327 | } 328 | , { 329 | "patchline" : { 330 | "destination" : [ "obj-5", 0 ], 331 | "order" : 0, 332 | "source" : [ "obj-15", 0 ] 333 | } 334 | 335 | } 336 | , { 337 | "patchline" : { 338 | "destination" : [ "obj-5", 0 ], 339 | "source" : [ "obj-2", 0 ] 340 | } 341 | 342 | } 343 | , { 344 | "patchline" : { 345 | "destination" : [ "obj-7", 0 ], 346 | "source" : [ "obj-3", 0 ] 347 | } 348 | 349 | } 350 | , { 351 | "patchline" : { 352 | "destination" : [ "obj-15", 0 ], 353 | "source" : [ "obj-6", 0 ] 354 | } 355 | 356 | } 357 | , { 358 | "patchline" : { 359 | "destination" : [ "obj-4", 0 ], 360 | "order" : 1, 361 | "source" : [ "obj-7", 0 ] 362 | } 363 | 364 | } 365 | , { 366 | "patchline" : { 367 | "destination" : [ "obj-5", 0 ], 368 | "order" : 0, 369 | "source" : [ "obj-7", 0 ] 370 | } 371 | 372 | } 373 | , { 374 | "patchline" : { 375 | "destination" : [ "obj-7", 1 ], 376 | "source" : [ "obj-8", 0 ] 377 | } 378 | 379 | } 380 | , { 381 | "patchline" : { 382 | "destination" : [ "obj-3", 1 ], 383 | "source" : [ "obj-9", 0 ] 384 | } 385 | 386 | } 387 | ] 388 | } 389 | , 390 | "patching_rect" : [ 24.0, 261.0, 39.0, 22.0 ], 391 | "saved_object_attributes" : { 392 | "exportfolder" : "Macintosh HD:/Users/grrrwaaa/Documents/Max 8/Packages/oopsy/examples/", 393 | "exportname" : "simple" 394 | } 395 | , 396 | "text" : "gen~", 397 | "varname" : "simple" 398 | } 399 | 400 | } 401 | ], 402 | "lines" : [ ], 403 | "parameters" : { 404 | "obj-9::obj-32" : [ "live.text[2]", "FILTER", 0 ], 405 | "obj-9::obj-33" : [ "live.text[1]", "FILTER", 0 ], 406 | "obj-9::obj-34" : [ "live.text[3]", "FILTER", 0 ], 407 | "parameterbanks" : { 408 | 409 | } 410 | , 411 | "inherited_shortname" : 1 412 | } 413 | , 414 | "dependency_cache" : [ { 415 | "name" : "oopsy.maxpat", 416 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/patchers", 417 | "patcherrelativepath" : "../patchers", 418 | "type" : "JSON", 419 | "implicit" : 1 420 | } 421 | , { 422 | "name" : "oopsy.snoop.js", 423 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 424 | "patcherrelativepath" : "../javascript", 425 | "type" : "TEXT", 426 | "implicit" : 1 427 | } 428 | , { 429 | "name" : "oopsy.node4max.js", 430 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 431 | "patcherrelativepath" : "../javascript", 432 | "type" : "TEXT", 433 | "implicit" : 1 434 | } 435 | ], 436 | "autosave" : 0 437 | } 438 | 439 | } 440 | -------------------------------------------------------------------------------- /examples/midside.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 927.0, 579.0, 618.0, 437.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 | "bgmode" : 0, 44 | "border" : 0, 45 | "clickthrough" : 0, 46 | "enablehscroll" : 0, 47 | "enablevscroll" : 0, 48 | "id" : "obj-9", 49 | "lockeddragscroll" : 0, 50 | "maxclass" : "bpatcher", 51 | "name" : "oopsy.maxpat", 52 | "numinlets" : 1, 53 | "numoutlets" : 0, 54 | "offset" : [ 0.0, 0.0 ], 55 | "patching_rect" : [ 298.0, 26.0, 128.0, 128.0 ], 56 | "viewvisibility" : 1 57 | } 58 | 59 | } 60 | , { 61 | "box" : { 62 | "id" : "obj-4", 63 | "lastchannelcount" : 0, 64 | "maxclass" : "live.gain~", 65 | "numinlets" : 2, 66 | "numoutlets" : 5, 67 | "outlettype" : [ "signal", "signal", "", "float", "list" ], 68 | "parameter_enable" : 1, 69 | "patching_rect" : [ 62.0, 225.0, 48.0, 136.0 ], 70 | "saved_attribute_attributes" : { 71 | "valueof" : { 72 | "parameter_longname" : "live.gain~", 73 | "parameter_mmax" : 6.0, 74 | "parameter_mmin" : -70.0, 75 | "parameter_shortname" : "live.gain~", 76 | "parameter_type" : 0, 77 | "parameter_unitstyle" : 4 78 | } 79 | 80 | } 81 | , 82 | "varname" : "live.gain~" 83 | } 84 | 85 | } 86 | , { 87 | "box" : { 88 | "id" : "obj-1", 89 | "maxclass" : "newobj", 90 | "numinlets" : 4, 91 | "numoutlets" : 4, 92 | "outlettype" : [ "signal", "signal", "signal", "signal" ], 93 | "patcher" : { 94 | "fileversion" : 1, 95 | "appversion" : { 96 | "major" : 8, 97 | "minor" : 1, 98 | "revision" : 8, 99 | "architecture" : "x64", 100 | "modernui" : 1 101 | } 102 | , 103 | "classnamespace" : "dsp.gen", 104 | "rect" : [ 977.0, 78.0, 634.0, 454.0 ], 105 | "bglocked" : 0, 106 | "openinpresentation" : 0, 107 | "default_fontsize" : 12.0, 108 | "default_fontface" : 0, 109 | "default_fontname" : "Arial", 110 | "gridonopen" : 1, 111 | "gridsize" : [ 15.0, 15.0 ], 112 | "gridsnaponopen" : 1, 113 | "objectsnaponopen" : 1, 114 | "statusbarvisible" : 2, 115 | "toolbarvisible" : 1, 116 | "lefttoolbarpinned" : 0, 117 | "toptoolbarpinned" : 0, 118 | "righttoolbarpinned" : 0, 119 | "bottomtoolbarpinned" : 0, 120 | "toolbars_unpinned_last_save" : 0, 121 | "tallnewobj" : 0, 122 | "boxanimatetime" : 200, 123 | "enablehscroll" : 1, 124 | "enablevscroll" : 1, 125 | "devicewidth" : 0.0, 126 | "description" : "", 127 | "digest" : "", 128 | "tags" : "", 129 | "style" : "", 130 | "subpatcher_template" : "", 131 | "assistshowspatchername" : 0, 132 | "boxes" : [ { 133 | "box" : { 134 | "id" : "obj-14", 135 | "linecount" : 3, 136 | "maxclass" : "comment", 137 | "numinlets" : 1, 138 | "numoutlets" : 0, 139 | "patching_rect" : [ 334.0, 183.0, 150.0, 47.0 ], 140 | "text" : "A really basic patch for mid-side stereo conversion" 141 | } 142 | 143 | } 144 | , { 145 | "box" : { 146 | "id" : "obj-11", 147 | "maxclass" : "newobj", 148 | "numinlets" : 1, 149 | "numoutlets" : 0, 150 | "patching_rect" : [ 221.0, 249.0, 47.0, 22.0 ], 151 | "text" : "out 4 R" 152 | } 153 | 154 | } 155 | , { 156 | "box" : { 157 | "id" : "obj-12", 158 | "maxclass" : "newobj", 159 | "numinlets" : 1, 160 | "numoutlets" : 0, 161 | "patching_rect" : [ 168.0, 249.0, 45.0, 22.0 ], 162 | "text" : "out 3 L" 163 | } 164 | 165 | } 166 | , { 167 | "box" : { 168 | "id" : "obj-9", 169 | "maxclass" : "newobj", 170 | "numinlets" : 2, 171 | "numoutlets" : 1, 172 | "outlettype" : [ "" ], 173 | "patching_rect" : [ 221.0, 183.0, 39.5, 22.0 ], 174 | "text" : "-" 175 | } 176 | 177 | } 178 | , { 179 | "box" : { 180 | "id" : "obj-10", 181 | "maxclass" : "newobj", 182 | "numinlets" : 1, 183 | "numoutlets" : 1, 184 | "outlettype" : [ "" ], 185 | "patching_rect" : [ 168.0, 183.0, 32.0, 22.0 ], 186 | "text" : "/ 2" 187 | } 188 | 189 | } 190 | , { 191 | "box" : { 192 | "id" : "obj-8", 193 | "maxclass" : "newobj", 194 | "numinlets" : 1, 195 | "numoutlets" : 0, 196 | "patching_rect" : [ 84.0, 249.0, 47.0, 22.0 ], 197 | "text" : "out 2 S" 198 | } 199 | 200 | } 201 | , { 202 | "box" : { 203 | "id" : "obj-7", 204 | "maxclass" : "newobj", 205 | "numinlets" : 1, 206 | "numoutlets" : 0, 207 | "patching_rect" : [ 31.0, 249.0, 49.0, 22.0 ], 208 | "text" : "out 1 M" 209 | } 210 | 211 | } 212 | , { 213 | "box" : { 214 | "id" : "obj-6", 215 | "maxclass" : "newobj", 216 | "numinlets" : 2, 217 | "numoutlets" : 1, 218 | "outlettype" : [ "" ], 219 | "patching_rect" : [ 84.0, 183.0, 39.5, 22.0 ], 220 | "text" : "-" 221 | } 222 | 223 | } 224 | , { 225 | "box" : { 226 | "id" : "obj-5", 227 | "maxclass" : "newobj", 228 | "numinlets" : 1, 229 | "numoutlets" : 1, 230 | "outlettype" : [ "" ], 231 | "patching_rect" : [ 31.0, 183.0, 32.0, 22.0 ], 232 | "text" : "/ 2" 233 | } 234 | 235 | } 236 | , { 237 | "box" : { 238 | "id" : "obj-3", 239 | "maxclass" : "newobj", 240 | "numinlets" : 0, 241 | "numoutlets" : 1, 242 | "outlettype" : [ "" ], 243 | "patching_rect" : [ 241.5, 125.0, 39.0, 22.0 ], 244 | "text" : "in 4 S" 245 | } 246 | 247 | } 248 | , { 249 | "box" : { 250 | "id" : "obj-4", 251 | "maxclass" : "newobj", 252 | "numinlets" : 0, 253 | "numoutlets" : 1, 254 | "outlettype" : [ "" ], 255 | "patching_rect" : [ 168.0, 125.0, 41.0, 22.0 ], 256 | "text" : "in 3 M" 257 | } 258 | 259 | } 260 | , { 261 | "box" : { 262 | "id" : "obj-2", 263 | "maxclass" : "newobj", 264 | "numinlets" : 0, 265 | "numoutlets" : 1, 266 | "outlettype" : [ "" ], 267 | "patching_rect" : [ 104.5, 125.0, 40.0, 22.0 ], 268 | "text" : "in 2 R" 269 | } 270 | 271 | } 272 | , { 273 | "box" : { 274 | "id" : "obj-1", 275 | "maxclass" : "newobj", 276 | "numinlets" : 0, 277 | "numoutlets" : 1, 278 | "outlettype" : [ "" ], 279 | "patching_rect" : [ 31.0, 125.0, 38.0, 22.0 ], 280 | "text" : "in 1 L" 281 | } 282 | 283 | } 284 | ], 285 | "lines" : [ { 286 | "patchline" : { 287 | "destination" : [ "obj-5", 0 ], 288 | "order" : 1, 289 | "source" : [ "obj-1", 0 ] 290 | } 291 | 292 | } 293 | , { 294 | "patchline" : { 295 | "destination" : [ "obj-6", 0 ], 296 | "order" : 0, 297 | "source" : [ "obj-1", 0 ] 298 | } 299 | 300 | } 301 | , { 302 | "patchline" : { 303 | "destination" : [ "obj-12", 0 ], 304 | "source" : [ "obj-10", 0 ] 305 | } 306 | 307 | } 308 | , { 309 | "patchline" : { 310 | "destination" : [ "obj-5", 0 ], 311 | "order" : 1, 312 | "source" : [ "obj-2", 0 ] 313 | } 314 | 315 | } 316 | , { 317 | "patchline" : { 318 | "destination" : [ "obj-6", 1 ], 319 | "order" : 0, 320 | "source" : [ "obj-2", 0 ] 321 | } 322 | 323 | } 324 | , { 325 | "patchline" : { 326 | "destination" : [ "obj-10", 0 ], 327 | "order" : 1, 328 | "source" : [ "obj-3", 0 ] 329 | } 330 | 331 | } 332 | , { 333 | "patchline" : { 334 | "destination" : [ "obj-9", 1 ], 335 | "order" : 0, 336 | "source" : [ "obj-3", 0 ] 337 | } 338 | 339 | } 340 | , { 341 | "patchline" : { 342 | "destination" : [ "obj-10", 0 ], 343 | "order" : 1, 344 | "source" : [ "obj-4", 0 ] 345 | } 346 | 347 | } 348 | , { 349 | "patchline" : { 350 | "destination" : [ "obj-9", 0 ], 351 | "order" : 0, 352 | "source" : [ "obj-4", 0 ] 353 | } 354 | 355 | } 356 | , { 357 | "patchline" : { 358 | "destination" : [ "obj-7", 0 ], 359 | "source" : [ "obj-5", 0 ] 360 | } 361 | 362 | } 363 | , { 364 | "patchline" : { 365 | "destination" : [ "obj-8", 0 ], 366 | "source" : [ "obj-6", 0 ] 367 | } 368 | 369 | } 370 | , { 371 | "patchline" : { 372 | "destination" : [ "obj-11", 0 ], 373 | "source" : [ "obj-9", 0 ] 374 | } 375 | 376 | } 377 | ] 378 | } 379 | , 380 | "patching_rect" : [ 62.0, 120.0, 50.5, 22.0 ], 381 | "saved_object_attributes" : { 382 | "exportfolder" : "Macintosh HD:/Users/grrrwaaa/Documents/Max 8/Packages/oopsy/examples/", 383 | "exportname" : "midside" 384 | } 385 | , 386 | "text" : "gen~", 387 | "varname" : "midside" 388 | } 389 | 390 | } 391 | , { 392 | "box" : { 393 | "fontname" : "Arial Bold Italic", 394 | "fontsize" : 24.0, 395 | "id" : "obj-3", 396 | "linecount" : 2, 397 | "maxclass" : "comment", 398 | "numinlets" : 1, 399 | "numoutlets" : 0, 400 | "patching_rect" : [ 24.0, 26.0, 261.0, 60.0 ], 401 | "text" : "Mid-Side Stereo Conversion" 402 | } 403 | 404 | } 405 | , { 406 | "box" : { 407 | "id" : "obj-2", 408 | "maxclass" : "ezdac~", 409 | "numinlets" : 2, 410 | "numoutlets" : 0, 411 | "patching_rect" : [ 62.0, 371.0, 45.0, 45.0 ] 412 | } 413 | 414 | } 415 | ], 416 | "lines" : [ { 417 | "patchline" : { 418 | "destination" : [ "obj-4", 0 ], 419 | "source" : [ "obj-1", 0 ] 420 | } 421 | 422 | } 423 | , { 424 | "patchline" : { 425 | "destination" : [ "obj-2", 1 ], 426 | "source" : [ "obj-4", 1 ] 427 | } 428 | 429 | } 430 | , { 431 | "patchline" : { 432 | "destination" : [ "obj-2", 0 ], 433 | "source" : [ "obj-4", 0 ] 434 | } 435 | 436 | } 437 | ], 438 | "parameters" : { 439 | "obj-4" : [ "live.gain~", "live.gain~", 0 ], 440 | "obj-9::obj-32" : [ "live.text[4]", "FILTER", 0 ], 441 | "obj-9::obj-36" : [ "live.menu[1]", "live.menu", 0 ], 442 | "obj-9::obj-4" : [ "live.menu[2]", "live.menu", 0 ], 443 | "parameterbanks" : { 444 | 445 | } 446 | , 447 | "parameter_overrides" : { 448 | "obj-9::obj-32" : { 449 | "parameter_longname" : "live.text[4]" 450 | } 451 | , 452 | "obj-9::obj-36" : { 453 | "parameter_longname" : "live.menu[1]" 454 | } 455 | 456 | } 457 | , 458 | "inherited_shortname" : 1 459 | } 460 | , 461 | "dependency_cache" : [ { 462 | "name" : "oopsy.maxpat", 463 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/patchers", 464 | "patcherrelativepath" : "../patchers", 465 | "type" : "JSON", 466 | "implicit" : 1 467 | } 468 | , { 469 | "name" : "oopsy.snoop.js", 470 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 471 | "patcherrelativepath" : "../javascript", 472 | "type" : "TEXT", 473 | "implicit" : 1 474 | } 475 | , { 476 | "name" : "oopsy.node4max.js", 477 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 478 | "patcherrelativepath" : "../javascript", 479 | "type" : "TEXT", 480 | "implicit" : 1 481 | } 482 | ], 483 | "autosave" : 0 484 | } 485 | 486 | } 487 | -------------------------------------------------------------------------------- /examples/sdcard-minimal.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 94.0, 78.0, 856.0, 468.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-16", 44 | "linecount" : 2, 45 | "maxclass" : "comment", 46 | "numinlets" : 1, 47 | "numoutlets" : 0, 48 | "patching_rect" : [ 555.0, 308.0, 218.0, 33.0 ], 49 | "presentation_linecount" : 3, 50 | "text" : "This is how long your gen~ data object needs to be to fit the wav data into it." 51 | } 52 | 53 | } 54 | , { 55 | "box" : { 56 | "id" : "obj-13", 57 | "maxclass" : "button", 58 | "numinlets" : 1, 59 | "numoutlets" : 1, 60 | "outlettype" : [ "bang" ], 61 | "parameter_enable" : 0, 62 | "patching_rect" : [ 745.0, 142.0, 24.0, 24.0 ] 63 | } 64 | 65 | } 66 | , { 67 | "box" : { 68 | "format" : 6, 69 | "id" : "obj-11", 70 | "maxclass" : "flonum", 71 | "numinlets" : 1, 72 | "numoutlets" : 2, 73 | "outlettype" : [ "", "bang" ], 74 | "parameter_enable" : 0, 75 | "patching_rect" : [ 555.0, 272.0, 110.0, 22.0 ] 76 | } 77 | 78 | } 79 | , { 80 | "box" : { 81 | "id" : "obj-8", 82 | "maxclass" : "newobj", 83 | "numinlets" : 2, 84 | "numoutlets" : 1, 85 | "outlettype" : [ "float" ], 86 | "patching_rect" : [ 555.0, 243.0, 53.0, 22.0 ], 87 | "text" : "* 44100." 88 | } 89 | 90 | } 91 | , { 92 | "box" : { 93 | "id" : "obj-4", 94 | "maxclass" : "newobj", 95 | "numinlets" : 2, 96 | "numoutlets" : 1, 97 | "outlettype" : [ "float" ], 98 | "patching_rect" : [ 618.0, 214.0, 47.0, 22.0 ], 99 | "text" : "* 0.001" 100 | } 101 | 102 | } 103 | , { 104 | "box" : { 105 | "id" : "obj-1", 106 | "maxclass" : "newobj", 107 | "numinlets" : 1, 108 | "numoutlets" : 9, 109 | "outlettype" : [ "float", "list", "float", "float", "float", "float", "float", "", "int" ], 110 | "patching_rect" : [ 555.0, 181.0, 103.0, 22.0 ], 111 | "text" : "info~ drumloop" 112 | } 113 | 114 | } 115 | , { 116 | "box" : { 117 | "id" : "obj-9", 118 | "maxclass" : "live.scope~", 119 | "numinlets" : 2, 120 | "numoutlets" : 1, 121 | "outlettype" : [ "bang" ], 122 | "patching_rect" : [ 105.0, 220.0, 178.0, 136.0 ] 123 | } 124 | 125 | } 126 | , { 127 | "box" : { 128 | "fontname" : "Arial Italic", 129 | "fontsize" : 18.0, 130 | "id" : "obj-7", 131 | "maxclass" : "comment", 132 | "numinlets" : 1, 133 | "numoutlets" : 0, 134 | "patching_rect" : [ 19.0, 24.0, 576.0, 27.0 ], 135 | "text" : "Minimal example of loading WAV file into gen~ data exported by Oopsy" 136 | } 137 | 138 | } 139 | , { 140 | "box" : { 141 | "id" : "obj-6", 142 | "linecount" : 4, 143 | "maxclass" : "comment", 144 | "numinlets" : 1, 145 | "numoutlets" : 0, 146 | "patching_rect" : [ 321.0, 142.0, 196.0, 60.0 ], 147 | "text" : "\"@drumloop_wav drumloop\" automatically loads the content of [buffer~ drumloop] into the gen~ object's [data drumloop_wav]" 148 | } 149 | 150 | } 151 | , { 152 | "box" : { 153 | "id" : "obj-5", 154 | "maxclass" : "newobj", 155 | "numinlets" : 1, 156 | "numoutlets" : 2, 157 | "outlettype" : [ "signal", "signal" ], 158 | "patcher" : { 159 | "fileversion" : 1, 160 | "appversion" : { 161 | "major" : 8, 162 | "minor" : 1, 163 | "revision" : 8, 164 | "architecture" : "x64", 165 | "modernui" : 1 166 | } 167 | , 168 | "classnamespace" : "dsp.gen", 169 | "rect" : [ 567.0, 254.0, 530.0, 354.0 ], 170 | "bglocked" : 0, 171 | "openinpresentation" : 0, 172 | "default_fontsize" : 12.0, 173 | "default_fontface" : 0, 174 | "default_fontname" : "Arial", 175 | "gridonopen" : 1, 176 | "gridsize" : [ 15.0, 15.0 ], 177 | "gridsnaponopen" : 1, 178 | "objectsnaponopen" : 1, 179 | "statusbarvisible" : 2, 180 | "toolbarvisible" : 1, 181 | "lefttoolbarpinned" : 0, 182 | "toptoolbarpinned" : 0, 183 | "righttoolbarpinned" : 0, 184 | "bottomtoolbarpinned" : 0, 185 | "toolbars_unpinned_last_save" : 0, 186 | "tallnewobj" : 0, 187 | "boxanimatetime" : 200, 188 | "enablehscroll" : 1, 189 | "enablevscroll" : 1, 190 | "devicewidth" : 0.0, 191 | "description" : "", 192 | "digest" : "", 193 | "tags" : "", 194 | "style" : "", 195 | "subpatcher_template" : "", 196 | "assistshowspatchername" : 0, 197 | "boxes" : [ { 198 | "box" : { 199 | "id" : "obj-3", 200 | "linecount" : 3, 201 | "maxclass" : "comment", 202 | "numinlets" : 1, 203 | "numoutlets" : 0, 204 | "patching_rect" : [ 265.0, 265.0, 232.0, 47.0 ], 205 | "text" : "Oopsy can read 16, 24 and 32 bit PCM wav files. Note that file names are case sensitive. " 206 | } 207 | 208 | } 209 | , { 210 | "box" : { 211 | "id" : "obj-2", 212 | "linecount" : 2, 213 | "maxclass" : "comment", 214 | "numinlets" : 1, 215 | "numoutlets" : 0, 216 | "patching_rect" : [ 265.0, 69.0, 232.0, 33.0 ], 217 | "text" : "In this case, there should be a file \"drumloop.wav\" in the root of the SD card:" 218 | } 219 | 220 | } 221 | , { 222 | "box" : { 223 | "id" : "obj-12", 224 | "maxclass" : "newobj", 225 | "numinlets" : 1, 226 | "numoutlets" : 0, 227 | "patching_rect" : [ 108.0, 148.0, 35.0, 22.0 ], 228 | "text" : "out 2" 229 | } 230 | 231 | } 232 | , { 233 | "box" : { 234 | "id" : "obj-11", 235 | "maxclass" : "newobj", 236 | "numinlets" : 1, 237 | "numoutlets" : 1, 238 | "outlettype" : [ "" ], 239 | "patching_rect" : [ 48.0, 69.0, 65.0, 22.0 ], 240 | "text" : "phasor 0.5" 241 | } 242 | 243 | } 244 | , { 245 | "box" : { 246 | "id" : "obj-6", 247 | "maxclass" : "newobj", 248 | "numinlets" : 2, 249 | "numoutlets" : 3, 250 | "outlettype" : [ "", "", "" ], 251 | "patching_rect" : [ 48.0, 119.0, 139.0, 22.0 ], 252 | "text" : "sample drumloop_wav 2" 253 | } 254 | 255 | } 256 | , { 257 | "box" : { 258 | "id" : "obj-1", 259 | "maxclass" : "newobj", 260 | "numinlets" : 0, 261 | "numoutlets" : 2, 262 | "outlettype" : [ "", "" ], 263 | "patching_rect" : [ 265.0, 119.0, 167.0, 22.0 ], 264 | "text" : "data drumloop_wav 153400 2" 265 | } 266 | 267 | } 268 | , { 269 | "box" : { 270 | "id" : "obj-10", 271 | "linecount" : 3, 272 | "maxclass" : "comment", 273 | "numinlets" : 1, 274 | "numoutlets" : 0, 275 | "patching_rect" : [ 265.0, 17.0, 232.0, 47.0 ], 276 | "text" : "Any [data] whose name ends with \"_wav\" will tell Oopsy to try to load a corresponding .wav file from the SDcard" 277 | } 278 | 279 | } 280 | , { 281 | "box" : { 282 | "id" : "obj-7", 283 | "linecount" : 7, 284 | "maxclass" : "comment", 285 | "numinlets" : 1, 286 | "numoutlets" : 0, 287 | "patching_rect" : [ 265.0, 150.0, 240.0, 100.0 ], 288 | "text" : "Note that the [data] still needs a length and number of channels defined\n\nWhile developing in Max, a [data foo_wav] can be automatically associated with a [buffer~ bar] by adding a \"@foo_wav bar\" attribute to the gen~ object." 289 | } 290 | 291 | } 292 | , { 293 | "box" : { 294 | "id" : "obj-4", 295 | "maxclass" : "newobj", 296 | "numinlets" : 1, 297 | "numoutlets" : 0, 298 | "patching_rect" : [ 48.0, 148.0, 35.0, 22.0 ], 299 | "text" : "out 1" 300 | } 301 | 302 | } 303 | ], 304 | "lines" : [ { 305 | "patchline" : { 306 | "destination" : [ "obj-6", 0 ], 307 | "source" : [ "obj-11", 0 ] 308 | } 309 | 310 | } 311 | , { 312 | "patchline" : { 313 | "destination" : [ "obj-12", 0 ], 314 | "source" : [ "obj-6", 1 ] 315 | } 316 | 317 | } 318 | , { 319 | "patchline" : { 320 | "destination" : [ "obj-4", 0 ], 321 | "source" : [ "obj-6", 0 ] 322 | } 323 | 324 | } 325 | ] 326 | } 327 | , 328 | "patching_rect" : [ 55.0, 142.0, 256.0, 22.0 ], 329 | "saved_object_attributes" : { 330 | "exportfolder" : "Macintosh HD:/Users/grrrwaaa/Documents/Max 8/Packages/oopsy/graham/", 331 | "exportname" : "sdcard" 332 | } 333 | , 334 | "text" : "gen~ @title sdcard @drumloop_wav drumloop", 335 | "varname" : "sdcard" 336 | } 337 | 338 | } 339 | , { 340 | "box" : { 341 | "id" : "obj-15", 342 | "maxclass" : "ezdac~", 343 | "numinlets" : 2, 344 | "numoutlets" : 0, 345 | "patching_rect" : [ 55.0, 366.0, 45.0, 45.0 ] 346 | } 347 | 348 | } 349 | , { 350 | "box" : { 351 | "id" : "obj-14", 352 | "lastchannelcount" : 0, 353 | "maxclass" : "live.gain~", 354 | "numinlets" : 2, 355 | "numoutlets" : 5, 356 | "outlettype" : [ "signal", "signal", "", "float", "list" ], 357 | "parameter_enable" : 1, 358 | "patching_rect" : [ 55.0, 220.0, 48.0, 136.0 ], 359 | "saved_attribute_attributes" : { 360 | "valueof" : { 361 | "parameter_longname" : "live.gain~", 362 | "parameter_mmax" : 6.0, 363 | "parameter_mmin" : -70.0, 364 | "parameter_shortname" : "live.gain~", 365 | "parameter_type" : 0, 366 | "parameter_unitstyle" : 4 367 | } 368 | 369 | } 370 | , 371 | "varname" : "live.gain~" 372 | } 373 | 374 | } 375 | , { 376 | "box" : { 377 | "id" : "obj-3", 378 | "maxclass" : "newobj", 379 | "numinlets" : 1, 380 | "numoutlets" : 2, 381 | "outlettype" : [ "float", "bang" ], 382 | "patching_rect" : [ 555.0, 142.0, 181.0, 22.0 ], 383 | "text" : "buffer~ drumloop drumLoop.wav" 384 | } 385 | 386 | } 387 | , { 388 | "box" : { 389 | "args" : [ "patch" ], 390 | "bgmode" : 0, 391 | "border" : 0, 392 | "clickthrough" : 0, 393 | "enablehscroll" : 0, 394 | "enablevscroll" : 0, 395 | "id" : "obj-2", 396 | "lockeddragscroll" : 0, 397 | "maxclass" : "bpatcher", 398 | "name" : "oopsy.maxpat", 399 | "numinlets" : 1, 400 | "numoutlets" : 0, 401 | "offset" : [ 0.0, 0.0 ], 402 | "patching_rect" : [ 321.0, 220.0, 128.0, 128.0 ], 403 | "viewvisibility" : 1 404 | } 405 | 406 | } 407 | ], 408 | "lines" : [ { 409 | "patchline" : { 410 | "destination" : [ "obj-4", 0 ], 411 | "source" : [ "obj-1", 6 ] 412 | } 413 | 414 | } 415 | , { 416 | "patchline" : { 417 | "destination" : [ "obj-8", 0 ], 418 | "source" : [ "obj-1", 0 ] 419 | } 420 | 421 | } 422 | , { 423 | "patchline" : { 424 | "destination" : [ "obj-1", 0 ], 425 | "source" : [ "obj-13", 0 ] 426 | } 427 | 428 | } 429 | , { 430 | "patchline" : { 431 | "destination" : [ "obj-15", 1 ], 432 | "source" : [ "obj-14", 1 ] 433 | } 434 | 435 | } 436 | , { 437 | "patchline" : { 438 | "destination" : [ "obj-15", 0 ], 439 | "source" : [ "obj-14", 0 ] 440 | } 441 | 442 | } 443 | , { 444 | "patchline" : { 445 | "destination" : [ "obj-1", 0 ], 446 | "source" : [ "obj-3", 1 ] 447 | } 448 | 449 | } 450 | , { 451 | "patchline" : { 452 | "destination" : [ "obj-8", 1 ], 453 | "source" : [ "obj-4", 0 ] 454 | } 455 | 456 | } 457 | , { 458 | "patchline" : { 459 | "destination" : [ "obj-14", 0 ], 460 | "order" : 1, 461 | "source" : [ "obj-5", 0 ] 462 | } 463 | 464 | } 465 | , { 466 | "patchline" : { 467 | "destination" : [ "obj-9", 0 ], 468 | "order" : 0, 469 | "source" : [ "obj-5", 0 ] 470 | } 471 | 472 | } 473 | , { 474 | "patchline" : { 475 | "destination" : [ "obj-11", 0 ], 476 | "source" : [ "obj-8", 0 ] 477 | } 478 | 479 | } 480 | ], 481 | "parameters" : { 482 | "obj-14" : [ "live.gain~", "live.gain~", 0 ], 483 | "obj-2::obj-32" : [ "live.text[2]", "FILTER", 0 ], 484 | "obj-2::obj-33" : [ "live.text[1]", "FILTER", 0 ], 485 | "obj-2::obj-34" : [ "live.text[3]", "FILTER", 0 ], 486 | "parameterbanks" : { 487 | 488 | } 489 | , 490 | "inherited_shortname" : 1 491 | } 492 | , 493 | "dependency_cache" : [ { 494 | "name" : "oopsy.maxpat", 495 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/patchers", 496 | "patcherrelativepath" : "../patchers", 497 | "type" : "JSON", 498 | "implicit" : 1 499 | } 500 | , { 501 | "name" : "oopsy.snoop.js", 502 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 503 | "patcherrelativepath" : "../javascript", 504 | "type" : "TEXT", 505 | "implicit" : 1 506 | } 507 | , { 508 | "name" : "oopsy.node4max.js", 509 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 510 | "patcherrelativepath" : "../javascript", 511 | "type" : "TEXT", 512 | "implicit" : 1 513 | } 514 | ], 515 | "autosave" : 0 516 | } 517 | 518 | } 519 | -------------------------------------------------------------------------------- /examples/multi_app.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 752.0, 158.0, 681.0, 395.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-15", 44 | "maxclass" : "newobj", 45 | "numinlets" : 0, 46 | "numoutlets" : 0, 47 | "patching_rect" : [ 95.0, 203.0, 45.0, 22.0 ], 48 | "text" : "scatter" 49 | } 50 | 51 | } 52 | , { 53 | "box" : { 54 | "id" : "obj-13", 55 | "maxclass" : "newobj", 56 | "numinlets" : 0, 57 | "numoutlets" : 0, 58 | "patching_rect" : [ 95.0, 152.0, 46.0, 22.0 ], 59 | "text" : "dattoro" 60 | } 61 | 62 | } 63 | , { 64 | "box" : { 65 | "id" : "obj-11", 66 | "maxclass" : "newobj", 67 | "numinlets" : 0, 68 | "numoutlets" : 0, 69 | "patching_rect" : [ 95.0, 257.0, 45.0, 22.0 ], 70 | "text" : "modfm" 71 | } 72 | 73 | } 74 | , { 75 | "box" : { 76 | "id" : "obj-10", 77 | "maxclass" : "newobj", 78 | "numinlets" : 0, 79 | "numoutlets" : 0, 80 | "patching_rect" : [ 24.0, 203.0, 61.0, 22.0 ], 81 | "text" : "crossover" 82 | } 83 | 84 | } 85 | , { 86 | "box" : { 87 | "id" : "obj-6", 88 | "maxclass" : "newobj", 89 | "numinlets" : 0, 90 | "numoutlets" : 0, 91 | "patching_rect" : [ 24.0, 257.0, 44.0, 22.0 ], 92 | "text" : "squine" 93 | } 94 | 95 | } 96 | , { 97 | "box" : { 98 | "id" : "obj-1", 99 | "maxclass" : "newobj", 100 | "numinlets" : 0, 101 | "numoutlets" : 0, 102 | "patching_rect" : [ 24.0, 152.0, 31.0, 22.0 ], 103 | "text" : "giga" 104 | } 105 | 106 | } 107 | , { 108 | "box" : { 109 | "id" : "obj-22", 110 | "linecount" : 4, 111 | "maxclass" : "comment", 112 | "numinlets" : 1, 113 | "numoutlets" : 0, 114 | "patching_rect" : [ 460.600008249282837, 77.59999805688858, 175.0, 60.0 ], 115 | "text" : "A midi-enabled multi-app Oopsy program will respond to program-change MIDI events to by switching between apps " 116 | } 117 | 118 | } 119 | , { 120 | "box" : { 121 | "id" : "obj-20", 122 | "maxclass" : "newobj", 123 | "numinlets" : 1, 124 | "numoutlets" : 0, 125 | "patching_rect" : [ 471.000008404254913, 290.59999805688858, 47.0, 22.0 ], 126 | "text" : "midiout" 127 | } 128 | 129 | } 130 | , { 131 | "box" : { 132 | "id" : "obj-19", 133 | "maxclass" : "number", 134 | "minimum" : 20, 135 | "numinlets" : 1, 136 | "numoutlets" : 2, 137 | "outlettype" : [ "", "bang" ], 138 | "parameter_enable" : 0, 139 | "patching_rect" : [ 546.500008404254913, 160.199996113777161, 50.0, 22.0 ] 140 | } 141 | 142 | } 143 | , { 144 | "box" : { 145 | "id" : "obj-16", 146 | "maxclass" : "toggle", 147 | "numinlets" : 1, 148 | "numoutlets" : 1, 149 | "outlettype" : [ "int" ], 150 | "parameter_enable" : 0, 151 | "patching_rect" : [ 502.500008404254913, 160.199996113777161, 24.0, 24.0 ] 152 | } 153 | 154 | } 155 | , { 156 | "box" : { 157 | "id" : "obj-9", 158 | "maxclass" : "newobj", 159 | "numinlets" : 2, 160 | "numoutlets" : 1, 161 | "outlettype" : [ "bang" ], 162 | "patching_rect" : [ 502.500008404254913, 186.199996113777161, 63.0, 22.0 ], 163 | "text" : "metro 250" 164 | } 165 | 166 | } 167 | , { 168 | "box" : { 169 | "id" : "obj-8", 170 | "maxclass" : "number", 171 | "numinlets" : 1, 172 | "numoutlets" : 2, 173 | "outlettype" : [ "", "bang" ], 174 | "parameter_enable" : 0, 175 | "patching_rect" : [ 502.500008404254913, 236.99999725818634, 50.0, 22.0 ] 176 | } 177 | 178 | } 179 | , { 180 | "box" : { 181 | "id" : "obj-4", 182 | "maxclass" : "newobj", 183 | "numinlets" : 5, 184 | "numoutlets" : 4, 185 | "outlettype" : [ "int", "", "", "int" ], 186 | "patching_rect" : [ 502.500008404254913, 211.399996876716614, 69.0, 22.0 ], 187 | "text" : "counter 1 8" 188 | } 189 | 190 | } 191 | , { 192 | "box" : { 193 | "id" : "obj-2", 194 | "maxclass" : "newobj", 195 | "numinlets" : 7, 196 | "numoutlets" : 2, 197 | "outlettype" : [ "int", "" ], 198 | "patching_rect" : [ 471.000008404254913, 263.399997651576996, 82.0, 22.0 ], 199 | "text" : "midiformat" 200 | } 201 | 202 | } 203 | , { 204 | "box" : { 205 | "id" : "obj-7", 206 | "linecount" : 3, 207 | "maxclass" : "comment", 208 | "numinlets" : 1, 209 | "numoutlets" : 0, 210 | "patching_rect" : [ 28.0, 77.59999805688858, 402.0, 47.0 ], 211 | "text" : "Oopsy will snoop for all gen~ objects in the same patcher or subpatchers, producing a 'multi-app' binary for the Daisy hardwares that support app switching, e.g. Patch, Field, Petal. " 212 | } 213 | 214 | } 215 | , { 216 | "box" : { 217 | "fontname" : "Arial Italic", 218 | "fontsize" : 18.0, 219 | "id" : "obj-5", 220 | "maxclass" : "comment", 221 | "numinlets" : 1, 222 | "numoutlets" : 0, 223 | "patching_rect" : [ 28.0, 34.5, 266.0, 27.0 ], 224 | "text" : "Multi-app" 225 | } 226 | 227 | } 228 | , { 229 | "box" : { 230 | "args" : [ "@samplerate", "48kHz" ], 231 | "bgmode" : 0, 232 | "border" : 0, 233 | "clickthrough" : 0, 234 | "enablehscroll" : 0, 235 | "enablevscroll" : 0, 236 | "id" : "obj-3", 237 | "lockeddragscroll" : 0, 238 | "maxclass" : "bpatcher", 239 | "name" : "oopsy.maxpat", 240 | "numinlets" : 1, 241 | "numoutlets" : 0, 242 | "offset" : [ 0.0, 0.0 ], 243 | "patching_rect" : [ 200.0, 142.0, 128.0, 128.0 ], 244 | "viewvisibility" : 1 245 | } 246 | 247 | } 248 | ], 249 | "lines" : [ { 250 | "patchline" : { 251 | "destination" : [ "obj-9", 0 ], 252 | "source" : [ "obj-16", 0 ] 253 | } 254 | 255 | } 256 | , { 257 | "patchline" : { 258 | "destination" : [ "obj-9", 1 ], 259 | "source" : [ "obj-19", 0 ] 260 | } 261 | 262 | } 263 | , { 264 | "patchline" : { 265 | "destination" : [ "obj-20", 0 ], 266 | "source" : [ "obj-2", 0 ] 267 | } 268 | 269 | } 270 | , { 271 | "patchline" : { 272 | "destination" : [ "obj-8", 0 ], 273 | "source" : [ "obj-4", 0 ] 274 | } 275 | 276 | } 277 | , { 278 | "patchline" : { 279 | "destination" : [ "obj-2", 3 ], 280 | "source" : [ "obj-8", 0 ] 281 | } 282 | 283 | } 284 | , { 285 | "patchline" : { 286 | "destination" : [ "obj-4", 0 ], 287 | "source" : [ "obj-9", 0 ] 288 | } 289 | 290 | } 291 | ], 292 | "parameters" : { 293 | "obj-10::obj-11" : [ "live.gain~[2]", "live.gain~", 0 ], 294 | "obj-10::obj-12" : [ "live.gain~[1]", "live.gain~", 0 ], 295 | "obj-10::obj-7::obj-21::obj-6" : [ "live.tab[4]", "live.tab[1]", 0 ], 296 | "obj-10::obj-7::obj-35" : [ "[6]", "Level", 0 ], 297 | "obj-10::obj-9::obj-32" : [ "live.text[12]", "FILTER", 0 ], 298 | "obj-10::obj-9::obj-33" : [ "live.text[11]", "FILTER", 0 ], 299 | "obj-10::obj-9::obj-34" : [ "live.text[13]", "FILTER", 0 ], 300 | "obj-11::obj-11" : [ "live.gain~[4]", "live.gain~", 0 ], 301 | "obj-11::obj-9::obj-32" : [ "live.text[14]", "FILTER", 0 ], 302 | "obj-11::obj-9::obj-33" : [ "live.text[15]", "FILTER", 0 ], 303 | "obj-11::obj-9::obj-34" : [ "live.text[16]", "FILTER", 0 ], 304 | "obj-13::obj-1::obj-32" : [ "live.text[23]", "FILTER", 0 ], 305 | "obj-13::obj-1::obj-33" : [ "live.text[22]", "FILTER", 0 ], 306 | "obj-13::obj-1::obj-34" : [ "live.text[24]", "FILTER", 0 ], 307 | "obj-13::obj-6" : [ "live.gain~[6]", "live.gain~", 0 ], 308 | "obj-13::obj-7::obj-21::obj-6" : [ "live.tab[5]", "live.tab[1]", 0 ], 309 | "obj-13::obj-7::obj-35" : [ "[7]", "Level", 0 ], 310 | "obj-15::obj-4::obj-32" : [ "live.text[27]", "FILTER", 0 ], 311 | "obj-15::obj-4::obj-33" : [ "live.text[28]", "FILTER", 0 ], 312 | "obj-15::obj-4::obj-34" : [ "live.text[29]", "FILTER", 0 ], 313 | "obj-1::obj-11" : [ "live.gain~", "live.gain~", 0 ], 314 | "obj-1::obj-3::obj-32" : [ "live.text[6]", "FILTER", 0 ], 315 | "obj-1::obj-3::obj-33" : [ "live.text[4]", "FILTER", 0 ], 316 | "obj-1::obj-3::obj-34" : [ "live.text[2]", "FILTER", 0 ], 317 | "obj-1::obj-6::obj-21::obj-6" : [ "live.tab[3]", "live.tab[1]", 0 ], 318 | "obj-1::obj-6::obj-35" : [ "[5]", "Level", 0 ], 319 | "obj-3::obj-32" : [ "live.text[5]", "FILTER", 0 ], 320 | "obj-3::obj-33" : [ "live.text[1]", "FILTER", 0 ], 321 | "obj-3::obj-34" : [ "live.text[3]", "FILTER", 0 ], 322 | "obj-6::obj-3::obj-32" : [ "live.text[7]", "FILTER", 0 ], 323 | "obj-6::obj-3::obj-33" : [ "live.text[8]", "FILTER", 0 ], 324 | "obj-6::obj-3::obj-34" : [ "live.text[9]", "FILTER", 0 ], 325 | "parameterbanks" : { 326 | 327 | } 328 | , 329 | "parameter_overrides" : { 330 | "obj-10::obj-11" : { 331 | "parameter_longname" : "live.gain~[2]" 332 | } 333 | , 334 | "obj-10::obj-7::obj-21::obj-6" : { 335 | "parameter_longname" : "live.tab[4]" 336 | } 337 | , 338 | "obj-10::obj-7::obj-35" : { 339 | "parameter_longname" : "[6]" 340 | } 341 | , 342 | "obj-10::obj-9::obj-32" : { 343 | "parameter_longname" : "live.text[12]" 344 | } 345 | , 346 | "obj-10::obj-9::obj-33" : { 347 | "parameter_longname" : "live.text[11]" 348 | } 349 | , 350 | "obj-10::obj-9::obj-34" : { 351 | "parameter_longname" : "live.text[13]" 352 | } 353 | , 354 | "obj-11::obj-11" : { 355 | "parameter_longname" : "live.gain~[4]" 356 | } 357 | , 358 | "obj-11::obj-9::obj-32" : { 359 | "parameter_longname" : "live.text[14]" 360 | } 361 | , 362 | "obj-11::obj-9::obj-33" : { 363 | "parameter_longname" : "live.text[15]" 364 | } 365 | , 366 | "obj-11::obj-9::obj-34" : { 367 | "parameter_longname" : "live.text[16]" 368 | } 369 | , 370 | "obj-13::obj-1::obj-32" : { 371 | "parameter_longname" : "live.text[23]" 372 | } 373 | , 374 | "obj-13::obj-1::obj-33" : { 375 | "parameter_longname" : "live.text[22]" 376 | } 377 | , 378 | "obj-13::obj-1::obj-34" : { 379 | "parameter_longname" : "live.text[24]" 380 | } 381 | , 382 | "obj-13::obj-6" : { 383 | "parameter_longname" : "live.gain~[6]" 384 | } 385 | , 386 | "obj-13::obj-7::obj-21::obj-6" : { 387 | "parameter_longname" : "live.tab[5]" 388 | } 389 | , 390 | "obj-13::obj-7::obj-35" : { 391 | "parameter_longname" : "[7]" 392 | } 393 | , 394 | "obj-15::obj-4::obj-32" : { 395 | "parameter_longname" : "live.text[27]" 396 | } 397 | , 398 | "obj-15::obj-4::obj-33" : { 399 | "parameter_longname" : "live.text[28]" 400 | } 401 | , 402 | "obj-15::obj-4::obj-34" : { 403 | "parameter_longname" : "live.text[29]" 404 | } 405 | , 406 | "obj-1::obj-3::obj-32" : { 407 | "parameter_longname" : "live.text[6]" 408 | } 409 | , 410 | "obj-1::obj-3::obj-33" : { 411 | "parameter_longname" : "live.text[4]" 412 | } 413 | , 414 | "obj-1::obj-3::obj-34" : { 415 | "parameter_longname" : "live.text[2]" 416 | } 417 | , 418 | "obj-3::obj-32" : { 419 | "parameter_longname" : "live.text[5]" 420 | } 421 | , 422 | "obj-6::obj-3::obj-32" : { 423 | "parameter_longname" : "live.text[7]" 424 | } 425 | , 426 | "obj-6::obj-3::obj-33" : { 427 | "parameter_longname" : "live.text[8]" 428 | } 429 | , 430 | "obj-6::obj-3::obj-34" : { 431 | "parameter_longname" : "live.text[9]" 432 | } 433 | 434 | } 435 | , 436 | "inherited_shortname" : 1 437 | } 438 | , 439 | "dependency_cache" : [ { 440 | "name" : "oopsy.maxpat", 441 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/patchers", 442 | "patcherrelativepath" : "../patchers", 443 | "type" : "JSON", 444 | "implicit" : 1 445 | } 446 | , { 447 | "name" : "oopsy.snoop.js", 448 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 449 | "patcherrelativepath" : "../javascript", 450 | "type" : "TEXT", 451 | "implicit" : 1 452 | } 453 | , { 454 | "name" : "oopsy.node4max.js", 455 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 456 | "patcherrelativepath" : "../javascript", 457 | "type" : "TEXT", 458 | "implicit" : 1 459 | } 460 | , { 461 | "name" : "giga.maxpat", 462 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/examples", 463 | "patcherrelativepath" : ".", 464 | "type" : "JSON", 465 | "implicit" : 1 466 | } 467 | , { 468 | "name" : "oopsy.ctrl.smooth3.gendsp", 469 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/code", 470 | "patcherrelativepath" : "../code", 471 | "type" : "gDSP", 472 | "implicit" : 1 473 | } 474 | , { 475 | "name" : "oopsy.ctrl.smooth2.gendsp", 476 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/code", 477 | "patcherrelativepath" : "../code", 478 | "type" : "gDSP", 479 | "implicit" : 1 480 | } 481 | , { 482 | "name" : "demosound.maxpat", 483 | "bootpath" : "C74:/help/msp", 484 | "type" : "JSON", 485 | "implicit" : 1 486 | } 487 | , { 488 | "name" : "sine.svg", 489 | "bootpath" : "C74:/media/max/picts/m4l-picts", 490 | "type" : "svg", 491 | "implicit" : 1 492 | } 493 | , { 494 | "name" : "saw.svg", 495 | "bootpath" : "C74:/media/max/picts/m4l-picts", 496 | "type" : "svg", 497 | "implicit" : 1 498 | } 499 | , { 500 | "name" : "square.svg", 501 | "bootpath" : "C74:/media/max/picts/m4l-picts", 502 | "type" : "svg", 503 | "implicit" : 1 504 | } 505 | , { 506 | "name" : "random.svg", 507 | "bootpath" : "C74:/media/max/picts/m4l-picts", 508 | "type" : "svg", 509 | "implicit" : 1 510 | } 511 | , { 512 | "name" : "interfacecolor.js", 513 | "bootpath" : "C74:/interfaces", 514 | "type" : "TEXT", 515 | "implicit" : 1 516 | } 517 | , { 518 | "name" : "squine.maxpat", 519 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/examples", 520 | "patcherrelativepath" : ".", 521 | "type" : "JSON", 522 | "implicit" : 1 523 | } 524 | , { 525 | "name" : "oopsy.cv2hz.gendsp", 526 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/code", 527 | "patcherrelativepath" : "../code", 528 | "type" : "gDSP", 529 | "implicit" : 1 530 | } 531 | , { 532 | "name" : "crossover.maxpat", 533 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/examples", 534 | "patcherrelativepath" : ".", 535 | "type" : "JSON", 536 | "implicit" : 1 537 | } 538 | , { 539 | "name" : "modfm.maxpat", 540 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/examples", 541 | "patcherrelativepath" : ".", 542 | "type" : "JSON", 543 | "implicit" : 1 544 | } 545 | , { 546 | "name" : "dattoro.maxpat", 547 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/examples", 548 | "patcherrelativepath" : ".", 549 | "type" : "JSON", 550 | "implicit" : 1 551 | } 552 | , { 553 | "name" : "scatter.maxpat", 554 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/examples", 555 | "patcherrelativepath" : ".", 556 | "type" : "JSON", 557 | "implicit" : 1 558 | } 559 | , { 560 | "name" : "jsui_2dvectorctrl.js", 561 | "bootpath" : "C74:/jsui", 562 | "type" : "TEXT", 563 | "implicit" : 1 564 | } 565 | ], 566 | "autosave" : 0 567 | } 568 | 569 | } 570 | -------------------------------------------------------------------------------- /templates/oopsy_bluemchen.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 647.0, 204.0, 546.0, 483.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" : "oopsy_bluemchen", 40 | "assistshowspatchername" : 0, 41 | "boxes" : [ { 42 | "box" : { 43 | "id" : "obj-2", 44 | "maxclass" : "comment", 45 | "numinlets" : 1, 46 | "numoutlets" : 0, 47 | "patching_rect" : [ 18.0, 69.0, 325.0, 20.0 ], 48 | "text" : "see https://kxmx-bluemchen.recursinging.com" 49 | } 50 | 51 | } 52 | , { 53 | "box" : { 54 | "fontname" : "Arial Italic", 55 | "fontsize" : 18.0, 56 | "id" : "obj-24", 57 | "maxclass" : "comment", 58 | "numinlets" : 1, 59 | "numoutlets" : 0, 60 | "patching_rect" : [ 18.0, 34.715827338129543, 325.0, 27.0 ], 61 | "text" : "Template for KXMX Bluemchen" 62 | } 63 | 64 | } 65 | , { 66 | "box" : { 67 | "id" : "obj-13", 68 | "maxclass" : "ezdac~", 69 | "numinlets" : 2, 70 | "numoutlets" : 0, 71 | "patching_rect" : [ 40.0, 385.0, 45.0, 45.0 ] 72 | } 73 | 74 | } 75 | , { 76 | "box" : { 77 | "id" : "obj-11", 78 | "lastchannelcount" : 0, 79 | "maxclass" : "live.gain~", 80 | "numinlets" : 2, 81 | "numoutlets" : 5, 82 | "outlettype" : [ "signal", "signal", "", "float", "list" ], 83 | "parameter_enable" : 1, 84 | "patching_rect" : [ 40.0, 279.0, 44.0, 90.0 ], 85 | "saved_attribute_attributes" : { 86 | "valueof" : { 87 | "parameter_longname" : "live.gain~", 88 | "parameter_mmax" : 6.0, 89 | "parameter_mmin" : -70.0, 90 | "parameter_shortname" : "live.gain~", 91 | "parameter_type" : 0, 92 | "parameter_unitstyle" : 4 93 | } 94 | 95 | } 96 | , 97 | "varname" : "live.gain~" 98 | } 99 | 100 | } 101 | , { 102 | "box" : { 103 | "args" : [ "@target", "bluemchen" ], 104 | "bgmode" : 0, 105 | "border" : 0, 106 | "clickthrough" : 0, 107 | "enablehscroll" : 0, 108 | "enablevscroll" : 0, 109 | "id" : "obj-9", 110 | "lockeddragscroll" : 0, 111 | "maxclass" : "bpatcher", 112 | "name" : "oopsy.maxpat", 113 | "numinlets" : 1, 114 | "numoutlets" : 0, 115 | "offset" : [ 0.0, 0.0 ], 116 | "patching_rect" : [ 240.0, 230.0, 128.0, 128.0 ], 117 | "viewvisibility" : 1 118 | } 119 | 120 | } 121 | , { 122 | "box" : { 123 | "fontsize" : 24.0, 124 | "id" : "obj-3", 125 | "maxclass" : "newobj", 126 | "numinlets" : 2, 127 | "numoutlets" : 2, 128 | "outlettype" : [ "signal", "signal" ], 129 | "patcher" : { 130 | "fileversion" : 1, 131 | "appversion" : { 132 | "major" : 8, 133 | "minor" : 1, 134 | "revision" : 8, 135 | "architecture" : "x64", 136 | "modernui" : 1 137 | } 138 | , 139 | "classnamespace" : "dsp.gen", 140 | "rect" : [ 84.0, 102.0, 587.0, 553.0 ], 141 | "bglocked" : 0, 142 | "openinpresentation" : 0, 143 | "default_fontsize" : 12.0, 144 | "default_fontface" : 0, 145 | "default_fontname" : "Arial", 146 | "gridonopen" : 1, 147 | "gridsize" : [ 15.0, 15.0 ], 148 | "gridsnaponopen" : 1, 149 | "objectsnaponopen" : 1, 150 | "statusbarvisible" : 2, 151 | "toolbarvisible" : 1, 152 | "lefttoolbarpinned" : 0, 153 | "toptoolbarpinned" : 0, 154 | "righttoolbarpinned" : 0, 155 | "bottomtoolbarpinned" : 0, 156 | "toolbars_unpinned_last_save" : 0, 157 | "tallnewobj" : 0, 158 | "boxanimatetime" : 200, 159 | "enablehscroll" : 1, 160 | "enablevscroll" : 1, 161 | "devicewidth" : 0.0, 162 | "description" : "", 163 | "digest" : "", 164 | "tags" : "", 165 | "style" : "", 166 | "subpatcher_template" : "", 167 | "assistshowspatchername" : 0, 168 | "boxes" : [ { 169 | "box" : { 170 | "id" : "obj-19", 171 | "maxclass" : "newobj", 172 | "numinlets" : 3, 173 | "numoutlets" : 1, 174 | "outlettype" : [ "" ], 175 | "patching_rect" : [ 192.5, 367.0, 53.0, 22.0 ], 176 | "text" : "mix" 177 | } 178 | 179 | } 180 | , { 181 | "box" : { 182 | "id" : "obj-18", 183 | "maxclass" : "newobj", 184 | "numinlets" : 3, 185 | "numoutlets" : 1, 186 | "outlettype" : [ "" ], 187 | "patching_rect" : [ 137.5, 367.0, 53.0, 22.0 ], 188 | "text" : "mix" 189 | } 190 | 191 | } 192 | , { 193 | "box" : { 194 | "id" : "obj-16", 195 | "maxclass" : "newobj", 196 | "numinlets" : 0, 197 | "numoutlets" : 1, 198 | "outlettype" : [ "" ], 199 | "patching_rect" : [ 269.5, 333.0, 172.0, 22.0 ], 200 | "text" : "param knob2 @min 0 @max 1" 201 | } 202 | 203 | } 204 | , { 205 | "box" : { 206 | "id" : "obj-17", 207 | "maxclass" : "newobj", 208 | "numinlets" : 0, 209 | "numoutlets" : 1, 210 | "outlettype" : [ "" ], 211 | "patching_rect" : [ 254.5, 309.0, 172.0, 22.0 ], 212 | "text" : "param knob1 @min 0 @max 1" 213 | } 214 | 215 | } 216 | , { 217 | "box" : { 218 | "id" : "obj-14", 219 | "maxclass" : "newobj", 220 | "numinlets" : 2, 221 | "numoutlets" : 1, 222 | "outlettype" : [ "" ], 223 | "patching_rect" : [ 350.25, 245.0, 103.0, 22.0 ], 224 | "text" : "scale 0 1 400 800" 225 | } 226 | 227 | } 228 | , { 229 | "box" : { 230 | "id" : "obj-15", 231 | "maxclass" : "newobj", 232 | "numinlets" : 0, 233 | "numoutlets" : 1, 234 | "outlettype" : [ "" ], 235 | "patching_rect" : [ 350.25, 219.0, 158.0, 22.0 ], 236 | "text" : "param cv2 @min 0 @max 1" 237 | } 238 | 239 | } 240 | , { 241 | "box" : { 242 | "id" : "obj-13", 243 | "maxclass" : "newobj", 244 | "numinlets" : 1, 245 | "numoutlets" : 2, 246 | "outlettype" : [ "", "" ], 247 | "patching_rect" : [ 209.5, 277.0, 36.0, 22.0 ], 248 | "text" : "cycle" 249 | } 250 | 251 | } 252 | , { 253 | "box" : { 254 | "id" : "obj-10", 255 | "maxclass" : "newobj", 256 | "numinlets" : 1, 257 | "numoutlets" : 2, 258 | "outlettype" : [ "", "" ], 259 | "patching_rect" : [ 154.5, 277.0, 36.0, 22.0 ], 260 | "text" : "cycle" 261 | } 262 | 263 | } 264 | , { 265 | "box" : { 266 | "id" : "obj-8", 267 | "maxclass" : "newobj", 268 | "numinlets" : 2, 269 | "numoutlets" : 1, 270 | "outlettype" : [ "" ], 271 | "patching_rect" : [ 229.5, 213.0, 103.0, 22.0 ], 272 | "text" : "scale 0 1 400 800" 273 | } 274 | 275 | } 276 | , { 277 | "box" : { 278 | "id" : "obj-58", 279 | "maxclass" : "comment", 280 | "numinlets" : 1, 281 | "numoutlets" : 0, 282 | "patching_rect" : [ 29.5, 395.0, 69.0, 20.0 ], 283 | "text" : "OUTPUTS" 284 | } 285 | 286 | } 287 | , { 288 | "box" : { 289 | "id" : "obj-59", 290 | "maxclass" : "comment", 291 | "numinlets" : 1, 292 | "numoutlets" : 0, 293 | "patching_rect" : [ 29.5, 141.0, 69.0, 20.0 ], 294 | "text" : "INPUTS" 295 | } 296 | 297 | } 298 | , { 299 | "box" : { 300 | "id" : "obj-2", 301 | "maxclass" : "newobj", 302 | "numinlets" : 0, 303 | "numoutlets" : 1, 304 | "outlettype" : [ "" ], 305 | "patching_rect" : [ 229.5, 187.0, 158.0, 22.0 ], 306 | "text" : "param cv1 @min 0 @max 1" 307 | } 308 | 309 | } 310 | , { 311 | "box" : { 312 | "id" : "obj-11", 313 | "maxclass" : "comment", 314 | "numinlets" : 1, 315 | "numoutlets" : 0, 316 | "patching_rect" : [ 137.5, 106.0, 65.0, 20.0 ], 317 | "text" : "Audio IOs" 318 | } 319 | 320 | } 321 | , { 322 | "box" : { 323 | "id" : "obj-67", 324 | "maxclass" : "newobj", 325 | "numinlets" : 0, 326 | "numoutlets" : 1, 327 | "outlettype" : [ "" ], 328 | "patching_rect" : [ 192.5, 141.0, 28.0, 22.0 ], 329 | "text" : "in 2" 330 | } 331 | 332 | } 333 | , { 334 | "box" : { 335 | "id" : "obj-5", 336 | "maxclass" : "newobj", 337 | "numinlets" : 1, 338 | "numoutlets" : 0, 339 | "patching_rect" : [ 192.5, 395.0, 35.0, 22.0 ], 340 | "text" : "out 2" 341 | } 342 | 343 | } 344 | , { 345 | "box" : { 346 | "id" : "obj-1", 347 | "maxclass" : "newobj", 348 | "numinlets" : 0, 349 | "numoutlets" : 1, 350 | "outlettype" : [ "" ], 351 | "patching_rect" : [ 137.5, 141.0, 28.0, 22.0 ], 352 | "text" : "in 1" 353 | } 354 | 355 | } 356 | , { 357 | "box" : { 358 | "id" : "obj-68", 359 | "maxclass" : "newobj", 360 | "numinlets" : 1, 361 | "numoutlets" : 0, 362 | "patching_rect" : [ 137.5, 395.0, 35.0, 22.0 ], 363 | "text" : "out 1" 364 | } 365 | 366 | } 367 | ], 368 | "lines" : [ { 369 | "patchline" : { 370 | "destination" : [ "obj-18", 0 ], 371 | "source" : [ "obj-1", 0 ] 372 | } 373 | 374 | } 375 | , { 376 | "patchline" : { 377 | "destination" : [ "obj-18", 1 ], 378 | "source" : [ "obj-10", 0 ] 379 | } 380 | 381 | } 382 | , { 383 | "patchline" : { 384 | "destination" : [ "obj-19", 1 ], 385 | "source" : [ "obj-13", 0 ] 386 | } 387 | 388 | } 389 | , { 390 | "patchline" : { 391 | "destination" : [ "obj-13", 0 ], 392 | "source" : [ "obj-14", 0 ] 393 | } 394 | 395 | } 396 | , { 397 | "patchline" : { 398 | "destination" : [ "obj-14", 0 ], 399 | "source" : [ "obj-15", 0 ] 400 | } 401 | 402 | } 403 | , { 404 | "patchline" : { 405 | "destination" : [ "obj-19", 2 ], 406 | "source" : [ "obj-16", 0 ] 407 | } 408 | 409 | } 410 | , { 411 | "patchline" : { 412 | "destination" : [ "obj-18", 2 ], 413 | "source" : [ "obj-17", 0 ] 414 | } 415 | 416 | } 417 | , { 418 | "patchline" : { 419 | "destination" : [ "obj-68", 0 ], 420 | "source" : [ "obj-18", 0 ] 421 | } 422 | 423 | } 424 | , { 425 | "patchline" : { 426 | "destination" : [ "obj-5", 0 ], 427 | "source" : [ "obj-19", 0 ] 428 | } 429 | 430 | } 431 | , { 432 | "patchline" : { 433 | "destination" : [ "obj-8", 0 ], 434 | "source" : [ "obj-2", 0 ] 435 | } 436 | 437 | } 438 | , { 439 | "patchline" : { 440 | "destination" : [ "obj-19", 0 ], 441 | "source" : [ "obj-67", 0 ] 442 | } 443 | 444 | } 445 | , { 446 | "patchline" : { 447 | "destination" : [ "obj-10", 0 ], 448 | "source" : [ "obj-8", 0 ] 449 | } 450 | 451 | } 452 | ] 453 | } 454 | , 455 | "patching_rect" : [ 40.0, 230.0, 144.0, 35.0 ], 456 | "saved_object_attributes" : { 457 | "exportfolder" : "Macintosh HD:/Users/grrrwaaa/Documents/Max 8/Packages/oopsy/templates/", 458 | "exportname" : "oopsy_bluemchen" 459 | } 460 | , 461 | "text" : "gen~", 462 | "varname" : "oopsy_bluemchen" 463 | } 464 | 465 | } 466 | , { 467 | "box" : { 468 | "attr" : "knob1", 469 | "id" : "obj-4", 470 | "maxclass" : "attrui", 471 | "numinlets" : 1, 472 | "numoutlets" : 1, 473 | "outlettype" : [ "" ], 474 | "patching_rect" : [ 40.0, 135.0, 150.0, 22.0 ] 475 | } 476 | 477 | } 478 | , { 479 | "box" : { 480 | "attr" : "knob2", 481 | "id" : "obj-5", 482 | "maxclass" : "attrui", 483 | "numinlets" : 1, 484 | "numoutlets" : 1, 485 | "outlettype" : [ "" ], 486 | "patching_rect" : [ 193.0, 135.0, 150.0, 22.0 ] 487 | } 488 | 489 | } 490 | , { 491 | "box" : { 492 | "attr" : "cv1", 493 | "id" : "obj-6", 494 | "maxclass" : "attrui", 495 | "numinlets" : 1, 496 | "numoutlets" : 1, 497 | "outlettype" : [ "" ], 498 | "patching_rect" : [ 40.0, 159.0, 150.0, 22.0 ] 499 | } 500 | 501 | } 502 | , { 503 | "box" : { 504 | "attr" : "cv2", 505 | "id" : "obj-7", 506 | "maxclass" : "attrui", 507 | "numinlets" : 1, 508 | "numoutlets" : 1, 509 | "outlettype" : [ "" ], 510 | "patching_rect" : [ 193.0, 159.0, 150.0, 22.0 ] 511 | } 512 | 513 | } 514 | ], 515 | "lines" : [ { 516 | "patchline" : { 517 | "destination" : [ "obj-13", 1 ], 518 | "source" : [ "obj-11", 1 ] 519 | } 520 | 521 | } 522 | , { 523 | "patchline" : { 524 | "destination" : [ "obj-13", 0 ], 525 | "source" : [ "obj-11", 0 ] 526 | } 527 | 528 | } 529 | , { 530 | "patchline" : { 531 | "destination" : [ "obj-11", 1 ], 532 | "source" : [ "obj-3", 1 ] 533 | } 534 | 535 | } 536 | , { 537 | "patchline" : { 538 | "destination" : [ "obj-11", 0 ], 539 | "source" : [ "obj-3", 0 ] 540 | } 541 | 542 | } 543 | , { 544 | "patchline" : { 545 | "destination" : [ "obj-3", 0 ], 546 | "source" : [ "obj-4", 0 ] 547 | } 548 | 549 | } 550 | , { 551 | "patchline" : { 552 | "destination" : [ "obj-3", 0 ], 553 | "source" : [ "obj-5", 0 ] 554 | } 555 | 556 | } 557 | , { 558 | "patchline" : { 559 | "destination" : [ "obj-3", 0 ], 560 | "source" : [ "obj-6", 0 ] 561 | } 562 | 563 | } 564 | , { 565 | "patchline" : { 566 | "destination" : [ "obj-3", 0 ], 567 | "source" : [ "obj-7", 0 ] 568 | } 569 | 570 | } 571 | ], 572 | "parameters" : { 573 | "obj-11" : [ "live.gain~", "live.gain~", 0 ], 574 | "obj-9::obj-32" : [ "live.text[2]", "FILTER", 0 ], 575 | "obj-9::obj-33" : [ "live.text[1]", "FILTER", 0 ], 576 | "obj-9::obj-34" : [ "live.text[3]", "FILTER", 0 ], 577 | "parameterbanks" : { 578 | 579 | } 580 | , 581 | "inherited_shortname" : 1 582 | } 583 | , 584 | "dependency_cache" : [ { 585 | "name" : "oopsy.maxpat", 586 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/patchers", 587 | "patcherrelativepath" : "../patchers", 588 | "type" : "JSON", 589 | "implicit" : 1 590 | } 591 | , { 592 | "name" : "oopsy.snoop.js", 593 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 594 | "patcherrelativepath" : "../javascript", 595 | "type" : "TEXT", 596 | "implicit" : 1 597 | } 598 | , { 599 | "name" : "oopsy.node4max.js", 600 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 601 | "patcherrelativepath" : "../javascript", 602 | "type" : "TEXT", 603 | "implicit" : 1 604 | } 605 | ], 606 | "autosave" : 0 607 | } 608 | 609 | } 610 | -------------------------------------------------------------------------------- /templates/oopsy_nehcmeulb.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 8, 6 | "minor" : 1, 7 | "revision" : 8, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "classnamespace" : "box", 13 | "rect" : [ 300.0, 426.0, 546.0, 483.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" : "oopsy_bluemchen", 40 | "assistshowspatchername" : 0, 41 | "boxes" : [ { 42 | "box" : { 43 | "attr" : "cv1", 44 | "id" : "obj-6", 45 | "maxclass" : "attrui", 46 | "numinlets" : 1, 47 | "numoutlets" : 1, 48 | "outlettype" : [ "" ], 49 | "patching_rect" : [ 193.0, 162.0, 150.0, 22.0 ] 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-2", 56 | "maxclass" : "comment", 57 | "numinlets" : 1, 58 | "numoutlets" : 0, 59 | "patching_rect" : [ 18.0, 69.0, 325.0, 20.0 ], 60 | "text" : "see https://kxmx-bluemchen.recursinging.com" 61 | } 62 | 63 | } 64 | , { 65 | "box" : { 66 | "fontname" : "Arial Italic", 67 | "fontsize" : 18.0, 68 | "id" : "obj-24", 69 | "maxclass" : "comment", 70 | "numinlets" : 1, 71 | "numoutlets" : 0, 72 | "patching_rect" : [ 18.0, 34.715827338129543, 325.0, 27.0 ], 73 | "text" : "Template for KXMX Nehcmeulb" 74 | } 75 | 76 | } 77 | , { 78 | "box" : { 79 | "id" : "obj-13", 80 | "maxclass" : "ezdac~", 81 | "numinlets" : 2, 82 | "numoutlets" : 0, 83 | "patching_rect" : [ 40.0, 385.0, 45.0, 45.0 ] 84 | } 85 | 86 | } 87 | , { 88 | "box" : { 89 | "id" : "obj-11", 90 | "lastchannelcount" : 0, 91 | "maxclass" : "live.gain~", 92 | "numinlets" : 2, 93 | "numoutlets" : 5, 94 | "outlettype" : [ "signal", "signal", "", "float", "list" ], 95 | "parameter_enable" : 1, 96 | "patching_rect" : [ 40.0, 279.0, 44.0, 90.0 ], 97 | "saved_attribute_attributes" : { 98 | "valueof" : { 99 | "parameter_longname" : "live.gain~", 100 | "parameter_mmax" : 6.0, 101 | "parameter_mmin" : -70.0, 102 | "parameter_shortname" : "live.gain~", 103 | "parameter_type" : 0, 104 | "parameter_unitstyle" : 4 105 | } 106 | 107 | } 108 | , 109 | "varname" : "live.gain~" 110 | } 111 | 112 | } 113 | , { 114 | "box" : { 115 | "args" : [ "@target", "nehcmeulb" ], 116 | "bgmode" : 0, 117 | "border" : 0, 118 | "clickthrough" : 0, 119 | "enablehscroll" : 0, 120 | "enablevscroll" : 0, 121 | "id" : "obj-9", 122 | "lockeddragscroll" : 0, 123 | "maxclass" : "bpatcher", 124 | "name" : "oopsy.maxpat", 125 | "numinlets" : 1, 126 | "numoutlets" : 0, 127 | "offset" : [ 0.0, 0.0 ], 128 | "patching_rect" : [ 240.0, 230.0, 128.0, 128.0 ], 129 | "viewvisibility" : 1 130 | } 131 | 132 | } 133 | , { 134 | "box" : { 135 | "fontsize" : 24.0, 136 | "id" : "obj-3", 137 | "maxclass" : "newobj", 138 | "numinlets" : 2, 139 | "numoutlets" : 3, 140 | "outlettype" : [ "signal", "signal", "signal" ], 141 | "patcher" : { 142 | "fileversion" : 1, 143 | "appversion" : { 144 | "major" : 8, 145 | "minor" : 1, 146 | "revision" : 8, 147 | "architecture" : "x64", 148 | "modernui" : 1 149 | } 150 | , 151 | "classnamespace" : "dsp.gen", 152 | "rect" : [ 715.0, 114.0, 844.0, 587.0 ], 153 | "bglocked" : 0, 154 | "openinpresentation" : 0, 155 | "default_fontsize" : 12.0, 156 | "default_fontface" : 0, 157 | "default_fontname" : "Arial", 158 | "gridonopen" : 1, 159 | "gridsize" : [ 15.0, 15.0 ], 160 | "gridsnaponopen" : 1, 161 | "objectsnaponopen" : 1, 162 | "statusbarvisible" : 2, 163 | "toolbarvisible" : 1, 164 | "lefttoolbarpinned" : 0, 165 | "toptoolbarpinned" : 0, 166 | "righttoolbarpinned" : 0, 167 | "bottomtoolbarpinned" : 0, 168 | "toolbars_unpinned_last_save" : 0, 169 | "tallnewobj" : 0, 170 | "boxanimatetime" : 200, 171 | "enablehscroll" : 1, 172 | "enablevscroll" : 1, 173 | "devicewidth" : 0.0, 174 | "description" : "", 175 | "digest" : "", 176 | "tags" : "", 177 | "style" : "", 178 | "subpatcher_template" : "", 179 | "assistshowspatchername" : 0, 180 | "boxes" : [ { 181 | "box" : { 182 | "id" : "obj-24", 183 | "maxclass" : "newobj", 184 | "numinlets" : 2, 185 | "numoutlets" : 1, 186 | "outlettype" : [ "" ], 187 | "patching_rect" : [ 360.0, 314.5, 40.5, 22.0 ], 188 | "text" : "+" 189 | } 190 | 191 | } 192 | , { 193 | "box" : { 194 | "id" : "obj-25", 195 | "maxclass" : "newobj", 196 | "numinlets" : 0, 197 | "numoutlets" : 1, 198 | "outlettype" : [ "" ], 199 | "patching_rect" : [ 360.0, 81.0, 162.0, 22.0 ], 200 | "text" : "param cv2 @min -1 @max 1" 201 | } 202 | 203 | } 204 | , { 205 | "box" : { 206 | "id" : "obj-26", 207 | "maxclass" : "newobj", 208 | "numinlets" : 1, 209 | "numoutlets" : 0, 210 | "patching_rect" : [ 410.0, 248.0, 74.0, 22.0 ], 211 | "text" : "out 4 cvout2" 212 | } 213 | 214 | } 215 | , { 216 | "box" : { 217 | "id" : "obj-27", 218 | "maxclass" : "newobj", 219 | "numinlets" : 1, 220 | "numoutlets" : 2, 221 | "outlettype" : [ "", "" ], 222 | "patching_rect" : [ 410.0, 217.0, 37.0, 22.0 ], 223 | "text" : "cycle" 224 | } 225 | 226 | } 227 | , { 228 | "box" : { 229 | "id" : "obj-28", 230 | "maxclass" : "newobj", 231 | "numinlets" : 1, 232 | "numoutlets" : 2, 233 | "outlettype" : [ "", "" ], 234 | "patching_rect" : [ 360.0, 379.0, 36.0, 22.0 ], 235 | "text" : "cycle" 236 | } 237 | 238 | } 239 | , { 240 | "box" : { 241 | "id" : "obj-29", 242 | "maxclass" : "newobj", 243 | "numinlets" : 2, 244 | "numoutlets" : 1, 245 | "outlettype" : [ "" ], 246 | "patching_rect" : [ 360.0, 347.0, 103.0, 22.0 ], 247 | "text" : "scale 0 1 400 800" 248 | } 249 | 250 | } 251 | , { 252 | "box" : { 253 | "id" : "obj-30", 254 | "maxclass" : "newobj", 255 | "numinlets" : 0, 256 | "numoutlets" : 1, 257 | "outlettype" : [ "" ], 258 | "patching_rect" : [ 382.0, 155.0, 172.0, 22.0 ], 259 | "text" : "param knob2 @min 0 @max 1" 260 | } 261 | 262 | } 263 | , { 264 | "box" : { 265 | "id" : "obj-31", 266 | "maxclass" : "newobj", 267 | "numinlets" : 0, 268 | "numoutlets" : 1, 269 | "outlettype" : [ "" ], 270 | "patching_rect" : [ 321.5, 81.0, 28.0, 22.0 ], 271 | "text" : "in 2" 272 | } 273 | 274 | } 275 | , { 276 | "box" : { 277 | "id" : "obj-32", 278 | "maxclass" : "newobj", 279 | "numinlets" : 1, 280 | "numoutlets" : 0, 281 | "patching_rect" : [ 321.5, 421.0, 35.0, 22.0 ], 282 | "text" : "out 2" 283 | } 284 | 285 | } 286 | , { 287 | "box" : { 288 | "id" : "obj-23", 289 | "maxclass" : "newobj", 290 | "numinlets" : 2, 291 | "numoutlets" : 1, 292 | "outlettype" : [ "" ], 293 | "patching_rect" : [ 112.0, 314.5, 40.5, 22.0 ], 294 | "text" : "+" 295 | } 296 | 297 | } 298 | , { 299 | "box" : { 300 | "id" : "obj-11", 301 | "linecount" : 9, 302 | "maxclass" : "comment", 303 | "numinlets" : 1, 304 | "numoutlets" : 0, 305 | "patching_rect" : [ 624.0, 45.0, 150.0, 127.0 ], 306 | "text" : "On the nehcmeulb hardware, the same jack input is routed to both audio and cv inputs. \n\nThe audio inputs are AC-coupled (will filter out DC offset). The CV inputs are sampled at block rate. " 307 | } 308 | 309 | } 310 | , { 311 | "box" : { 312 | "id" : "obj-3", 313 | "maxclass" : "newobj", 314 | "numinlets" : 0, 315 | "numoutlets" : 1, 316 | "outlettype" : [ "" ], 317 | "patching_rect" : [ 112.0, 81.0, 162.0, 22.0 ], 318 | "text" : "param cv1 @min -1 @max 1" 319 | } 320 | 321 | } 322 | , { 323 | "box" : { 324 | "id" : "obj-6", 325 | "maxclass" : "newobj", 326 | "numinlets" : 1, 327 | "numoutlets" : 0, 328 | "patching_rect" : [ 162.0, 248.0, 74.0, 22.0 ], 329 | "text" : "out 3 cvout1" 330 | } 331 | 332 | } 333 | , { 334 | "box" : { 335 | "id" : "obj-4", 336 | "maxclass" : "newobj", 337 | "numinlets" : 1, 338 | "numoutlets" : 2, 339 | "outlettype" : [ "", "" ], 340 | "patching_rect" : [ 162.0, 217.0, 37.0, 22.0 ], 341 | "text" : "cycle" 342 | } 343 | 344 | } 345 | , { 346 | "box" : { 347 | "id" : "obj-10", 348 | "maxclass" : "newobj", 349 | "numinlets" : 1, 350 | "numoutlets" : 2, 351 | "outlettype" : [ "", "" ], 352 | "patching_rect" : [ 112.0, 379.0, 36.0, 22.0 ], 353 | "text" : "cycle" 354 | } 355 | 356 | } 357 | , { 358 | "box" : { 359 | "id" : "obj-8", 360 | "maxclass" : "newobj", 361 | "numinlets" : 2, 362 | "numoutlets" : 1, 363 | "outlettype" : [ "" ], 364 | "patching_rect" : [ 112.0, 347.0, 103.0, 22.0 ], 365 | "text" : "scale 0 1 400 800" 366 | } 367 | 368 | } 369 | , { 370 | "box" : { 371 | "id" : "obj-2", 372 | "maxclass" : "newobj", 373 | "numinlets" : 0, 374 | "numoutlets" : 1, 375 | "outlettype" : [ "" ], 376 | "patching_rect" : [ 134.0, 155.0, 172.0, 22.0 ], 377 | "text" : "param knob1 @min 0 @max 1" 378 | } 379 | 380 | } 381 | , { 382 | "box" : { 383 | "id" : "obj-1", 384 | "maxclass" : "newobj", 385 | "numinlets" : 0, 386 | "numoutlets" : 1, 387 | "outlettype" : [ "" ], 388 | "patching_rect" : [ 73.5, 81.0, 28.0, 22.0 ], 389 | "text" : "in 1" 390 | } 391 | 392 | } 393 | , { 394 | "box" : { 395 | "id" : "obj-68", 396 | "maxclass" : "newobj", 397 | "numinlets" : 1, 398 | "numoutlets" : 0, 399 | "patching_rect" : [ 73.5, 421.0, 35.0, 22.0 ], 400 | "text" : "out 1" 401 | } 402 | 403 | } 404 | ], 405 | "lines" : [ { 406 | "patchline" : { 407 | "destination" : [ "obj-68", 0 ], 408 | "source" : [ "obj-1", 0 ] 409 | } 410 | 411 | } 412 | , { 413 | "patchline" : { 414 | "destination" : [ "obj-68", 0 ], 415 | "source" : [ "obj-10", 0 ] 416 | } 417 | 418 | } 419 | , { 420 | "patchline" : { 421 | "destination" : [ "obj-23", 1 ], 422 | "order" : 1, 423 | "source" : [ "obj-2", 0 ] 424 | } 425 | 426 | } 427 | , { 428 | "patchline" : { 429 | "destination" : [ "obj-4", 0 ], 430 | "order" : 0, 431 | "source" : [ "obj-2", 0 ] 432 | } 433 | 434 | } 435 | , { 436 | "patchline" : { 437 | "destination" : [ "obj-8", 0 ], 438 | "source" : [ "obj-23", 0 ] 439 | } 440 | 441 | } 442 | , { 443 | "patchline" : { 444 | "destination" : [ "obj-29", 0 ], 445 | "source" : [ "obj-24", 0 ] 446 | } 447 | 448 | } 449 | , { 450 | "patchline" : { 451 | "destination" : [ "obj-24", 0 ], 452 | "source" : [ "obj-25", 0 ] 453 | } 454 | 455 | } 456 | , { 457 | "patchline" : { 458 | "destination" : [ "obj-26", 0 ], 459 | "source" : [ "obj-27", 0 ] 460 | } 461 | 462 | } 463 | , { 464 | "patchline" : { 465 | "destination" : [ "obj-32", 0 ], 466 | "source" : [ "obj-28", 0 ] 467 | } 468 | 469 | } 470 | , { 471 | "patchline" : { 472 | "destination" : [ "obj-28", 0 ], 473 | "source" : [ "obj-29", 0 ] 474 | } 475 | 476 | } 477 | , { 478 | "patchline" : { 479 | "destination" : [ "obj-23", 0 ], 480 | "source" : [ "obj-3", 0 ] 481 | } 482 | 483 | } 484 | , { 485 | "patchline" : { 486 | "destination" : [ "obj-24", 1 ], 487 | "order" : 1, 488 | "source" : [ "obj-30", 0 ] 489 | } 490 | 491 | } 492 | , { 493 | "patchline" : { 494 | "destination" : [ "obj-27", 0 ], 495 | "order" : 0, 496 | "source" : [ "obj-30", 0 ] 497 | } 498 | 499 | } 500 | , { 501 | "patchline" : { 502 | "destination" : [ "obj-32", 0 ], 503 | "source" : [ "obj-31", 0 ] 504 | } 505 | 506 | } 507 | , { 508 | "patchline" : { 509 | "destination" : [ "obj-6", 0 ], 510 | "source" : [ "obj-4", 0 ] 511 | } 512 | 513 | } 514 | , { 515 | "patchline" : { 516 | "destination" : [ "obj-10", 0 ], 517 | "source" : [ "obj-8", 0 ] 518 | } 519 | 520 | } 521 | ] 522 | } 523 | , 524 | "patching_rect" : [ 40.0, 230.0, 144.0, 35.0 ], 525 | "saved_object_attributes" : { 526 | "exportfolder" : "Macintosh HD:/Users/grrrwaaa/Documents/Max 8/Packages/oopsy/templates/", 527 | "exportname" : "oopsy_nehcmeulb" 528 | } 529 | , 530 | "text" : "gen~", 531 | "varname" : "oopsy_nehcmeulb" 532 | } 533 | 534 | } 535 | , { 536 | "box" : { 537 | "attr" : "knob1", 538 | "id" : "obj-4", 539 | "maxclass" : "attrui", 540 | "numinlets" : 1, 541 | "numoutlets" : 1, 542 | "outlettype" : [ "" ], 543 | "patching_rect" : [ 40.0, 135.0, 150.0, 22.0 ] 544 | } 545 | 546 | } 547 | , { 548 | "box" : { 549 | "attr" : "knob2", 550 | "id" : "obj-5", 551 | "maxclass" : "attrui", 552 | "numinlets" : 1, 553 | "numoutlets" : 1, 554 | "outlettype" : [ "" ], 555 | "patching_rect" : [ 193.0, 135.0, 150.0, 22.0 ] 556 | } 557 | 558 | } 559 | , { 560 | "box" : { 561 | "attr" : "cv1", 562 | "id" : "obj-1", 563 | "maxclass" : "attrui", 564 | "numinlets" : 1, 565 | "numoutlets" : 1, 566 | "outlettype" : [ "" ], 567 | "patching_rect" : [ 40.0, 162.0, 150.0, 22.0 ] 568 | } 569 | 570 | } 571 | ], 572 | "lines" : [ { 573 | "patchline" : { 574 | "destination" : [ "obj-3", 0 ], 575 | "source" : [ "obj-1", 0 ] 576 | } 577 | 578 | } 579 | , { 580 | "patchline" : { 581 | "destination" : [ "obj-13", 1 ], 582 | "source" : [ "obj-11", 1 ] 583 | } 584 | 585 | } 586 | , { 587 | "patchline" : { 588 | "destination" : [ "obj-13", 0 ], 589 | "source" : [ "obj-11", 0 ] 590 | } 591 | 592 | } 593 | , { 594 | "patchline" : { 595 | "destination" : [ "obj-11", 1 ], 596 | "source" : [ "obj-3", 1 ] 597 | } 598 | 599 | } 600 | , { 601 | "patchline" : { 602 | "destination" : [ "obj-11", 0 ], 603 | "source" : [ "obj-3", 0 ] 604 | } 605 | 606 | } 607 | , { 608 | "patchline" : { 609 | "destination" : [ "obj-3", 0 ], 610 | "source" : [ "obj-4", 0 ] 611 | } 612 | 613 | } 614 | , { 615 | "patchline" : { 616 | "destination" : [ "obj-3", 0 ], 617 | "source" : [ "obj-5", 0 ] 618 | } 619 | 620 | } 621 | , { 622 | "patchline" : { 623 | "destination" : [ "obj-3", 0 ], 624 | "source" : [ "obj-6", 0 ] 625 | } 626 | 627 | } 628 | ], 629 | "parameters" : { 630 | "obj-11" : [ "live.gain~", "live.gain~", 0 ], 631 | "obj-9::obj-32" : [ "live.text[2]", "FILTER", 0 ], 632 | "obj-9::obj-33" : [ "live.text[1]", "FILTER", 0 ], 633 | "obj-9::obj-34" : [ "live.text[3]", "FILTER", 0 ], 634 | "parameterbanks" : { 635 | 636 | } 637 | , 638 | "inherited_shortname" : 1 639 | } 640 | , 641 | "dependency_cache" : [ { 642 | "name" : "oopsy.maxpat", 643 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/patchers", 644 | "patcherrelativepath" : "../patchers", 645 | "type" : "JSON", 646 | "implicit" : 1 647 | } 648 | , { 649 | "name" : "oopsy.snoop.js", 650 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 651 | "patcherrelativepath" : "../javascript", 652 | "type" : "TEXT", 653 | "implicit" : 1 654 | } 655 | , { 656 | "name" : "oopsy.node4max.js", 657 | "bootpath" : "~/Documents/Max 8/Packages/oopsy/javascript", 658 | "patcherrelativepath" : "../javascript", 659 | "type" : "TEXT", 660 | "implicit" : 1 661 | } 662 | ], 663 | "autosave" : 0 664 | } 665 | 666 | } 667 | --------------------------------------------------------------------------------