From 2431714ab5c78fc50ff07c1b99b47ae07e037ba9 Mon Sep 17 00:00:00 2001 From: Timothy Place Date: Sat, 10 Oct 2026 11:50:22 -0500 Subject: [PATCH 1/4] The help patchers, the tutorials' patchers and the Overview, saved by Max (9.6) Opened and saved in Max 9.1.5, which writes them in its own form: the same boxes and patch cords (checked, every patcher and subpatcher), scripts/check-docs.py passing. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz --- .../pythontap-tut/pythontap_01_gain.maxpat | 1015 ++--- .../pythontap-tut/pythontap_02_filter.maxpat | 1165 ++--- .../pythontap-tut/pythontap_03_control.maxpat | 1680 +++---- extras/PythonTap Overview.maxpat | 1063 ++--- help/tap.python.maxhelp | 3878 ++++++---------- help/tap.python~.maxhelp | 3892 ++++++----------- 6 files changed, 4653 insertions(+), 8040 deletions(-) diff --git a/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat b/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat index 8eabc74..b96168f 100644 --- a/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat +++ b/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat @@ -1,645 +1,372 @@ { - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 760.0, - 560.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "PythonTap Tutorial 1", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A gain, per sample and per vector", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "The Documentation window has this tutorial's text. Turn on the audio with the speaker.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 110", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 150.0, - 74.0, - 24.0 - ], - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 190.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "gain", - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 200.0, - 190.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "gain", - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "message", - "text": "float 0.5", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 225.0, - 92.39999999999999, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "message", - "text": "greet max", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 120.39999999999999, - 225.0, - 92.39999999999999, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ default", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 265.0, - 151.0, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ numpy_gain", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 200.0, - 265.0, - 172.0, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "comment", - "text": "per sample: default.py", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 295.0, - 170, - 26.849999999999998 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "comment", - "text": "per vector: numpy_gain.py", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 200.0, - 295.0, - 190, - 26.849999999999998 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "message", - "text": "1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 335.0, - 40.0, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "message", - "text": "2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 68.0, - 335.0, - 40.0, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "comment", - "text": "listen to one or the other", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 120.0, - 335.0, - 220, - 26.849999999999998 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "selector~ 2 1", - "numinlets": 3, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 375.0, - 109.0, - 24.0 - ], - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 415.0, - 60.0, - 24.0 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "ezdac~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 20.0, - 450.0, - 45.0, - 45.0 - ], - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "metro 250 @active 1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 200.0, - 415.0, - 151.0, - 24.0 - ], - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "adstatus cpu", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "", - "int" - ], - "patching_rect": [ - 200.0, - 445.0, - 102.0, - 24.0 - ], - "id": "obj-20" - } - }, - { - "box": { - "maxclass": "number", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "bang" - ], - "patching_rect": [ - 200.0, - 475.0, - 60.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-21" - } - }, - { - "box": { - "maxclass": "comment", - "text": "CPU %", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 265.0, - 475.0, - 60, - 26.849999999999998 - ], - "id": "obj-22" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Make your own: save a copy of default.py as python/mygain.py, rename its class mygain, and type tap.python~ mygain into a new object box. Every save reloads it.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 420.0, - 150.0, - 300, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-23" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-4", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-4", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-5", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-16", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-16", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-16", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-16", - 2 - ] - } - }, - { - "patchline": { - "source": [ - "obj-16", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 0 - ], - "destination": [ - "obj-18", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 0 - ], - "destination": [ - "obj-18", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-19", - 0 - ], - "destination": [ - "obj-20", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-20", - 0 - ], - "destination": [ - "obj-21", - 0 - ] - } - } - ] - } -} + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 100.0, 760.0, 560.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "PythonTap Tutorial 1" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "A gain, per sample and per vector", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 330.0, 38.0 ], + "text": "The Documentation window has this tutorial's text. Turn on the audio with the speaker." + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 150.0, 74.0, 24.0 ], + "text": "saw~ 110" + } + }, + { + "box": { + "attr": "gain", + "id": "obj-5", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 20.0, 190.0, 150.0, 24.0 ] + } + }, + { + "box": { + "attr": "gain", + "id": "obj-6", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 200.0, 190.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 20.0, 225.0, 92.39999999999999, 24.0 ], + "text": "float 0.5" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 120.39999999999999, 225.0, 92.39999999999999, 24.0 ], + "text": "greet max" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 265.0, 151.0, 24.0 ], + "text": "tap.python~ default" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 200.0, 265.0, 172.0, 24.0 ], + "text": "tap.python~ numpy_gain" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 295.0, 170.0, 22.0 ], + "text": "per sample: default.py" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 200.0, 295.0, 190.0, 22.0 ], + "text": "per vector: numpy_gain.py" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 20.0, 335.0, 40.0, 24.0 ], + "text": "1" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 68.0, 335.0, 40.0, 24.0 ], + "text": "2" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 120.0, 335.0, 220.0, 22.0 ], + "text": "listen to one or the other" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 375.0, 109.0, 24.0 ], + "text": "selector~ 2 1" + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 415.0, 60.0, 24.0 ], + "text": "*~ 0.2" + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 20.0, 450.0, 45.0, 45.0 ] + } + }, + { + "box": { + "id": "obj-19", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "bang" ], + "patching_rect": [ 200.0, 415.0, 151.0, 24.0 ], + "text": "metro 250 @active 1" + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "", "int" ], + "patching_rect": [ 200.0, 445.0, 102.0, 24.0 ], + "text": "adstatus cpu" + } + }, + { + "box": { + "id": "obj-21", + "maxclass": "number", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "bang" ], + "parameter_enable": 0, + "patching_rect": [ 200.0, 475.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-22", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 265.0, 475.0, 60.0, 22.0 ], + "text": "CPU %" + } + }, + { + "box": { + "id": "obj-23", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 420.0, 150.0, 300.0, 69.0 ], + "text": "Make your own: save a copy of default.py as python/mygain.py, rename its class mygain, and type tap.python~ mygain into a new object box. Every save reloads it." + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-16", 2 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "source": [ "obj-16", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-18", 1 ], + "order": 0, + "source": [ "obj-17", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-18", 0 ], + "order": 1, + "source": [ "obj-17", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-20", 0 ], + "source": [ "obj-19", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-21", 0 ], + "source": [ "obj-20", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "order": 0, + "source": [ "obj-4", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 1, + "source": [ "obj-4", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "source": [ "obj-5", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 1 ], + "source": [ "obj-9", 0 ] + } + } + ], + "autosave": 0, + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + } +} \ No newline at end of file diff --git a/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat b/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat index e7201db..2dc4d58 100644 --- a/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat +++ b/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat @@ -1,737 +1,430 @@ { - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 760.0, - 560.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "PythonTap Tutorial 2", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A filter that knows the sample rate", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "The Documentation window has this tutorial's text. Turn on the audio with the speaker.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "noise~", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 150.0, - 60.0, - 24.0 - ], - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 185.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "delay", - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 180.0, - 185.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "alpha", - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "message", - "text": "alpha 1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 180.0, - 220.0, - 77.19999999999999, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "message", - "text": "clear", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 265.2, - 220.0, - 62.0, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ allpass", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 260.0, - 151.0, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ numpy_allpass", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 220.0, - 260.0, - 193.0, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "message", - "text": "1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 305.0, - 40.0, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "message", - "text": "2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 68.0, - 305.0, - 40.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "comment", - "text": "allpass.py, or numpy_allpass.py", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 120.0, - 305.0, - 220, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "selector~ 2 1", - "numinlets": 3, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 345.0, - 109.0, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "+~", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 380.0, - 40.0, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "comment", - "text": "with the dry signal: the notches", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 65.0, - 380.0, - 240, - 26.849999999999998 - ], - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 420.0, - 60.0, - 24.0 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "ezdac~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 20.0, - 455.0, - 45.0, - 45.0 - ], - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "metro 250 @active 1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 220.0, - 420.0, - 151.0, - 24.0 - ], - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "adstatus cpu", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "", - "int" - ], - "patching_rect": [ - 220.0, - 450.0, - 102.0, - 24.0 - ], - "id": "obj-20" - } - }, - { - "box": { - "maxclass": "number", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "bang" - ], - "patching_rect": [ - 220.0, - 480.0, - 60.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-21" - } - }, - { - "box": { - "maxclass": "comment", - "text": "CPU %", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 285.0, - 480.0, - 60, - 26.849999999999998 - ], - "id": "obj-22" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Both objects get every message: the attrui and the message boxes reach the one you hear and the one you don't alike.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 420.0, - 150.0, - 300, - 64.55 - ], - "linecount": 3, - "id": "obj-23" - } - }, - { - "box": { - "maxclass": "comment", - "text": "alpha 1 is refused by the class's validator: its traceback prints to the Max console, and alpha keeps its value.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 420.0, - 230.0, - 300, - 64.55 - ], - "linecount": 3, - "id": "obj-24" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-4", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-5", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-4", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-5", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-14", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-14", - 2 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-4", - 0 - ], - "destination": [ - "obj-15", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 0 - ], - "destination": [ - "obj-18", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 0 - ], - "destination": [ - "obj-18", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-19", - 0 - ], - "destination": [ - "obj-20", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-20", - 0 - ], - "destination": [ - "obj-21", - 0 - ] - } - } - ] - } -} + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 100.0, 760.0, 560.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "PythonTap Tutorial 2" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "A filter that knows the sample rate", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 330.0, 38.0 ], + "text": "The Documentation window has this tutorial's text. Turn on the audio with the speaker." + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 150.0, 60.0, 24.0 ], + "text": "noise~" + } + }, + { + "box": { + "attr": "delay", + "id": "obj-5", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 20.0, 185.0, 150.0, 24.0 ] + } + }, + { + "box": { + "attr": "alpha", + "id": "obj-6", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 180.0, 185.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 180.0, 220.0, 77.19999999999999, 24.0 ], + "text": "alpha 1" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 265.2, 220.0, 62.0, 24.0 ], + "text": "clear" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 260.0, 151.0, 24.0 ], + "text": "tap.python~ allpass" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 220.0, 260.0, 193.0, 24.0 ], + "text": "tap.python~ numpy_allpass" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 20.0, 305.0, 40.0, 24.0 ], + "text": "1" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 68.0, 305.0, 40.0, 24.0 ], + "text": "2" + } + }, + { + "box": { + "id": "obj-13", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 120.0, 305.0, 182.0, 38.0 ], + "text": "allpass.py, or numpy_allpass.py" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 345.0, 109.0, 24.0 ], + "text": "selector~ 2 1" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 380.0, 40.0, 24.0 ], + "text": "+~" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 65.0, 380.0, 240.0, 22.0 ], + "text": "with the dry signal: the notches" + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 420.0, 60.0, 24.0 ], + "text": "*~ 0.1" + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 20.0, 455.0, 45.0, 45.0 ] + } + }, + { + "box": { + "id": "obj-19", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "bang" ], + "patching_rect": [ 220.0, 420.0, 151.0, 24.0 ], + "text": "metro 250 @active 1" + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "", "int" ], + "patching_rect": [ 220.0, 450.0, 102.0, 24.0 ], + "text": "adstatus cpu" + } + }, + { + "box": { + "id": "obj-21", + "maxclass": "number", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "bang" ], + "parameter_enable": 0, + "patching_rect": [ 220.0, 480.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-22", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 285.0, 480.0, 60.0, 22.0 ], + "text": "CPU %" + } + }, + { + "box": { + "id": "obj-23", + "linecount": 3, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 420.0, 150.0, 300.0, 53.0 ], + "text": "Both objects get every message: the attrui and the message boxes reach the one you hear and the one you don't alike." + } + }, + { + "box": { + "id": "obj-24", + "linecount": 3, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 420.0, 230.0, 300.0, 53.0 ], + "text": "alpha 1 is refused by the class's validator: its traceback prints to the Max console, and alpha keeps its value." + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-14", 2 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-18", 1 ], + "order": 0, + "source": [ "obj-17", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-18", 0 ], + "order": 1, + "source": [ "obj-17", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-20", 0 ], + "source": [ "obj-19", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-21", 0 ], + "source": [ "obj-20", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "order": 0, + "source": [ "obj-4", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 1 ], + "order": 1, + "source": [ "obj-4", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 2, + "source": [ "obj-4", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "order": 0, + "source": [ "obj-5", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 1, + "source": [ "obj-5", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "order": 0, + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 1, + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "order": 0, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 1, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "order": 0, + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 1, + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 1 ], + "source": [ "obj-9", 0 ] + } + } + ], + "autosave": 0, + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + } +} \ No newline at end of file diff --git a/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat b/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat index b6d575c..576f27b 100644 --- a/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat +++ b/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat @@ -1,1078 +1,604 @@ { - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 820.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "PythonTap Tutorial 3", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "An object without audio", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "The Documentation window has this tutorial's text. Turn on the metro, and the audio to hear the rhythm.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 360, - 64.55 - ], - "linecount": 3, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "toggle", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "int" - ], - "patching_rect": [ - 20.0, - 150.0, - 24.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "metro 150", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 185.0, - 81.0, - 24.0 - ], - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "t b b", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "bang", - "bang" - ], - "patching_rect": [ - 20.0, - 220.0, - 53.0, - 24.0 - ], - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 120.0, - 220.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "steps", - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 280.0, - 220.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "pulses", - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "message", - "text": "getsteps", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 440.0, - 220.0, - 84.8, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python euclid", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 120.0, - 260.0, - 137.0, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "t l l", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 120.0, - 295.0, - 53.0, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 280.0, - 330.0, - 95.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 280.0, - 365.0, - 200, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 500.0, - 295.0, - 95.0, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 500.0, - 330.0, - 110, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "comment", - "text": "the dumpout", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 500.0, - 365.0, - 100, - 26.849999999999998 - ], - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "zl.len", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 120.0, - 330.0, - 60.0, - 24.0 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "counter", - "numinlets": 3, - "numoutlets": 4, - "outlettype": [ - "int", - "", - "", - "int" - ], - "patching_rect": [ - 20.0, - 330.0, - 67.0, - 24.0 - ], - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "%", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "int" - ], - "patching_rect": [ - 20.0, - 365.0, - 40.0, - 24.0 - ], - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "zl.lookup", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 20.0, - 400.0, - 81.0, - 24.0 - ], - "id": "obj-20" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "sel 1", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "bang", - "" - ], - "patching_rect": [ - 20.0, - 435.0, - 53.0, - 24.0 - ], - "id": "obj-21" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "click~", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 470.0, - 60.0, - 24.0 - ], - "id": "obj-22" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.5", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 505.0, - 60.0, - 24.0 - ], - "id": "obj-23" - } - }, - { - "box": { - "maxclass": "ezdac~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 20.0, - 540.0, - 45.0, - 45.0 - ], - "id": "obj-24" - } - }, - { - "box": { - "maxclass": "comment", - "text": "note_name.py: two outlets, right to left", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 280.0, - 410.0, - 260, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-25" - } - }, - { - "box": { - "maxclass": "kslider", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "int", - "int" - ], - "patching_rect": [ - 280.0, - 440.0, - 168.0, - 53.0 - ], - "parameter_enable": 0, - "id": "obj-26" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python note_name", - "numinlets": 1, - "numoutlets": 3, - "outlettype": [ - "", - "", - "" - ], - "patching_rect": [ - 280.0, - 500.0, - 158.0, - 24.0 - ], - "id": "obj-27" - } - }, - { - "box": { - "maxclass": "message", - "text": "set $1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 280.0, - 535.0, - 69.6, - 24.0 - ], - "id": "obj-28" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 280.0, - 570.0, - 60, - 24.0 - ], - "id": "obj-29" - } - }, - { - "box": { - "maxclass": "number", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "bang" - ], - "patching_rect": [ - 360.0, - 570.0, - 60.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-30" - } - }, - { - "box": { - "maxclass": "comment", - "text": "scale.py: a list through numpy", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 520.0, - 405.0, - 230, - 26.849999999999998 - ], - "id": "obj-31" - } - }, - { - "box": { - "maxclass": "message", - "text": "1 2 3 4", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 520.0, - 435.0, - 77.19999999999999, - 24.0 - ], - "id": "obj-32" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 520.0, - 470.0, - 140, - 24.0 - ], - "parameter_enable": 0, - "attr": "factor", - "id": "obj-33" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python scale", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 520.0, - 500.0, - 130.0, - 24.0 - ], - "id": "obj-34" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 520.0, - 535.0, - 95.0, - 24.0 - ], - "id": "obj-35" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 520.0, - 570.0, - 150, - 24.0 - ], - "id": "obj-36" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-4", - 0 - ], - "destination": [ - "obj-5", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-5", - 0 - ], - "destination": [ - "obj-6", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-6", - 1 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-11", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 1 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 1 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-18", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-18", - 0 - ], - "destination": [ - "obj-19", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 0 - ], - "destination": [ - "obj-19", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-19", - 0 - ], - "destination": [ - "obj-20", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-20", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-20", - 0 - ], - "destination": [ - "obj-21", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-21", - 0 - ], - "destination": [ - "obj-22", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-22", - 0 - ], - "destination": [ - "obj-23", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-23", - 0 - ], - "destination": [ - "obj-24", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-23", - 0 - ], - "destination": [ - "obj-24", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-26", - 0 - ], - "destination": [ - "obj-27", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-27", - 0 - ], - "destination": [ - "obj-28", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-28", - 0 - ], - "destination": [ - "obj-29", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-27", - 1 - ], - "destination": [ - "obj-30", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-32", - 0 - ], - "destination": [ - "obj-34", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-33", - 0 - ], - "destination": [ - "obj-34", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-34", - 0 - ], - "destination": [ - "obj-35", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-35", - 0 - ], - "destination": [ - "obj-36", - 0 - ] - } - } - ] - } -} + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 100.0, 820.0, 700.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "PythonTap Tutorial 3" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "An object without audio", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 3, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 300.0, 53.0 ], + "text": "The Documentation window has this tutorial's text. Turn on the metro, and the audio to hear the rhythm." + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "toggle", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "int" ], + "parameter_enable": 0, + "patching_rect": [ 20.0, 150.0, 24.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "bang" ], + "patching_rect": [ 20.0, 185.0, 81.0, 24.0 ], + "text": "metro 150" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "bang", "bang" ], + "patching_rect": [ 20.0, 220.0, 53.0, 24.0 ], + "text": "t b b" + } + }, + { + "box": { + "attr": "steps", + "id": "obj-7", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 120.0, 220.0, 150.0, 24.0 ] + } + }, + { + "box": { + "attr": "pulses", + "id": "obj-8", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 280.0, 220.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 440.0, 220.0, 84.8, 24.0 ], + "text": "getsteps" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 120.0, 260.0, 137.0, 24.0 ], + "text": "tap.python euclid" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 120.0, 295.0, 53.0, 24.0 ], + "text": "t l l" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 280.0, 330.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 280.0, 365.0, 200.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 500.0, 295.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 500.0, 330.0, 110.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 500.0, 365.0, 100.0, 22.0 ], + "text": "the dumpout" + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 120.0, 330.0, 60.0, 24.0 ], + "text": "zl.len" + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "newobj", + "numinlets": 5, + "numoutlets": 4, + "outlettype": [ "int", "", "", "int" ], + "patching_rect": [ 20.0, 330.0, 67.0, 24.0 ], + "text": "counter" + } + }, + { + "box": { + "id": "obj-19", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "int" ], + "patching_rect": [ 20.0, 365.0, 40.0, 24.0 ], + "text": "%" + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 20.0, 400.0, 81.0, 24.0 ], + "text": "zl.lookup" + } + }, + { + "box": { + "id": "obj-21", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "bang", "" ], + "patching_rect": [ 20.0, 435.0, 53.0, 24.0 ], + "text": "sel 1" + } + }, + { + "box": { + "id": "obj-22", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 470.0, 60.0, 24.0 ], + "text": "click~" + } + }, + { + "box": { + "id": "obj-23", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 505.0, 60.0, 24.0 ], + "text": "*~ 0.5" + } + }, + { + "box": { + "id": "obj-24", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 20.0, 540.0, 45.0, 45.0 ] + } + }, + { + "box": { + "id": "obj-25", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 280.0, 410.0, 226.0, 38.0 ], + "text": "note_name.py: two outlets, right to left" + } + }, + { + "box": { + "id": "obj-26", + "maxclass": "kslider", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "int", "int" ], + "parameter_enable": 0, + "patching_rect": [ 280.0, 440.0, 196.0, 34.0 ] + } + }, + { + "box": { + "id": "obj-27", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 3, + "outlettype": [ "", "", "" ], + "patching_rect": [ 280.0, 500.0, 158.0, 24.0 ], + "text": "tap.python note_name" + } + }, + { + "box": { + "id": "obj-28", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 280.0, 535.0, 69.6, 24.0 ], + "text": "set $1" + } + }, + { + "box": { + "id": "obj-29", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 280.0, 570.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-30", + "maxclass": "number", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "bang" ], + "parameter_enable": 0, + "patching_rect": [ 360.0, 570.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-31", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 520.0, 405.0, 230.0, 22.0 ], + "text": "scale.py: a list through numpy" + } + }, + { + "box": { + "id": "obj-32", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 520.0, 435.0, 77.19999999999999, 24.0 ], + "text": "1 2 3 4" + } + }, + { + "box": { + "attr": "factor", + "id": "obj-33", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 520.0, 470.0, 140.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-34", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 520.0, 500.0, 130.0, 24.0 ], + "text": "tap.python scale" + } + }, + { + "box": { + "id": "obj-35", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 520.0, 535.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-36", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 520.0, 570.0, 150.0, 24.0 ] + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-11", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-10", 1 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-11", 1 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "order": 0, + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-20", 1 ], + "order": 1, + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-19", 1 ], + "source": [ "obj-17", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-19", 0 ], + "source": [ "obj-18", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-20", 0 ], + "source": [ "obj-19", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-21", 0 ], + "source": [ "obj-20", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-22", 0 ], + "source": [ "obj-21", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-23", 0 ], + "source": [ "obj-22", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-24", 1 ], + "order": 0, + "source": [ "obj-23", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-24", 0 ], + "order": 1, + "source": [ "obj-23", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-27", 0 ], + "source": [ "obj-26", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-28", 0 ], + "source": [ "obj-27", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-30", 0 ], + "source": [ "obj-27", 1 ] + } + }, + { + "patchline": { + "destination": [ "obj-29", 0 ], + "source": [ "obj-28", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-34", 0 ], + "source": [ "obj-32", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-34", 0 ], + "source": [ "obj-33", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-35", 0 ], + "source": [ "obj-34", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-36", 0 ], + "source": [ "obj-35", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-5", 0 ], + "source": [ "obj-4", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-6", 0 ], + "source": [ "obj-5", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-6", 1 ] + } + }, + { + "patchline": { + "destination": [ "obj-18", 0 ], + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "autosave": 0, + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + } +} \ No newline at end of file diff --git a/extras/PythonTap Overview.maxpat b/extras/PythonTap Overview.maxpat index 66a5419..63ebc64 100644 --- a/extras/PythonTap Overview.maxpat +++ b/extras/PythonTap Overview.maxpat @@ -1,674 +1,391 @@ { - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 820.0, - 620.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "PythonTap", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Write Max objects in Python", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "PythonTap runs a Python class as a Max object: its typed fields become attributes, its methods messages, and saving the file reloads it in place. The classes live in the package's python folder; CPython 3.13, numpy and attrs come with it.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 360, - 102.25 - ], - "linecount": 5, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "tap.python~ — process audio with a Python class", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 200.0, - 360, - 26.849999999999998 - ], - "fontname": "Ableton Sans Bold Regular", - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 110", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 235.0, - 74.0, - 24.0 - ], - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 110.0, - 235.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "gain", - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ numpy_gain", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 270.0, - 172.0, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 20.0, - 305.0, - 60.0, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "ezdac~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 20.0, - 340.0, - 45.0, - 45.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "message", - "text": "help tap.python~", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 200.0, - 305.0, - 145.6, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "comment", - "text": "tap.python — a Python class as a Max object: what a method returns, it outputs", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 400.0, - 360, - 45.699999999999996 - ], - "linecount": 2, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "button", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "bang" - ], - "patching_rect": [ - 20.0, - 455.0, - 24.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 55.0, - 455.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "steps", - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python euclid", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 20.0, - 490.0, - 137.0, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 525.0, - 95.0, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 20.0, - 560.0, - 200, - 24.0 - ], - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "message", - "text": "help tap.python", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 220.0, - 490.0, - 138.0, - 24.0 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Learn", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 440.0, - 200.0, - 300, - 26.849999999999998 - ], - "fontname": "Ableton Sans Bold Regular", - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "comment", - "text": "The guide, Writing Max Objects in Python, and three tutorials are in the Documentation window: Reference > Package Docs > PythonTap. The tutorials' patchers:", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 440.0, - 230.0, - 330, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "message", - "text": "load pythontap_01_gain.maxpat", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 440.0, - 305.0, - 244.39999999999998, - 24.0 - ], - "id": "obj-20" - } - }, - { - "box": { - "maxclass": "message", - "text": "load pythontap_02_filter.maxpat", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 440.0, - 340.0, - 259.6, - 24.0 - ], - "id": "obj-21" - } - }, - { - "box": { - "maxclass": "message", - "text": "load pythontap_03_control.maxpat", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 440.0, - 375.0, - 267.2, - 24.0 - ], - "id": "obj-22" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "pcontrol", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 440.0, - 555.0, - 74.0, - 24.0 - ], - "id": "obj-23" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Every rule, the performance measurements, and how to add Python packages to the runtime:", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 440.0, - 420.0, - 330, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-24" - } - }, - { - "box": { - "maxclass": "message", - "text": ";\rmax launchbrowser https://github.com/tap/PythonTap#readme", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 440.0, - 465.0, - 330, - 42.0 - ], - "linecount": 2, - "id": "obj-25" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-5", - 0 - ], - "destination": [ - "obj-7", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-7", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-8", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-9", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-16", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-20", - 0 - ], - "destination": [ - "obj-23", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-21", - 0 - ], - "destination": [ - "obj-23", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-22", - 0 - ], - "destination": [ - "obj-23", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-23", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 0 - ], - "destination": [ - "obj-23", - 0 - ] - } - } - ] - } -} + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 100.0, 820.0, 620.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "PythonTap" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "Write Max objects in Python", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 5, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 338.0, 85.0 ], + "text": "PythonTap runs a Python class as a Max object: its typed fields become attributes, its methods messages, and saving the file reloads it in place. The classes live in the package's python folder; CPython 3.13, numpy and attrs come with it." + } + }, + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "id": "obj-4", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 200.0, 360.0, 22.0 ], + "text": "tap.python~ — process audio with a Python class" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 235.0, 74.0, 24.0 ], + "text": "saw~ 110" + } + }, + { + "box": { + "attr": "gain", + "id": "obj-6", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 110.0, 235.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 270.0, 172.0, 24.0 ], + "text": "tap.python~ numpy_gain" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 20.0, 305.0, 60.0, 24.0 ], + "text": "*~ 0.2" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 20.0, 340.0, 45.0, 45.0 ] + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 200.0, 305.0, 145.6, 24.0 ], + "text": "help tap.python~" + } + }, + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "id": "obj-11", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 400.0, 360.0, 38.0 ], + "text": "tap.python — a Python class as a Max object: what a method returns, it outputs" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "button", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "bang" ], + "parameter_enable": 0, + "patching_rect": [ 20.0, 455.0, 24.0, 24.0 ] + } + }, + { + "box": { + "attr": "steps", + "id": "obj-13", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 55.0, 455.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 20.0, 490.0, 137.0, 24.0 ], + "text": "tap.python euclid" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 20.0, 525.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 20.0, 560.0, 200.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 220.0, 490.0, 138.0, 24.0 ], + "text": "help tap.python" + } + }, + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "id": "obj-18", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 440.0, 200.0, 300.0, 22.0 ], + "text": "Learn" + } + }, + { + "box": { + "id": "obj-19", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 440.0, 230.0, 306.0, 69.0 ], + "text": "The guide, Writing Max Objects in Python, and three tutorials are in the Documentation window: Reference > Package Docs > PythonTap. The tutorials' patchers:" + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 440.0, 305.0, 244.39999999999998, 24.0 ], + "text": "load pythontap_01_gain.maxpat" + } + }, + { + "box": { + "id": "obj-21", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 440.0, 340.0, 259.6, 24.0 ], + "text": "load pythontap_02_filter.maxpat" + } + }, + { + "box": { + "id": "obj-22", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 440.0, 375.0, 267.2, 24.0 ], + "text": "load pythontap_03_control.maxpat" + } + }, + { + "box": { + "id": "obj-23", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 440.0, 555.0, 74.0, 24.0 ], + "text": "pcontrol" + } + }, + { + "box": { + "id": "obj-24", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 440.0, 420.0, 330.0, 38.0 ], + "text": "Every rule, the performance measurements, and how to add Python packages to the runtime:" + } + }, + { + "box": { + "id": "obj-25", + "linecount": 2, + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 440.0, 465.0, 366.0, 40.0 ], + "text": ";\rmax launchbrowser https://github.com/tap/PythonTap#readme" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-23", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 0 ], + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-23", 0 ], + "source": [ "obj-17", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-23", 0 ], + "source": [ "obj-20", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-23", 0 ], + "source": [ "obj-21", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-23", 0 ], + "source": [ "obj-22", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-7", 0 ], + "source": [ "obj-5", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-7", 0 ], + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-8", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 1 ], + "order": 0, + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 1, + "source": [ "obj-8", 0 ] + } + } + ], + "autosave": 0, + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + } +} \ No newline at end of file diff --git a/help/tap.python.maxhelp b/help/tap.python.maxhelp index 02c010b..0a02d97 100644 --- a/help/tap.python.maxhelp +++ b/help/tap.python.maxhelp @@ -1,2451 +1,1429 @@ { - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 800.0, - 620.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "newobj", - "text": "p basic", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 20.0, - 67.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "tap.python", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Run a Python class as a Max object", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "[tap.python name] loads python/name.py from this package and makes an object of the class name in it: its typed fields are attributes, its methods are messages, and what a method returns is what the object outputs.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 102.25 - ], - "linecount": 5, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "This one is euclid.py. A bang outputs a Euclidean rhythm: steps beats, pulses of them on, spread as evenly as they go. steps and pulses are attributes, from the class's two typed fields.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 185.0, - 330.0, - 102.25 - ], - "linecount": 5, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Open python/euclid.py in a text editor to see the class. Save a change and the object loads it again, keeping steps and pulses; a mistake prints its traceback to the Max console, and the object outputs nothing until a save fixes it.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 280.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Every object using the file shares one load of it per save, tap.python~ objects included.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 390.0, - 330.0, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "button", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "bang" - ], - "patching_rect": [ - 400.0, - 90.0, - 24.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "comment", - "text": "bang: output the rhythm", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 430.0, - 90.0, - 200, - 26.849999999999998 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 130.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "steps", - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 560.0, - 130.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "pulses", - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "message", - "text": "getsteps", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 560.0, - 170.0, - 84.8, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "message", - "text": "filechanged", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 652.8, - 170.0, - 107.6, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python euclid", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 400.0, - 215.0, - 137.0, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 265.0, - 95.0, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 300.0, - 230, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 650.0, - 265.0, - 95.0, - 24.0 - ], - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 650.0, - 300.0, - 120, - 24.0 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "comment", - "text": "what a method returns", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 400.0, - 335.0, - 200, - 26.849999999999998 - ], - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "comment", - "text": "the dumpout: get + an attribute's name", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 650.0, - 335.0, - 190, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "comment", - "text": "filechanged reloads the file at once; saving it does that for you.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 400.0, - 390.0, - 330, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-20" - } - }, - { - "box": { - "maxclass": "comment", - "text": "More in the other tabs: lists, several outlets, messages and methods, threads.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 400.0, - 435.0, - 330, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-21" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 1 - ], - "destination": [ - "obj-16", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-16", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p lists", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 120.0, - 20.0, - 67.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "Lists in, lists out", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A list message through numpy", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "scale.py's method list(self, values: np.ndarray) takes the whole list as one numpy array — a last parameter hinted np.ndarray, or list[float], takes every argument left — and returns an array, which the object outputs as a list.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "What a method returns is output by its type: a number as a number, a str as symbol and the string, and a list, a range or a numpy array as a list.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 205.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A list whose first element is a str outputs the message it names: return [\"note\", 60, 100] and the object outputs note 60 100. A dict, a set or an object outputs nothing, and the console says why.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 285.0, - 330.0, - 102.25 - ], - "linecount": 5, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "message", - "text": "1 2 3 4", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 90.0, - 77.19999999999999, - 24.0 - ], - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "message", - "text": "0.5 0.25 0.125", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 485.2, - 90.0, - 130.39999999999998, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 130.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "factor", - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 560.0, - 130.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "offset", - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python scale @factor 2 @offset 1", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 400.0, - 175.0, - 270.0, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 225.0, - 95.0, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 260.0, - 300, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "comment", - "text": "each value times factor, plus offset", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 400.0, - 295.0, - 300, - 26.849999999999998 - ], - "id": "obj-13" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-11", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p outlets", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 220.0, - 20.0, - 81.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "One value per outlet", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A method hinted to return a tuple", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "note_name.py's method int(self, note: int) -> tuple[str, int] returns two values, so the object has two outlets for them, and outputs them right to left, as Max objects do: the octave, then the name.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 102.25 - ], - "linecount": 5, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "The name is a str, which the object outputs as symbol and the string: sel matches it, and route needs route symbol first. Return it in a list, [\"C\"], to output the message C instead.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 205.0, - 330.0, - 102.25 - ], - "linecount": 5, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "The object has as many outlets as the widest tuple return hint among the class's methods — a method returning one value fills the first — plus the dumpout at the right. A save that changes the number changes the outlets in place, keeping their patch cords.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 305.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "kslider", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "int", - "int" - ], - "patching_rect": [ - 400.0, - 90.0, - 168.0, - 53.0 - ], - "parameter_enable": 0, - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "number", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "bang" - ], - "patching_rect": [ - 615.0, - 105.0, - 60.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python note_name", - "numinlets": 1, - "numoutlets": 3, - "outlettype": [ - "", - "", - "" - ], - "patching_rect": [ - 400.0, - 175.0, - 158.0, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "message", - "text": "set $1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 225.0, - 69.6, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 260.0, - 120, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "number", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "bang" - ], - "patching_rect": [ - 540.0, - 225.0, - 60.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "sel C", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 620.0, - 225.0, - 53.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "button", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "bang" - ], - "patching_rect": [ - 620.0, - 260.0, - 24.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "comment", - "text": "name", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 400.0, - 290.0, - 120, - 26.849999999999998 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "comment", - "text": "octave", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 540.0, - 255.0, - 70, - 26.849999999999998 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "comment", - "text": "every C", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 650.0, - 260.0, - 80, - 26.849999999999998 - ], - "id": "obj-16" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-8", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-8", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 1 - ], - "destination": [ - "obj-11", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p messages", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 320.0, - 20.0, - 88.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "Messages and methods", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "The class's methods are the object's messages", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "With no argument the object loads python/default.py, which tap.python~ loads too. Its public methods are messages, called according to their signatures: bang returns the gain, float and int set it, greet prints to the Max console.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "process() is an ordinary method here: process 0.25 calls it, and outputs what it returns — a way to try a tap.python~ class sample by sample.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 205.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A method named anything answers every message the class has no method or attribute for, with the message's name first: def anything(self, selector: str, *args). Without one, the object doesn't understand it — try nonesuch.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 280.0, - 330.0, - 102.25 - ], - "linecount": 5, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Names Max and the object keep — dumpout, filechanged, assist and Max's own messages — are not exposed: the console says so, so that you can rename the method.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 380.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "message", - "text": "bang", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 90.0, - 54.4, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "message", - "text": "float 0.5", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 462.4, - 90.0, - 92.39999999999999, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "message", - "text": "int 2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 562.8, - 90.0, - 62.0, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "message", - "text": "greet max", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 632.8, - 90.0, - 92.39999999999999, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "message", - "text": "process 0.25", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 125.0, - 115.19999999999999, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "message", - "text": "nonesuch 1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 523.2, - 125.0, - 100.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 165.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "gain", - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 400.0, - 210.0, - 88.0, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 260.0, - 95.0, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 295.0, - 120, - 24.0 - ], - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "comment", - "text": "what the method returned", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 530.0, - 295.0, - 180, - 26.849999999999998 - ], - "id": "obj-17" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-16", - 0 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p threads", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 420.0, - 20.0, - 81.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "Threads", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A message runs on the thread it arrives on", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "As with any Max object, a message runs on the thread it arrives on, and what the method returns is output before the message returns. From a click or a message box that is Max's main thread; from a metro with Overdrive on, the scheduler thread — where a long method holds the scheduler while it runs.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 139.95 - ], - "linecount": 7, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "With Scheduler in Audio Interrupt on, and audio running, the scheduler thread is the audio thread: Python then runs on it, where a long method, a reload or another object's Python can interrupt the audio. The object says so in the console, once. deferlow moves the message to the main thread.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 225.0, - 330.0, - 139.95 - ], - "linecount": 7, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Output is what a method returns: a thread the class starts itself has no outlet to reach.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 360.0, - 330.0, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "toggle", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "int" - ], - "patching_rect": [ - 400.0, - 90.0, - 24.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "metro 125", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 125.0, - 81.0, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python euclid", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 400.0, - 210.0, - 137.0, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "deferlow", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 550.0, - 165.0, - 74.0, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python euclid", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "" - ], - "patching_rect": [ - 550.0, - 210.0, - 137.0, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 260.0, - 95.0, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 295.0, - 140, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "prepend set", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 550.0, - 260.0, - 95.0, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "message", - "text": "", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 550.0, - 295.0, - 140, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "comment", - "text": "on the scheduler thread (Overdrive on)", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 400.0, - 335.0, - 140, - 64.55 - ], - "linecount": 3, - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "comment", - "text": "on the main thread", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 550.0, - 335.0, - 140, - 26.849999999999998 - ], - "id": "obj-16" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-7", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-8", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-10", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-11", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-14", - 0 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p ?", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 520.0, - 20.0, - 40.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [], - "lines": [], - "showontab": 1 - }, - "id": "obj-6" - } - } - ], - "lines": [], - "showrootpatcherontab": 0, - "showontab": 0 - } -} + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 100.0, 800.0, 620.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showrootpatcherontab": 0, + "showontab": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 152.0, 800.0, 568.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "tap.python" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "Run a Python class as a Max object", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 5, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 316.0, 85.0 ], + "text": "[tap.python name] loads python/name.py from this package and makes an object of the class name in it: its typed fields are attributes, its methods are messages, and what a method returns is what the object outputs." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 5, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 185.0, 278.0, 85.0 ], + "text": "This one is euclid.py. A bang outputs a Euclidean rhythm: steps beats, pulses of them on, spread as evenly as they go. steps and pulses are attributes, from the class's two typed fields." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 280.0, 264.0, 100.0 ], + "text": "Open python/euclid.py in a text editor to see the class. Save a change and the object loads it again, keeping steps and pulses; a mistake prints its traceback to the Max console, and the object outputs nothing until a save fixes it." + } + }, + { + "box": { + "id": "obj-6", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 390.0, 330.0, 38.0 ], + "text": "Every object using the file shares one load of it per save, tap.python~ objects included." + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "button", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "bang" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 90.0, 24.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 430.0, 90.0, 200.0, 22.0 ], + "text": "bang: output the rhythm" + } + }, + { + "box": { + "attr": "steps", + "id": "obj-9", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 130.0, 150.0, 24.0 ] + } + }, + { + "box": { + "attr": "pulses", + "id": "obj-10", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 560.0, 130.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 560.0, 170.0, 84.8, 24.0 ], + "text": "getsteps" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 652.8, 170.0, 107.6, 24.0 ], + "text": "filechanged" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 400.0, 215.0, 137.0, 24.0 ], + "text": "tap.python euclid" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 265.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 300.0, 230.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 650.0, 265.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 650.0, 300.0, 120.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 400.0, 335.0, 200.0, 22.0 ], + "text": "what a method returns" + } + }, + { + "box": { + "id": "obj-19", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 650.0, 335.0, 190.0, 38.0 ], + "text": "the dumpout: get + an attribute's name" + } + }, + { + "box": { + "id": "obj-20", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 400.0, 390.0, 330.0, 38.0 ], + "text": "filechanged reloads the file at once; saving it does that for you." + } + }, + { + "box": { + "id": "obj-21", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 400.0, 435.0, 330.0, 38.0 ], + "text": "More in the other tabs: lists, several outlets, messages and methods, threads." + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 0 ], + "source": [ "obj-13", 1 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "source": [ "obj-16", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 20.0, 20.0, 67.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p basic" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 568.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "Lists in, lists out" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "A list message through numpy", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 266.0, 100.0 ], + "text": "scale.py's method list(self, values: np.ndarray) takes the whole list as one numpy array — a last parameter hinted np.ndarray, or list[float], takes every argument left — and returns an array, which the object outputs as a list." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 205.0, 288.0, 69.0 ], + "text": "What a method returns is output by its type: a number as a number, a str as symbol and the string, and a list, a range or a numpy array as a list." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 5, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 285.0, 288.0, 85.0 ], + "text": "A list whose first element is a str outputs the message it names: return [\"note\", 60, 100] and the object outputs note 60 100. A dict, a set or an object outputs nothing, and the console says why." + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 90.0, 77.19999999999999, 24.0 ], + "text": "1 2 3 4" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 485.2, 90.0, 130.39999999999998, 24.0 ], + "text": "0.5 0.25 0.125" + } + }, + { + "box": { + "attr": "factor", + "id": "obj-8", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 130.0, 150.0, 24.0 ] + } + }, + { + "box": { + "attr": "offset", + "id": "obj-9", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 560.0, 130.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 400.0, 175.0, 270.0, 24.0 ], + "text": "tap.python scale @factor 2 @offset 1" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 225.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 260.0, 300.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 400.0, 295.0, 300.0, 22.0 ], + "text": "each value times factor, plus offset" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-11", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 120.0, 20.0, 67.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p lists" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 568.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "One value per outlet" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "A method hinted to return a tuple", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 5, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 288.0, 85.0 ], + "text": "note_name.py's method int(self, note: int) -> tuple[str, int] returns two values, so the object has two outlets for them, and outputs them right to left, as Max objects do: the octave, then the name." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 5, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 205.0, 252.0, 85.0 ], + "text": "The name is a str, which the object outputs as symbol and the string: sel matches it, and route needs route symbol first. Return it in a list, [\"C\"], to output the message C instead." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 305.0, 304.0, 100.0 ], + "text": "The object has as many outlets as the widest tuple return hint among the class's methods — a method returning one value fills the first — plus the dumpout at the right. A save that changes the number changes the outlets in place, keeping their patch cords." + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "kslider", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "int", "int" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 90.0, 196.0, 34.0 ] + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "number", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "bang" ], + "parameter_enable": 0, + "patching_rect": [ 615.0, 105.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 3, + "outlettype": [ "", "", "" ], + "patching_rect": [ 400.0, 175.0, 158.0, 24.0 ], + "text": "tap.python note_name" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 225.0, 69.6, 24.0 ], + "text": "set $1" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 260.0, 120.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "number", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "bang" ], + "parameter_enable": 0, + "patching_rect": [ 540.0, 225.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "bang", "" ], + "patching_rect": [ 620.0, 225.0, 53.0, 24.0 ], + "text": "sel C" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "button", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "bang" ], + "parameter_enable": 0, + "patching_rect": [ 620.0, 260.0, 24.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 400.0, 290.0, 120.0, 22.0 ], + "text": "name" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 540.0, 255.0, 70.0, 22.0 ], + "text": "octave" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 650.0, 260.0, 80.0, 22.0 ], + "text": "every C" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-8", 0 ], + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-8", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-11", 0 ], + "source": [ "obj-8", 1 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "order": 0, + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 1, + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 220.0, 20.0, 81.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p outlets" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 568.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "Messages and methods" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "The class's methods are the object's messages", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 286.0, 100.0 ], + "text": "With no argument the object loads python/default.py, which tap.python~ loads too. Its public methods are messages, called according to their signatures: bang returns the gain, float and int set it, greet prints to the Max console." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 205.0, 278.0, 69.0 ], + "text": "process() is an ordinary method here: process 0.25 calls it, and outputs what it returns — a way to try a tap.python~ class sample by sample." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 5, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 280.0, 330.0, 85.0 ], + "text": "A method named anything answers every message the class has no method or attribute for, with the message's name first: def anything(self, selector: str, *args). Without one, the object doesn't understand it — try nonesuch." + } + }, + { + "box": { + "id": "obj-6", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 380.0, 330.0, 69.0 ], + "text": "Names Max and the object keep — dumpout, filechanged, assist and Max's own messages — are not exposed: the console says so, so that you can rename the method." + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 90.0, 54.4, 24.0 ], + "text": "bang" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 462.4, 90.0, 92.39999999999999, 24.0 ], + "text": "float 0.5" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 562.8, 90.0, 62.0, 24.0 ], + "text": "int 2" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 632.8, 90.0, 92.39999999999999, 24.0 ], + "text": "greet max" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 125.0, 115.19999999999999, 24.0 ], + "text": "process 0.25" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 523.2, 125.0, 100.0, 24.0 ], + "text": "nonesuch 1" + } + }, + { + "box": { + "attr": "gain", + "id": "obj-13", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 165.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 400.0, 210.0, 88.0, 24.0 ], + "text": "tap.python" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 260.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 295.0, 120.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 530.0, 295.0, 180.0, 22.0 ], + "text": "what the method returned" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 0 ], + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 320.0, 20.0, 88.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p messages" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 568.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "Threads" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "A message runs on the thread it arrives on", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 7, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 300.0, 116.0 ], + "text": "As with any Max object, a message runs on the thread it arrives on, and what the method returns is output before the message returns. From a click or a message box that is Max's main thread; from a metro with Overdrive on, the scheduler thread — where a long method holds the scheduler while it runs." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 7, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 225.0, 284.0, 116.0 ], + "text": "With Scheduler in Audio Interrupt on, and audio running, the scheduler thread is the audio thread: Python then runs on it, where a long method, a reload or another object's Python can interrupt the audio. The object says so in the console, once. deferlow moves the message to the main thread." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 360.0, 330.0, 38.0 ], + "text": "Output is what a method returns: a thread the class starts itself has no outlet to reach." + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "toggle", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "int" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 90.0, 24.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "bang" ], + "patching_rect": [ 400.0, 125.0, 81.0, 24.0 ], + "text": "metro 125" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 400.0, 210.0, 137.0, 24.0 ], + "text": "tap.python euclid" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 550.0, 165.0, 74.0, 24.0 ], + "text": "deferlow" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "" ], + "patching_rect": [ 550.0, 210.0, 137.0, 24.0 ], + "text": "tap.python euclid" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 260.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 295.0, 140.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 550.0, 260.0, 95.0, 24.0 ], + "text": "prepend set" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 550.0, 295.0, 140.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-15", + "linecount": 3, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 400.0, 335.0, 128.0, 53.0 ], + "text": "on the scheduler thread (Overdrive on)" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 550.0, 335.0, 140.0, 22.0 ], + "text": "on the main thread" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-14", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-7", 0 ], + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-8", 0 ], + "order": 1, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 0, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-11", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-10", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 420.0, 20.0, 81.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p threads" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 568.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [], + "lines": [], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 520.0, 20.0, 40.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p ?" + } + } + ], + "lines": [], + "autosave": 0, + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + } +} \ No newline at end of file diff --git a/help/tap.python~.maxhelp b/help/tap.python~.maxhelp index 1e67da0..a9de6f3 100644 --- a/help/tap.python~.maxhelp +++ b/help/tap.python~.maxhelp @@ -1,2461 +1,1433 @@ { - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 800.0, - 680.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "newobj", - "text": "p basic", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 20.0, - 67.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "tap.python~", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Process audio with a Python class", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "[tap.python~ name] loads python/name.py from this package and runs the class name in it as an audio object. With no argument it loads python/default.py: open it to follow along.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Its typed fields are attributes (gain), its public methods are messages called according to their signatures (greet, float, int, bang), and its process() method runs on the signal — here once per sample; the numpy tab has the form that runs once per vector.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 170.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Save the .py file and the object loads it again, keeping its attribute values, and the audio carries on with the new code. A mistake prints its traceback to the Max console, and the object outputs silence until a save fixes it.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 285.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "comment", - "text": "@mode worker runs process() on a thread of its own, @latency milliseconds (30) behind the audio, so that a reload or a message never holds the audio up.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 400.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 110", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 90.0, - 74.0, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 221", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 480.0, - 90.0, - 74.0, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.5", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 125.0, - 60.0, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "message", - "text": "greet max", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 160.0, - 92.39999999999999, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "message", - "text": "float 0.5", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 500.4, - 160.0, - 92.39999999999999, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "message", - "text": "int 2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 600.8, - 160.0, - 62.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "message", - "text": "filechanged", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 670.8, - 160.0, - 107.6, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 195.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "gain", - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 235.0, - 95.0, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "comment", - "text": "filechanged reloads at once; saving the file does it for you", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 490.0, - 235.0, - 260, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "scope~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 490.0, - 280.0, - 150, - 70 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 280.0, - 60.0, - 24.0 - ], - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "ezdac~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 400.0, - 315.0, - 45.0, - 45.0 - ], - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "metro 250 @active 1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 660.0, - 280.0, - 151.0, - 24.0 - ], - "id": "obj-20" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "adstatus cpu", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "", - "int" - ], - "patching_rect": [ - 660.0, - 310.0, - 102.0, - 24.0 - ], - "id": "obj-21" - } - }, - { - "box": { - "maxclass": "number", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "bang" - ], - "patching_rect": [ - 660.0, - 340.0, - 60.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-22" - } - }, - { - "box": { - "maxclass": "comment", - "text": "CPU %", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 725.0, - 340.0, - 60, - 26.849999999999998 - ], - "id": "obj-23" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-18", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-18", - 0 - ], - "destination": [ - "obj-19", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-18", - 0 - ], - "destination": [ - "obj-19", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-20", - 0 - ], - "destination": [ - "obj-21", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-21", - 0 - ], - "destination": [ - "obj-22", - 0 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p numpy", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 120.0, - 20.0, - 67.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "Per vector, with numpy", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "One call per signal vector instead of one per sample", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "process(self, x: float) -> float is called once per sample: simplest to write, but every line of Python in it runs tens of thousands of times a second.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "process(self, x: np.ndarray) -> np.ndarray is called once per signal vector, with the vector as a numpy array, and numpy then works on the whole of it at C speed: the form for anything with real work in it. numpy_gain.py is default.py's gain written that way.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 170.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Choose one with the message boxes and watch the CPU meter: the ReadMe's performance note has the measurements, per sample and per vector, at 48 and 96 kHz.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 285.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Turn on audio with the speaker.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 365.0, - 330.0, - 26.849999999999998 - ], - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 110", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 90.0, - 74.0, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ default", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 165.0, - 151.0, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ numpy_gain", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 570.0, - 165.0, - 172.0, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 130.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "gain", - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 570.0, - 130.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "gain", - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "message", - "text": "1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 210.0, - 40.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "message", - "text": "2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 448.0, - 210.0, - 40.0, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "comment", - "text": "per sample, per vector", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 500.0, - 210.0, - 170, - 26.849999999999998 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "selector~ 2 1", - "numinlets": 3, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 250.0, - 109.0, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 290.0, - 60.0, - 24.0 - ], - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "ezdac~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 400.0, - 325.0, - 45.0, - 45.0 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "metro 250 @active 1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 570.0, - 290.0, - 151.0, - 24.0 - ], - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "adstatus cpu", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "", - "int" - ], - "patching_rect": [ - 570.0, - 320.0, - 102.0, - 24.0 - ], - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "number", - "numinlets": 1, - "numoutlets": 2, - "outlettype": [ - "", - "bang" - ], - "patching_rect": [ - 570.0, - 350.0, - 60.0, - 24.0 - ], - "parameter_enable": 0, - "id": "obj-20" - } - }, - { - "box": { - "maxclass": "comment", - "text": "CPU %", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 635.0, - 350.0, - 60, - 26.849999999999998 - ], - "id": "obj-21" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-8", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-8", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-9", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-15", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-15", - 2 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-16", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-16", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-16", - 0 - ], - "destination": [ - "obj-17", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-18", - 0 - ], - "destination": [ - "obj-19", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-19", - 0 - ], - "destination": [ - "obj-20", - 0 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p allpass", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 220.0, - 20.0, - 81.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "A filter that knows the sample rate", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "prepare(sample_rate, vector_size)", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "allpass.py is a Schroeder allpass filter: it passes every frequency at the same level and shifts their phase, so mixed with the dry signal it notches the spectrum. Its delay is an attribute in milliseconds, which it turns into samples.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "For that it needs the sample rate: an optional method prepare(self, sample_rate: float, vector_size: int) -> None is called before the object processes any audio, again whenever the rate or the vector size changes, and on every reload before the new code runs.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 205.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Its fields are attrs fields with validators: alpha must stay strictly between -1 and 1. Try alpha 1 — the validator's error prints to the console, and alpha keeps its value.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 325.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "comment", - "text": "numpy_allpass.py computes exactly the same, a vector at a time.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 415.0, - 330.0, - 45.699999999999996 - ], - "linecount": 2, - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "noise~", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 90.0, - 60.0, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 125.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "delay", - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 560.0, - 125.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "alpha", - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "message", - "text": "alpha 1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 560.0, - 160.0, - 77.19999999999999, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "message", - "text": "clear", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 645.2, - 160.0, - 62.0, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ allpass", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 195.0, - 151.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "+~", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 235.0, - 40.0, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "comment", - "text": "with the dry signal", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 445.0, - 235.0, - 150, - 26.849999999999998 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 275.0, - 60.0, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "ezdac~", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 400.0, - 310.0, - 45.0, - 45.0 - ], - "id": "obj-16" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-13", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-13", - 0 - ], - "destination": [ - "obj-15", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-16", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-16", - 1 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p mc", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 320.0, - 20.0, - 46.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [ - { - "box": { - "maxclass": "comment", - "text": "Many channels", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 15.0, - 600.0, - 45.699999999999996 - ], - "fontsize": 26.0, - "fontname": "Ableton Sans Bold Regular", - "id": "obj-1" - } - }, - { - "box": { - "maxclass": "comment", - "text": "mc., and a class with several inputs", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 55.0, - 600.0, - 29.75 - ], - "fontsize": 15.0, - "textcolor": [ - 0.976470588235294, - 0.733333333333333, - 0.258823529411765, - 1.0 - ], - "id": "obj-2" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Wrap the object in mc. to run one instance per channel of a multichannel signal: [mc.tap.python~ numpy_gain] here, over two channels. The class's attributes and messages are each instance's own, so the MC wrapper passes them on through its own messages: setvalue, an instance's number and the message, for one; applyvalues, the name and a value for each, for all.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 90.0, - 330.0, - 177.65 - ], - "linecount": 9, - "id": "obj-3" - } - }, - { - "box": { - "maxclass": "comment", - "text": "Or write one class with several channels: process()'s parameters are the object's signal inlets and its return hint its outlets. stereo_width.py takes left and right, returns tuple[np.ndarray, np.ndarray], and gets two of each.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 255.0, - 330.0, - 121.1 - ], - "linecount": 6, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "comment", - "text": "A save that changes process()'s inputs or outputs changes the object's inlets and outlets to match, keeping the patch cords of those that stay.", - "numinlets": 1, - "numoutlets": 0, - "patching_rect": [ - 20.0, - 370.0, - 330.0, - 83.39999999999999 - ], - "linecount": 4, - "id": "obj-5" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 110", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 90.0, - 74.0, - 24.0 - ], - "id": "obj-6" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 165", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 480.0, - 90.0, - 74.0, - 24.0 - ], - "id": "obj-7" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "mc.pack~ 2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "multichannelsignal" - ], - "patching_rect": [ - 400.0, - 125.0, - 88.0, - 24.0 - ], - "id": "obj-8" - } - }, - { - "box": { - "maxclass": "message", - "text": "applyvalues gain 0.5 0.25", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 400.0, - 160.0, - 214.0, - 24.0 - ], - "id": "obj-9" - } - }, - { - "box": { - "maxclass": "message", - "text": "setvalue 2 gain 0.1", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 622.0, - 160.0, - 168.4, - 24.0 - ], - "id": "obj-10" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "mc.tap.python~ numpy_gain", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "multichannelsignal" - ], - "patching_rect": [ - 400.0, - 195.0, - 193.0, - 24.0 - ], - "id": "obj-11" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "mc.*~ 0.2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "multichannelsignal" - ], - "patching_rect": [ - 400.0, - 230.0, - 81.0, - 24.0 - ], - "id": "obj-12" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "mc.dac~ 1 2", - "numinlets": 1, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 400.0, - 265.0, - 95.0, - 24.0 - ], - "id": "obj-13" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 110", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 330.0, - 74.0, - 24.0 - ], - "id": "obj-14" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "saw~ 110.5", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 480.0, - 330.0, - 88.0, - 24.0 - ], - "id": "obj-15" - } - }, - { - "box": { - "maxclass": "attrui", - "numinlets": 1, - "numoutlets": 1, - "outlettype": [ - "" - ], - "patching_rect": [ - 570.0, - 330.0, - 150, - 24.0 - ], - "parameter_enable": 0, - "attr": "width", - "id": "obj-16" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "tap.python~ stereo_width", - "numinlets": 2, - "numoutlets": 2, - "outlettype": [ - "signal", - "signal" - ], - "patching_rect": [ - 400.0, - 370.0, - 186.0, - 24.0 - ], - "id": "obj-17" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 400.0, - 405.0, - 60.0, - 24.0 - ], - "id": "obj-18" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "*~ 0.2", - "numinlets": 2, - "numoutlets": 1, - "outlettype": [ - "signal" - ], - "patching_rect": [ - 480.0, - 405.0, - 60.0, - 24.0 - ], - "id": "obj-19" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "dac~ 1 2", - "numinlets": 2, - "numoutlets": 0, - "outlettype": [], - "patching_rect": [ - 400.0, - 440.0, - 74.0, - 24.0 - ], - "id": "obj-20" - } - } - ], - "lines": [ - { - "patchline": { - "source": [ - "obj-6", - 0 - ], - "destination": [ - "obj-8", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-7", - 0 - ], - "destination": [ - "obj-8", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-8", - 0 - ], - "destination": [ - "obj-11", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-9", - 0 - ], - "destination": [ - "obj-11", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-10", - 0 - ], - "destination": [ - "obj-11", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-11", - 0 - ], - "destination": [ - "obj-12", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-12", - 0 - ], - "destination": [ - "obj-13", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-14", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-15", - 0 - ], - "destination": [ - "obj-17", - 1 - ] - } - }, - { - "patchline": { - "source": [ - "obj-16", - 0 - ], - "destination": [ - "obj-17", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 0 - ], - "destination": [ - "obj-18", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-17", - 1 - ], - "destination": [ - "obj-19", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-18", - 0 - ], - "destination": [ - "obj-20", - 0 - ] - } - }, - { - "patchline": { - "source": [ - "obj-19", - 0 - ], - "destination": [ - "obj-20", - 1 - ] - } - } - ], - "showontab": 1 - }, - "id": "obj-4" - } - }, - { - "box": { - "maxclass": "newobj", - "text": "p ?", - "numinlets": 0, - "numoutlets": 0, - "patching_rect": [ - 420.0, - 20.0, - 40.0, - 24.0 - ], - "patcher": { - "fileversion": 1, - "appversion": { - "major": 9, - "minor": 1, - "revision": 5, - "architecture": "x64", - "modernui": 1 - }, - "classnamespace": "box", - "rect": [ - 100.0, - 100.0, - 900.0, - 700.0 - ], - "bglocked": 0, - "openinpresentation": 0, - "default_fontsize": 13.0, - "default_fontface": 0, - "default_fontname": "Ableton Sans Light Regular", - "gridonopen": 1, - "gridsize": [ - 5.0, - 5.0 - ], - "gridsnaponopen": 2, - "objectsnaponopen": 0, - "statusbarvisible": 2, - "toolbarvisible": 1, - "boxanimatetime": 200, - "enablehscroll": 1, - "enablevscroll": 1, - "description": "", - "digest": "", - "tags": "", - "style": "", - "assistshowspatchername": 0, - "textcolor": [ - 0.847058823529412, - 0.847058823529412, - 0.847058823529412, - 1.0 - ], - "bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "editing_bgcolor": [ - 0.109803921568627, - 0.109803921568627, - 0.109803921568627, - 1.0 - ], - "boxes": [], - "lines": [], - "showontab": 1 - }, - "id": "obj-5" - } - } - ], - "lines": [], - "showrootpatcherontab": 0, - "showontab": 0 - } -} + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 100.0, 800.0, 680.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showrootpatcherontab": 0, + "showontab": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 100.0, 126.0, 800.0, 654.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "tap.python~" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "Process audio with a Python class", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 330.0, 69.0 ], + "text": "[tap.python~ name] loads python/name.py from this package and runs the class name in it as an audio object. With no argument it loads python/default.py: open it to follow along." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 170.0, 308.0, 100.0 ], + "text": "Its typed fields are attributes (gain), its public methods are messages called according to their signatures (greet, float, int, bang), and its process() method runs on the signal — here once per sample; the numpy tab has the form that runs once per vector." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 285.0, 260.0, 100.0 ], + "text": "Save the .py file and the object loads it again, keeping its attribute values, and the audio carries on with the new code. A mistake prints its traceback to the Max console, and the object outputs silence until a save fixes it." + } + }, + { + "box": { + "id": "obj-6", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 400.0, 304.0, 69.0 ], + "text": "@mode worker runs process() on a thread of its own, @latency milliseconds (30) behind the audio, so that a reload or a message never holds the audio up." + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 90.0, 74.0, 24.0 ], + "text": "saw~ 110" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 480.0, 90.0, 74.0, 24.0 ], + "text": "saw~ 221" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 125.0, 60.0, 24.0 ], + "text": "*~ 0.5" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 160.0, 92.39999999999999, 24.0 ], + "text": "greet max" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 500.4, 160.0, 92.39999999999999, 24.0 ], + "text": "float 0.5" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 600.8, 160.0, 62.0, 24.0 ], + "text": "int 2" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 670.8, 160.0, 107.6, 24.0 ], + "text": "filechanged" + } + }, + { + "box": { + "attr": "gain", + "id": "obj-14", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 195.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 235.0, 95.0, 24.0 ], + "text": "tap.python~" + } + }, + { + "box": { + "id": "obj-16", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 490.0, 235.0, 260.0, 38.0 ], + "text": "filechanged reloads at once; saving the file does it for you" + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "scope~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 490.0, 280.0, 150.0, 70.0 ] + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 280.0, 60.0, 24.0 ], + "text": "*~ 0.2" + } + }, + { + "box": { + "id": "obj-19", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 400.0, 315.0, 45.0, 45.0 ] + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "bang" ], + "patching_rect": [ 660.0, 280.0, 151.0, 24.0 ], + "text": "metro 250 @active 1" + } + }, + { + "box": { + "id": "obj-21", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "", "int" ], + "patching_rect": [ 660.0, 310.0, 102.0, 24.0 ], + "text": "adstatus cpu" + } + }, + { + "box": { + "id": "obj-22", + "maxclass": "number", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "bang" ], + "parameter_enable": 0, + "patching_rect": [ 660.0, 340.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-23", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 725.0, 340.0, 60.0, 22.0 ], + "text": "CPU %" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "order": 0, + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-18", 0 ], + "order": 1, + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-19", 1 ], + "order": 0, + "source": [ "obj-18", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-19", 0 ], + "order": 1, + "source": [ "obj-18", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-21", 0 ], + "source": [ "obj-20", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-22", 0 ], + "source": [ "obj-21", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 20.0, 20.0, 67.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p basic" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 654.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "Per vector, with numpy" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "One call per signal vector instead of one per sample", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 284.0, 69.0 ], + "text": "process(self, x: float) -> float is called once per sample: simplest to write, but every line of Python in it runs tens of thousands of times a second." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 170.0, 296.0, 100.0 ], + "text": "process(self, x: np.ndarray) -> np.ndarray is called once per signal vector, with the vector as a numpy array, and numpy then works on the whole of it at C speed: the form for anything with real work in it. numpy_gain.py is default.py's gain written that way." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 285.0, 330.0, 69.0 ], + "text": "Choose one with the message boxes and watch the CPU meter: the ReadMe's performance note has the measurements, per sample and per vector, at 48 and 96 kHz." + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 365.0, 330.0, 22.0 ], + "text": "Turn on audio with the speaker." + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 90.0, 74.0, 24.0 ], + "text": "saw~ 110" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 165.0, 151.0, 24.0 ], + "text": "tap.python~ default" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 570.0, 165.0, 172.0, 24.0 ], + "text": "tap.python~ numpy_gain" + } + }, + { + "box": { + "attr": "gain", + "id": "obj-10", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 130.0, 150.0, 24.0 ] + } + }, + { + "box": { + "attr": "gain", + "id": "obj-11", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 570.0, 130.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 210.0, 40.0, 24.0 ], + "text": "1" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 448.0, 210.0, 40.0, 24.0 ], + "text": "2" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 500.0, 210.0, 170.0, 22.0 ], + "text": "per sample, per vector" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 250.0, 109.0, 24.0 ], + "text": "selector~ 2 1" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 290.0, 60.0, 24.0 ], + "text": "*~ 0.2" + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 400.0, 325.0, 45.0, 45.0 ] + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "bang" ], + "patching_rect": [ 570.0, 290.0, 151.0, 24.0 ], + "text": "metro 250 @active 1" + } + }, + { + "box": { + "id": "obj-19", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "", "int" ], + "patching_rect": [ 570.0, 320.0, 102.0, 24.0 ], + "text": "adstatus cpu" + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "number", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ "", "bang" ], + "parameter_enable": 0, + "patching_rect": [ 570.0, 350.0, 60.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-21", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 635.0, 350.0, 60.0, 22.0 ], + "text": "CPU %" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-8", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 0 ], + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 1 ], + "order": 0, + "source": [ "obj-16", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "order": 1, + "source": [ "obj-16", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-19", 0 ], + "source": [ "obj-18", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-20", 0 ], + "source": [ "obj-19", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-8", 0 ], + "order": 1, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-9", 0 ], + "order": 0, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 1 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 2 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 120.0, 20.0, 67.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p numpy" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 654.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "A filter that knows the sample rate" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "prepare(sample_rate, vector_size)", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 270.0, 100.0 ], + "text": "allpass.py is a Schroeder allpass filter: it passes every frequency at the same level and shifts their phase, so mixed with the dry signal it notches the spectrum. Its delay is an attribute in milliseconds, which it turns into samples." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 205.0, 302.0, 100.0 ], + "text": "For that it needs the sample rate: an optional method prepare(self, sample_rate: float, vector_size: int) -> None is called before the object processes any audio, again whenever the rate or the vector size changes, and on every reload before the new code runs." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 325.0, 316.0, 69.0 ], + "text": "Its fields are attrs fields with validators: alpha must stay strictly between -1 and 1. Try alpha 1 — the validator's error prints to the console, and alpha keeps its value." + } + }, + { + "box": { + "id": "obj-6", + "linecount": 2, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 415.0, 332.0, 38.0 ], + "text": "numpy_allpass.py computes exactly the same, a vector at a time." + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 90.0, 60.0, 24.0 ], + "text": "noise~" + } + }, + { + "box": { + "attr": "delay", + "id": "obj-8", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 400.0, 125.0, 150.0, 24.0 ] + } + }, + { + "box": { + "attr": "alpha", + "id": "obj-9", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 560.0, 125.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 560.0, 160.0, 77.19999999999999, 24.0 ], + "text": "alpha 1" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 645.2, 160.0, 62.0, 24.0 ], + "text": "clear" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 195.0, 151.0, 24.0 ], + "text": "tap.python~ allpass" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 235.0, 40.0, 24.0 ], + "text": "+~" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 445.0, 235.0, 150.0, 22.0 ], + "text": "with the dry signal" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 275.0, 60.0, 24.0 ], + "text": "*~ 0.1" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 400.0, 310.0, 45.0, 45.0 ] + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-15", 0 ], + "source": [ "obj-13", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 1 ], + "order": 0, + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-16", 0 ], + "order": 1, + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "order": 1, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 1 ], + "order": 0, + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 220.0, 20.0, 81.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p allpass" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 654.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [ + { + "box": { + "fontname": "Ableton Sans Bold Regular", + "fontsize": 26.0, + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 15.0, 600.0, 38.0 ], + "text": "Many channels" + } + }, + { + "box": { + "fontsize": 15.0, + "id": "obj-2", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 55.0, 600.0, 24.0 ], + "text": "mc., and a class with several inputs", + "textcolor": [ 0.976470588235294, 0.733333333333333, 0.258823529411765, 1.0 ] + } + }, + { + "box": { + "id": "obj-3", + "linecount": 9, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 90.0, 284.0, 147.0 ], + "text": "Wrap the object in mc. to run one instance per channel of a multichannel signal: [mc.tap.python~ numpy_gain] here, over two channels. The class's attributes and messages are each instance's own, so the MC wrapper passes them on through its own messages: setvalue, an instance's number and the message, for one; applyvalues, the name and a value for each, for all." + } + }, + { + "box": { + "id": "obj-4", + "linecount": 6, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 255.0, 294.0, 100.0 ], + "text": "Or write one class with several channels: process()'s parameters are the object's signal inlets and its return hint its outlets. stereo_width.py takes left and right, returns tuple[np.ndarray, np.ndarray], and gets two of each." + } + }, + { + "box": { + "id": "obj-5", + "linecount": 4, + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 20.0, 370.0, 284.0, 69.0 ], + "text": "A save that changes process()'s inputs or outputs changes the object's inlets and outlets to match, keeping the patch cords of those that stay." + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 90.0, 74.0, 24.0 ], + "text": "saw~ 110" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 480.0, 90.0, 74.0, 24.0 ], + "text": "saw~ 165" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "multichannelsignal" ], + "patching_rect": [ 400.0, 125.0, 88.0, 24.0 ], + "text": "mc.pack~ 2" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 400.0, 160.0, 214.0, 24.0 ], + "text": "applyvalues gain 0.5 0.25" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "message", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "" ], + "patching_rect": [ 622.0, 160.0, 168.4, 24.0 ], + "text": "setvalue 2 gain 0.1" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "multichannelsignal" ], + "patching_rect": [ 400.0, 195.0, 193.0, 24.0 ], + "text": "mc.tap.python~ numpy_gain" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "multichannelsignal" ], + "patching_rect": [ 400.0, 230.0, 81.0, 24.0 ], + "text": "mc.*~ 0.2" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ 400.0, 265.0, 95.0, 24.0 ], + "text": "mc.dac~ 1 2" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 330.0, 74.0, 24.0 ], + "text": "saw~ 110" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 480.0, 330.0, 88.0, 24.0 ], + "text": "saw~ 110.5" + } + }, + { + "box": { + "attr": "width", + "id": "obj-16", + "maxclass": "attrui", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ "" ], + "parameter_enable": 0, + "patching_rect": [ 570.0, 330.0, 150.0, 24.0 ] + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ "signal", "signal" ], + "patching_rect": [ 400.0, 370.0, 186.0, 24.0 ], + "text": "tap.python~ stereo_width" + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 400.0, 405.0, 60.0, 24.0 ], + "text": "*~ 0.2" + } + }, + { + "box": { + "id": "obj-19", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ "signal" ], + "patching_rect": [ 480.0, 405.0, 60.0, 24.0 ], + "text": "*~ 0.2" + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ 400.0, 440.0, 74.0, 24.0 ], + "text": "dac~ 1 2" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ "obj-11", 0 ], + "source": [ "obj-10", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-12", 0 ], + "source": [ "obj-11", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-13", 0 ], + "source": [ "obj-12", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "source": [ "obj-14", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 1 ], + "source": [ "obj-15", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-17", 0 ], + "source": [ "obj-16", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-18", 0 ], + "source": [ "obj-17", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-19", 0 ], + "source": [ "obj-17", 1 ] + } + }, + { + "patchline": { + "destination": [ "obj-20", 0 ], + "source": [ "obj-18", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-20", 1 ], + "source": [ "obj-19", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-8", 0 ], + "source": [ "obj-6", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-8", 1 ], + "source": [ "obj-7", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-11", 0 ], + "source": [ "obj-8", 0 ] + } + }, + { + "patchline": { + "destination": [ "obj-11", 0 ], + "source": [ "obj-9", 0 ] + } + } + ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 320.0, 20.0, 46.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p mc" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 0, + "patcher": { + "fileversion": 1, + "appversion": { + "major": 9, + "minor": 1, + "revision": 5, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ 0.0, 26.0, 800.0, 654.0 ], + "default_fontsize": 13.0, + "default_fontname": "Ableton Sans Light Regular", + "gridsize": [ 5.0, 5.0 ], + "gridsnaponopen": 2, + "objectsnaponopen": 0, + "showontab": 1, + "boxes": [], + "lines": [], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + }, + "patching_rect": [ 420.0, 20.0, 40.0, 24.0 ], + "saved_object_attributes": { + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "fontname": "Ableton Sans Light Regular", + "fontsize": 13.0, + "locked_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ] + }, + "text": "p ?" + } + } + ], + "lines": [], + "autosave": 0, + "textcolor": [ 0.847058823529412, 0.847058823529412, 0.847058823529412, 1.0 ], + "bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ], + "editing_bgcolor": [ 0.109803921568627, 0.109803921568627, 0.109803921568627, 1.0 ] + } +} \ No newline at end of file From 1d2587657a0f931321527b672612e56357beb726 Mon Sep 17 00:00:00 2001 From: Timothy Place Date: Sat, 10 Oct 2026 11:56:23 -0500 Subject: [PATCH 2/4] The patchers' titles bold by face, not by a named bold font On Windows Max did not resolve "Ableton Sans Bold Regular" by name and fell back to a Lucida Sans Bold the system does not have ("typeface name Lucida Sans with style Bold not found!", found opening the help files in the Windows VM). The titles are now the default font with fontface 1, as the original help's title was. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz --- docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat | 2 +- .../tutorials/pythontap-tut/pythontap_02_filter.maxpat | 2 +- .../pythontap-tut/pythontap_03_control.maxpat | 2 +- extras/PythonTap Overview.maxpat | 8 ++++---- help/tap.python.maxhelp | 10 +++++----- help/tap.python~.maxhelp | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat b/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat index b96168f..1e56ff9 100644 --- a/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat +++ b/docs/tutorials/pythontap-tut/pythontap_01_gain.maxpat @@ -18,7 +18,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", diff --git a/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat b/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat index 2dc4d58..39aeefd 100644 --- a/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat +++ b/docs/tutorials/pythontap-tut/pythontap_02_filter.maxpat @@ -18,7 +18,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", diff --git a/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat b/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat index 576f27b..392a46a 100644 --- a/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat +++ b/docs/tutorials/pythontap-tut/pythontap_03_control.maxpat @@ -18,7 +18,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", diff --git a/extras/PythonTap Overview.maxpat b/extras/PythonTap Overview.maxpat index 63ebc64..5dbe3c6 100644 --- a/extras/PythonTap Overview.maxpat +++ b/extras/PythonTap Overview.maxpat @@ -18,7 +18,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -53,7 +53,7 @@ }, { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "id": "obj-4", "maxclass": "comment", "numinlets": 1, @@ -129,7 +129,7 @@ }, { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "id": "obj-11", "linecount": 2, "maxclass": "comment", @@ -207,7 +207,7 @@ }, { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "id": "obj-18", "maxclass": "comment", "numinlets": 1, diff --git a/help/tap.python.maxhelp b/help/tap.python.maxhelp index 0a02d97..d879391 100644 --- a/help/tap.python.maxhelp +++ b/help/tap.python.maxhelp @@ -44,7 +44,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -371,7 +371,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -594,7 +594,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -854,7 +854,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -1138,7 +1138,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", diff --git a/help/tap.python~.maxhelp b/help/tap.python~.maxhelp index a9de6f3..ad0c637 100644 --- a/help/tap.python~.maxhelp +++ b/help/tap.python~.maxhelp @@ -44,7 +44,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -425,7 +425,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -779,7 +779,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", @@ -1062,7 +1062,7 @@ "boxes": [ { "box": { - "fontname": "Ableton Sans Bold Regular", + "fontface": 1, "fontsize": 26.0, "id": "obj-1", "maxclass": "comment", From 2691be0b6b69a0382d3e6fc280fa2c35d4e657ff Mon Sep 17 00:00:00 2001 From: Timothy Place Date: Sat, 10 Oct 2026 12:17:22 -0500 Subject: [PATCH 3/4] CHANGELOG: 2.0.0, dated, with what the release is and how it was verified (9.6) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz --- CHANGELOG.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 238fa6c..e88f61c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,15 @@ breaking changes to the contract were allowed where they bought correctness (D5 `docs/PRODUCTION-PLAN.md`); each is recorded here. From 1.0.0, a change to the class contract is a major version. -## 2.0.0 — unreleased +## 2.0.0 — 2026-10-10 -The release that brings `tap.python`, a Python class as a Max object without audio -(`docs/TAP-PYTHON-PLAN.md`, Phase 9 of the production plan). Its entries are added as the phase -lands. +The release that brings `tap.python`, a Python class as a Max object without audio, beside +`tap.python~` in the same package and the same binary (`docs/TAP-PYTHON-PLAN.md`, Phase 9 of the +production plan). It is a major version because of one change to the class contract — a message's +last parameter hinted `list[…]` or `np.ndarray` now takes the remaining atoms (Changed, below); +classes that do not use such a hint load and behave as they did. Verified in Max 9.1.5 on macOS — +every runtime test, `tap.python`'s included, and the hour-long soak — and on Windows 11, where both +objects, their attributes and messages, a reload and the help files were checked in Max by hand. ### Added — `tap.python`, a Python class as a Max object without audio @@ -27,7 +31,6 @@ lands. Audio Interrupt on that is the audio thread, which the object says once per session. - **`default.py` has a `bang`**, which returns the gain: `[tap.python]` with no argument outputs it. In `tap.python~` a `bang` now calls that method, its result dropped there as every method's is. - - **Documentation in Max's own system** (plan 9.4): a reference page for `tap.python`, a guide — *Writing Max Objects in Python* — and three tutorials with their patchers in the Documentation window (Package Docs › PythonTap), the help patchers of both objects in tabs, and a *PythonTap From 85fc0d8d74ebd3b14a3ed5900c83c2045de4458f Mon Sep 17 00:00:00 2001 From: Timothy Place Date: Sat, 10 Oct 2026 12:17:39 -0500 Subject: [PATCH 4/4] =?UTF-8?q?The=20plan:=209.6=20done=20(#51)=20?= =?UTF-8?q?=E2=80=94=20what=20the=20release=20session=20checked,=20and=20t?= =?UTF-8?q?he=20tables=20left=20for=20later?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_019rVV9SkjkWmiBXFMT4whkz --- docs/PRODUCTION-PLAN.md | 2 +- docs/TAP-PYTHON-PLAN.md | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/PRODUCTION-PLAN.md b/docs/PRODUCTION-PLAN.md index 4c1f55c..ef48215 100644 --- a/docs/PRODUCTION-PLAN.md +++ b/docs/PRODUCTION-PLAN.md @@ -830,7 +830,7 @@ row shipped what only a host platform could show. checks for the hand-made XML and JSON. - [x] **9.5 Runtime tests** (#50)**:** the `tap.python.*` patchers in `make_patchers.py`; `run.py` aware of the second object; the soak session gains a `metro`-driven `tap.python` under saves. -- [ ] **9.6 The release session, Mac and Windows:** the whole suite on the Mac, the help patcher +- [x] **9.6 The release session, Mac and Windows** (#51)**:** the whole suite on the Mac, the help patcher checked and re-saved, Max's page for `tap.python~` committed, the hand checks; the package by hand on Windows; then tag `v2.0.0`. - [ ] **9.7 The book:** after 2.0.0, the family's mdBook under `book/`, published by CI, with the diff --git a/docs/TAP-PYTHON-PLAN.md b/docs/TAP-PYTHON-PLAN.md index 529f523..4499c76 100644 --- a/docs/TAP-PYTHON-PLAN.md +++ b/docs/TAP-PYTHON-PLAN.md @@ -8,7 +8,7 @@ change — and the plan to build it (Phase 9 of the production plan, which point Drafted 2026-10-02 against 1.0.0 and audited the same day (`AUDIT-TAP-PYTHON-PLAN.md`: two blockers, six major findings, nine minor; its addendum of 2026-10-09 records what 1.0.1 and 1.0.2 changed). **Revised 2026-10-09 against 1.0.2** for every finding; the [revision record](#revision-record) -at the end says what each changed. 9.0 to 9.5 are built — the spike ran in Max on a Mac +at the end says what each changed. 9.0 to 9.6 are done, and 2.0.0 released — the spike ran in Max on a Mac and on Windows: its answers are under [9.0](#what-90-found), and the design below follows them. Tick the items below (with the PR) as they land, and keep the design current where a PR decides differently. @@ -371,7 +371,7 @@ third was Windows-only. examples on known inputs. A `core/bench` row for a message call with a list of 64 atoms, written by `scripts/update-perf-docs.py` with the others, so the ReadMe's performance sentence is measured. *(9.1: the row and the script's sentence are in; the ReadMe's table is regenerated on - the next measurement on an idle machine, 9.6 at the latest — on 2026-10-09, with macOS's indexing + the next measurement on an idle machine — not in 9.6 after all, whose Mac was busy: after 2.0.0 — on 2026-10-09, with macOS's indexing running, a message with 64 numbers in and out measured 5.6 µs for the bridge alone and 15 µs for `scale.py`, and `main` and the branch measured alike back to back.)* No Max code changes; `tap.python~`'s battery and glue test unchanged and green; the audio bench numbers unchanged (the audio path does not touch the new code). @@ -474,12 +474,21 @@ third was Windows-only. passed all 18 of its checks, the `tap.python` answering every message of a 10 ms metro correctly for 60 minutes of saves: Max's memory 658 MB a minute in, 663 MB at the end (peak 675), 3601 executions of the file, Python's object count between 18,700 and 22,000 throughout.)* -- [ ] **9.6 The release session, Mac and Windows.** Build, run the whole runtime suite on the Mac, +- [x] **9.6 The release session, Mac and Windows** (#51). Build, run the whole runtime suite on the Mac, check the help patcher and re-save it, commit the page Max writes for `tap.python~`, the hand checks the tests cannot make (`get` through the dumpout in a patcher, attrui on a `tap.python`, a `tap.python~` and a `tap.python` on one file saved while audio runs); on Windows, the package by hand: both objects load through the mapping, attributes and messages - work, a reload keeps them. Then tag `v2.0.0`. + work, a reload keeps them. Then tag `v2.0.0`. *(2026-10-10, Max 9.1.5. The Mac: every runtime + test (21), the help files, the tutorials' patchers and the Overview saved by Max — the same boxes + and cords — and the hand checks: an `attrui` on a `tap.python` lists, reads and sets its class's + attributes, `get` comes from the dumpout; one file for both kinds saved while audio runs is + `tap.python.shared`'s. Windows 11: the glue test and `check-docs.py`, and in Max both objects and + `mc.tap.python~` through `init/`, attributes and messages, a reload keeping their values, the help + files open with their tabs and the see-also. The ReadMe's performance tables are not regenerated: + the Mac was not idle (media analysis on a core, load average 4; the same code measured 25–50% + slower), so Sep 30's stay, by the maintainer's decision, and the message sentence 9.1 measured + joins them when the Mac is next idle, after the tag. v2.0.0 is tagged on #51's merge.)* - [ ] **9.7 The book.** After 2.0.0, the family's shape: an mdBook under `book/` (TapHouse's icon rule already knows `book/book.toml` and guards `book/theme/favicon.*`), built and published by CI. Chapters from the ReadMe's sections — install, writing a class, audio, worker mode, control