diff --git a/docs/gen_operator_comparison.md b/docs/gen_operator_comparison.md new file mode 100644 index 0000000..f858814 --- /dev/null +++ b/docs/gen_operator_comparison.md @@ -0,0 +1,265 @@ +# Gen Operator Comparison: Local vs. Cycling '74 Online Docs + +**Local operators:** 240 +**Online operators:** 240 +**In both:** 231 +**Local only:** 9 +**Online only:** 9 + +## Operators Found Only in Local Installation + +- `&&` +- `<` +- `<=` +- `<=p` +- `` +- `>=` +- `>=p` +- `>p` + +## Operators Found Only in Online Docs + +- `&&` +- `>` +- `>=` +- `>=p` +- `>p` +- `<` +- `<=` +- `<=p` +- `<p` + +## Operators Found in Both Sources + +- `!` +- `!%` +- `!-` +- `!/` +- `!=` +- `!=p` +- `%` +- `*` +- `*=` +- `+` +- `+=` +- `-` +- `/` +- `==` +- `==p` +- `?` +- `DEGTORAD` +- `E` +- `FFTFULLSPECT` +- `FFTHOP` +- `FFTOFFSET` +- `FFTSIZE` +- `HALFPI` +- `INVPI` +- `LN10` +- `LN2` +- `LOG10E` +- `LOG2E` +- `PHI` +- `PI` +- `Param` +- `RADTODEG` +- `SAMPLERATE` +- `SQRT1_2` +- `SQRT2` +- `TWOPI` +- `VECTORSIZE` +- `^^` +- `abs` +- `absdiff` +- `accum` +- `acos` +- `acosh` +- `add` +- `and` +- `asin` +- `asinh` +- `atan` +- `atan2` +- `atanh` +- `atodb` +- `bool` +- `buffer` +- `cartopol` +- `ceil` +- `cell` +- `change` +- `channels` +- `circle` +- `clamp` +- `clip` +- `concat` +- `cone` +- `constant` +- `cos` +- `cosh` +- `counter` +- `cross` +- `cycle` +- `cylinder` +- `data` +- `dbtoa` +- `dcblock` +- `degrees` +- `degtorad` +- `delay` +- `delta` +- `dim` +- `div` +- `dot` +- `e` +- `elapsed` +- `eq` +- `eqp` +- `exp` +- `exp2` +- `expr` +- `f` +- `faceforward` +- `fastcos` +- `fastexp` +- `fastpow` +- `fastsin` +- `fasttan` +- `fftfullspect` +- `ffthop` +- `fftinfo` +- `fftoffset` +- `fftsize` +- `fixdenorm` +- `fixnan` +- `float` +- `floor` +- `fold` +- `fract` +- `ftom` +- `gate` +- `gen` +- `gt` +- `gte` +- `gtep` +- `gtp` +- `halfpi` +- `history` +- `hsl2rgb` +- `hypot` +- `i` +- `in` +- `int` +- `interp` +- `invpi` +- `isdenorm` +- `isnan` +- `latch` +- `length` +- `ln` +- `ln10` +- `ln2` +- `log` +- `log10` +- `log10e` +- `log2` +- `log2e` +- `lookup` +- `lt` +- `lte` +- `ltep` +- `ltp` +- `max` +- `maximum` +- `mc_channel` +- `mc_channelcount` +- `min` +- `minimum` +- `mix` +- `mod` +- `mstosamps` +- `mtof` +- `mul` +- `mulequals` +- `nearest` +- `nearestpix` +- `neg` +- `neq` +- `neqp` +- `noise` +- `norm` +- `normalize` +- `not` +- `or` +- `out` +- `param` +- `pass` +- `peek` +- `phasewrap` +- `phasor` +- `phi` +- `pi` +- `plane` +- `plusequals` +- `poke` +- `poltocar` +- `pow` +- `qconj` +- `qmul` +- `qrot` +- `r` +- `radians` +- `radtodeg` +- `rate` +- `rdiv` +- `receive` +- `reflect` +- `refract` +- `rgb2hsl` +- `rmod` +- `rotor` +- `round` +- `rsub` +- `s` +- `sah` +- `sample` +- `samplepix` +- `samplerate` +- `sampstoms` +- `scale` +- `selector` +- `send` +- `setparam` +- `sign` +- `sin` +- `sinh` +- `slide` +- `smoothstep` +- `snorm` +- `sphere` +- `splat` +- `sqrt` +- `sqrt1_2` +- `sqrt2` +- `step` +- `sub` +- `switch` +- `swiz` +- `t60` +- `t60time` +- `tan` +- `tanh` +- `torus` +- `train` +- `triangle` +- `trunc` +- `twopi` +- `vec` +- `vectorsize` +- `voice` +- `voicecount` +- `wave` +- `wrap` +- `xor` +- `||` diff --git a/examples/gen-bounded-ramp/gen_bounded_ramp.maxpat b/examples/gen-bounded-ramp/gen_bounded_ramp.maxpat new file mode 100644 index 0000000..a25fee6 --- /dev/null +++ b/examples/gen-bounded-ramp/gen_bounded_ramp.maxpat @@ -0,0 +1,349 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === GEN~ RAMP GENERATOR ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 140.0, + 50, + 60.0, + 22.0 + ], + "text": "param rate 0.001" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 240.0, + 130, + 18.0, + 22.0 + ], + "text": "+" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 240.0, + 210, + 60.0, + 22.0 + ], + "text": "wrap 0 1" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 390.0, + 130, + 60.0, + 22.0 + ], + "text": "history" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 240.0, + 300, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-2", + 0 + ], + "source": [ + "obj-1", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-3", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-2", + 1 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 60, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === VISUALIZER ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "scope~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 160, + 130.0, + 130.0 + ], + "text": "scope~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-bounded-ramp/main.py b/examples/gen-bounded-ramp/main.py new file mode 100644 index 0000000..4eced8a --- /dev/null +++ b/examples/gen-bounded-ramp/main.py @@ -0,0 +1,98 @@ +""" +Gen~ Bounded Ramp Example +========================== +A manual phasor implemented using history + wrap feedback. Each sample, +a small rate value is added to the previous ramp position, and wrap +keeps the output in the [0, 1) range — creating a continuously cycling +sawtooth waveform. + +This is the "manual phasor" pattern, useful for understanding how +gen~'s built-in phasor actually works under the hood. + +Signal chain (gen~ interior): + param rate 0.001 ──→ + ──→ wrap 0 1 ──→ out 1 + ↑ │ + history ←─────┘ (feedback: wraps back into adder) + +Signal chain (outer patch): + gen~ → scope~ + +Usage: + python main.py + → Generates gen_bounded_ramp.maxpat + → Open in Max/MSP; scope~ will show a sawtooth wave cycling at ~44 Hz + (rate 0.001 at 44100 Hz sr = 0.001 * 44100 ≈ 44 cycles/sec) + → Change param rate to adjust the ramp speed (0.0001 for very slow) +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: manual phasor via history + wrap +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# param rate sets how much to advance the ramp each sample +# 0.001 at 44100 Hz sr produces ~44 Hz cycling +gen_patch.set_position(60, 50) +rate_param = gen_patch.place("param rate 0.001", verbose=False)[0] + +# + adds the rate increment to the previous ramp position +gen_patch.set_position(160, 130) +adder = gen_patch.place("+", verbose=False)[0] + +# wrap 0 1 folds the output back into [0, 1) when it reaches or exceeds 1 +gen_patch.set_position(160, 210) +wr = gen_patch.place("wrap 0 1", verbose=False)[0] + +# history stores the wrapped ramp position from the previous sample +gen_patch.set_position(310, 130) +hist = gen_patch.place("history", verbose=False)[0] + +# out 1 sends the current ramp position (0.0 to just below 1.0) out +gen_patch.set_position(160, 300) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire the bounded ramp loop: +# param rate → left inlet of + (advance by this amount each sample) +# history → right inlet of + (previous ramp position) +# + → wrap 0 1 (keep in [0, 1) range) +# wrap → history (store for next sample — feedback) +# wrap → out 1 (output the ramp value) +gen_patch.connect( + [rate_param.outs[0], adder.ins[0]], # rate increment → adder left + [hist.outs[0], adder.ins[1]], # previous position → adder right + [adder.outs[0], wr.ins[0]], # sum → wrap (boundary check) + [wr.outs[0], hist.ins[0]], # wrapped value → history (feedback) + [wr.outs[0], gen_out.ins[0]], # wrapped value → output + verbose=False, +) + +# ===================================================================== +# OUTER PATCH +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === GEN~ RAMP GENERATOR === +patch.set_position(30, 30) +patch.place("comment === GEN~ RAMP GENERATOR ===", verbose=False)[0] + +patch.set_position(30, 60) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === VISUALIZER === +patch.set_position(30, 130) +patch.place("comment === VISUALIZER ===", verbose=False)[0] + +patch.set_position(30, 160) +# scope~ shows the repeating sawtooth ramp waveform +scope = patch.place("scope~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [gen_obj.outs[0], scope.ins[0]], # ramp signal → oscilloscope + verbose=False, +) + +# === SAVE === +patch.save("gen_bounded_ramp.maxpat") diff --git a/examples/gen-echo-delay/gen_echo_delay.maxpat b/examples/gen-echo-delay/gen_echo_delay.maxpat new file mode 100644 index 0000000..d80d20e --- /dev/null +++ b/examples/gen-echo-delay/gen_echo_delay.maxpat @@ -0,0 +1,571 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === SIGNAL SOURCE ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 60, + 43.0, + 22.0 + ], + "text": "cycle~ 440" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GAIN TRIM ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 160, + 20.0, + 22.0 + ], + "text": "*~ 0.3" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === GEN~ ECHO ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- INPUTS AND PARAMS ---" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 80, + 60.0, + 22.0 + ], + "text": "in 1" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 80, + 60.0, + 22.0 + ], + "text": "param delaytime 10000" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 160.0, + 60.0, + 22.0 + ], + "text": "param feedback 0.5" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 180, + 150.0, + 20.0 + ], + "text": "comment --- FEEDBACK LOOP ---" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 210, + 18.0, + 22.0 + ], + "text": "+" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 290, + 60.0, + 22.0 + ], + "text": "delay 44100" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 370, + 18.0, + 22.0 + ], + "text": "*" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 460, + 150.0, + 20.0 + ], + "text": "comment --- OUTPUT ---" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 490, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-7", + 1 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-7", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-10", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-7", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 1 + ], + "source": [ + "obj-8", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 260, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 330, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 360, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-echo-delay/main.py b/examples/gen-echo-delay/main.py new file mode 100644 index 0000000..bf148fe --- /dev/null +++ b/examples/gen-echo-delay/main.py @@ -0,0 +1,150 @@ +""" +Gen~ Echo Delay Example +========================= +A feedback echo effect built inside gen~. The input signal is summed +with a delayed, attenuated copy of itself. The delay buffer holds up +to one second of audio; delaytime and feedback are exposed as params +so they can be adjusted from the outer patch without recompiling. + +Delay formula (per sample): + summed = in[n] + delayed[n] * feedback + delay ← summed (write new sample) + out[n] = summed + +Signal chain (gen~ interior): + param feedback 0.5 ──────────────────────────┐ + ▼ + in 1 ──► + (summed) ──► delay 44100 ──► * (feedback) ──► (back to +) + │ ▲ + │ └── param delaytime 10000 + ▼ + out 1 + +Signal chain (outer patch): + cycle~ 440 → *~ 0.3 → gen~ → ezdac~ + +Usage: + python main.py + → Generates gen_echo_delay.maxpat + → Open in Max/MSP and click the ezdac~ to hear a repeating echo + → Adjust delaytime param to change echo spacing + → Adjust feedback param (keep < 1.0) to change echo decay +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: feedback echo delay +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# --- INPUTS AND PARAMS --- +gen_patch.set_position(80, 50) +gen_patch.place("comment --- INPUTS AND PARAMS ---", verbose=False)[0] + +gen_patch.set_position(80, 80) +gen_in = gen_patch.place("in 1", verbose=False)[0] # audio inlet + +# delaytime in samples (~227 ms at 44100 Hz) +gen_patch.set_position(300, 80) +delaytime_param = gen_patch.place("param delaytime 10000", verbose=False)[0] + +# feedback coefficient: how much of the delayed signal recirculates +gen_patch.set_position(500, 80) +feedback_param = gen_patch.place("param feedback 0.5", verbose=False)[0] + +# --- FEEDBACK LOOP --- +gen_patch.set_position(80, 180) +gen_patch.place("comment --- FEEDBACK LOOP ---", verbose=False)[0] + +# Summing junction: input + feedback signal +gen_patch.set_position(80, 210) +add = gen_patch.place("+", verbose=False)[0] + +# Delay line: 44100-sample buffer (1 second max at 44100 Hz) +gen_patch.set_position(80, 290) +dly = gen_patch.place("delay 44100", verbose=False)[0] + +# Attenuate the delayed signal before feeding back +gen_patch.set_position(80, 370) +mul = gen_patch.place("*", verbose=False)[0] + +# --- OUTPUT --- +gen_patch.set_position(80, 460) +gen_patch.place("comment --- OUTPUT ---", verbose=False)[0] + +gen_patch.set_position(80, 490) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire summing junction: in + feedback +gen_patch.connect( + [gen_in.outs[0], add.ins[0]], # audio input → add left inlet + [mul.outs[0], add.ins[1]], # attenuated delayed signal → add right inlet + verbose=False, +) + +# Wire delay: summed signal in, delaytime sets the read position +gen_patch.connect( + [add.outs[0], dly.ins[0]], # summed → delay write inlet + [delaytime_param.outs[0], dly.ins[1]], # delaytime → delay tap position + verbose=False, +) + +# Wire feedback attenuation: delay output * feedback coefficient +gen_patch.connect( + [dly.outs[0], mul.ins[0]], # delayed signal → multiply left inlet + [feedback_param.outs[0], mul.ins[1]], # feedback coeff → multiply right inlet + verbose=False, +) + +# Send summed signal (wet+dry) to output +gen_patch.connect( + [add.outs[0], gen_out.ins[0]], # summed signal → gen outlet + verbose=False, +) + +# ===================================================================== +# OUTER PATCH: apply echo to a test tone +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === SIGNAL SOURCE === +patch.set_position(30, 30) +patch.place("comment === SIGNAL SOURCE ===", verbose=False)[0] + +patch.set_position(30, 60) +osc = patch.place("cycle~ 440", verbose=False)[0] # 440 Hz test tone + +# === GAIN TRIM === +patch.set_position(30, 130) +patch.place("comment === GAIN TRIM ===", verbose=False)[0] + +patch.set_position(30, 160) +# Trim before the delay so the buffer doesn't clip +trim = patch.place("*~ 0.3", verbose=False)[0] + +# === GEN~ ECHO === +patch.set_position(30, 230) +patch.place("comment === GEN~ ECHO ===", verbose=False)[0] + +patch.set_position(30, 260) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === OUTPUT === +patch.set_position(30, 330) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 360) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [osc.outs[0], trim.ins[0]], # oscillator → gain trim + [trim.outs[0], gen_obj.ins[0]], # trimmed signal → gen~ inlet + [gen_obj.outs[0], dac.ins[0]], # echo output → left speaker + [gen_obj.outs[0], dac.ins[1]], # echo output → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_echo_delay.maxpat") diff --git a/examples/gen-fm-synthesis/gen_fm_synthesis.maxpat b/examples/gen-fm-synthesis/gen_fm_synthesis.maxpat new file mode 100644 index 0000000..00cfb35 --- /dev/null +++ b/examples/gen-fm-synthesis/gen_fm_synthesis.maxpat @@ -0,0 +1,622 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === GEN~ FM SYNTHESIZER ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- PARAMETERS ---" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 80, + 60.0, + 22.0 + ], + "text": "param carrier_freq 440" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 80, + 60.0, + 22.0 + ], + "text": "param mod_freq 220" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 160.0, + 60.0, + 22.0 + ], + "text": "param mod_depth 200" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 380.0, + 180, + 150.0, + 20.0 + ], + "text": "comment --- MODULATOR OSCILLATOR ---" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 210, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 280, + 60.0, + 22.0 + ], + "text": "cycle" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 380.0, + 350, + 18.0, + 22.0 + ], + "text": "*" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 430, + 150.0, + 20.0 + ], + "text": "comment --- CARRIER OSCILLATOR ---" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 460, + 18.0, + 22.0 + ], + "text": "+" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 530, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 600, + 60.0, + 22.0 + ], + "text": "cycle" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 680, + 150.0, + 20.0 + ], + "text": "comment --- OUTPUT ---" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 710, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-10", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-7", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-7", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-10", + 1 + ], + "source": [ + "obj-8", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-11", + 0 + ], + "source": [ + "obj-10", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-12", + 0 + ], + "source": [ + "obj-11", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-14", + 0 + ], + "source": [ + "obj-12", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 60, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GAIN CONTROL ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 160, + 20.0, + 22.0 + ], + "text": "*~ 0.3" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 260, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 1 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-fm-synthesis/main.py b/examples/gen-fm-synthesis/main.py new file mode 100644 index 0000000..0cba4d5 --- /dev/null +++ b/examples/gen-fm-synthesis/main.py @@ -0,0 +1,152 @@ +""" +Gen~ FM Synthesis Example +========================== +Two-operator frequency modulation (FM) synthesis built inside gen~. +A modulator oscillator varies the instantaneous frequency of a carrier +oscillator, producing sidebands and timbral richness from just three +parameters: carrier frequency, modulator frequency, and modulation depth. + +FM formula: + modulator = sin(2π * mod_freq * t) + inst_freq = carrier_freq + modulator * mod_depth + output = sin(2π * inst_freq * t) (via phasor + cycle) + +Signal chain (gen~ interior): + param mod_freq 220 → phasor → cycle (modulator sine) + │ + * mod_depth (scale modulation) + │ + param carrier_freq 440 ──────► + (instantaneous frequency) + │ + phasor (carrier ramp at inst_freq) + │ + cycle (carrier sine) + │ + out 1 + +Signal chain (outer patch): + gen~ → *~ 0.3 → ezdac~ + +Usage: + python main.py + → Generates gen_fm_synthesis.maxpat + → Open in Max/MSP and click the ezdac~ to hear FM synthesis + → Adjust carrier_freq, mod_freq, and mod_depth params to explore timbres + → Integer ratios of mod_freq/carrier_freq produce harmonic spectra + → Non-integer ratios produce inharmonic, bell-like sounds +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: two-operator FM synthesizer +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# --- PARAMETERS --- +gen_patch.set_position(80, 50) +gen_patch.place("comment --- PARAMETERS ---", verbose=False)[0] + +gen_patch.set_position(80, 80) +carrier_freq = gen_patch.place("param carrier_freq 440", verbose=False)[0] + +gen_patch.set_position(300, 80) +mod_freq = gen_patch.place("param mod_freq 220", verbose=False)[0] + +gen_patch.set_position(520, 80) +mod_depth = gen_patch.place("param mod_depth 200", verbose=False)[0] + +# --- MODULATOR OSCILLATOR --- +gen_patch.set_position(300, 180) +gen_patch.place("comment --- MODULATOR OSCILLATOR ---", verbose=False)[0] + +# phasor1 generates the modulator ramp at mod_freq +gen_patch.set_position(300, 210) +ph1 = gen_patch.place("phasor", verbose=False)[0] + +# cycle1 converts the ramp to a sine wave (the modulator) +gen_patch.set_position(300, 280) +cyc1 = gen_patch.place("cycle", verbose=False)[0] + +# Scale modulator sine by mod_depth to get Hz deviation +gen_patch.set_position(300, 350) +mul = gen_patch.place("*", verbose=False)[0] + +# --- CARRIER OSCILLATOR --- +gen_patch.set_position(80, 430) +gen_patch.place("comment --- CARRIER OSCILLATOR ---", verbose=False)[0] + +# Add modulation to carrier frequency to get instantaneous frequency +gen_patch.set_position(80, 460) +add = gen_patch.place("+", verbose=False)[0] + +# phasor2 tracks the instantaneous (modulated) frequency +gen_patch.set_position(80, 530) +ph2 = gen_patch.place("phasor", verbose=False)[0] + +# cycle2 converts the carrier ramp to the output sine wave +gen_patch.set_position(80, 600) +cyc2 = gen_patch.place("cycle", verbose=False)[0] + +# --- OUTPUT --- +gen_patch.set_position(80, 680) +gen_patch.place("comment --- OUTPUT ---", verbose=False)[0] + +gen_patch.set_position(80, 710) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire modulator: mod_freq → phasor1 → cycle1 → * mod_depth +gen_patch.connect( + [mod_freq.outs[0], ph1.ins[0]], # mod frequency → phasor1 + [ph1.outs[0], cyc1.ins[0]], # phasor1 ramp → cycle1 phase + [cyc1.outs[0], mul.ins[0]], # modulator sine → multiply left + [mod_depth.outs[0], mul.ins[1]], # mod depth (Hz) → multiply right + verbose=False, +) + +# Wire carrier: (carrier_freq + modulation) → phasor2 → cycle2 → out +gen_patch.connect( + [carrier_freq.outs[0], add.ins[0]], # carrier base freq → add left + [mul.outs[0], add.ins[1]], # Hz deviation → add right + [add.outs[0], ph2.ins[0]], # instantaneous freq → phasor2 + [ph2.outs[0], cyc2.ins[0]], # carrier ramp → cycle2 phase + [cyc2.outs[0], gen_out.ins[0]], # carrier sine → gen outlet + verbose=False, +) + +# ===================================================================== +# OUTER PATCH +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === GEN~ FM SYNTHESIZER === +patch.set_position(30, 30) +patch.place("comment === GEN~ FM SYNTHESIZER ===", verbose=False)[0] + +patch.set_position(30, 60) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === GAIN CONTROL === +patch.set_position(30, 130) +patch.place("comment === GAIN CONTROL ===", verbose=False)[0] + +patch.set_position(30, 160) +gain = patch.place("*~ 0.3", verbose=False)[0] # attenuate to safe level + +# === OUTPUT === +patch.set_position(30, 230) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 260) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [gen_obj.outs[0], gain.ins[0]], # FM output → attenuator + [gain.outs[0], dac.ins[0]], # attenuated → left speaker + [gain.outs[0], dac.ins[1]], # attenuated → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_fm_synthesis.maxpat") diff --git a/examples/gen-noise-and-hold/gen_noise_and_hold.maxpat b/examples/gen-noise-and-hold/gen_noise_and_hold.maxpat new file mode 100644 index 0000000..5bcada3 --- /dev/null +++ b/examples/gen-noise-and-hold/gen_noise_and_hold.maxpat @@ -0,0 +1,670 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === GEN~ PITCH GENERATOR ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- NOISE SOURCE ---" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 80, + 60.0, + 22.0 + ], + "text": "noise" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 380.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- TRIGGER CHAIN ---" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 80, + 60.0, + 22.0 + ], + "text": "param rate 4" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 150, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 220, + 60.0, + 22.0 + ], + "text": "delta" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 290, + 60.0, + 22.0 + ], + "text": "abs" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 380.0, + 360, + 18.0, + 22.0 + ], + "text": "> 0.5" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 360, + 150.0, + 20.0 + ], + "text": "comment --- SAMPLE AND HOLD ---" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 390, + 60.0, + 22.0 + ], + "text": "sah" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 460, + 150.0, + 20.0 + ], + "text": "comment --- SCALING ---" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 490, + 18.0, + 22.0 + ], + "text": "* 500" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 560, + 18.0, + 22.0 + ], + "text": "+ 700" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 630, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-10", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-5", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-7", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-7", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-10", + 1 + ], + "source": [ + "obj-8", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-12", + 0 + ], + "source": [ + "obj-10", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-13", + 0 + ], + "source": [ + "obj-12", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-14", + 0 + ], + "source": [ + "obj-13", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 60, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === OSCILLATOR ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 160, + 43.0, + 22.0 + ], + "text": "cycle~" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === GAIN CONTROL ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 260, + 20.0, + 22.0 + ], + "text": "*~ 0.2" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 330, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 360, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-noise-and-hold/main.py b/examples/gen-noise-and-hold/main.py new file mode 100644 index 0000000..af849b6 --- /dev/null +++ b/examples/gen-noise-and-hold/main.py @@ -0,0 +1,151 @@ +""" +Gen~ Noise-and-Hold Example +============================ +A sample-and-hold random pitch generator. White noise is sampled at a +rate set by a param, producing stepped random voltages that drive a +sine oscillator at a random pitch. Demonstrates noise, phasor-based +triggering, and sah (sample-and-hold) inside gen~. + +Signal chain (gen~ interior): + noise → sah (signal input) + param rate 4 → phasor → delta → abs → > 0.5 → sah (trigger input) + sah → * 1000 → + 200 → out 1 + +Signal chain (outer patch): + gen~ → cycle~ → *~ 0.2 → ezdac~ + (gen~ output is used as frequency for cycle~) + +Usage: + python main.py + → Generates gen_noise_and_hold.maxpat + → Open in Max/MSP and click the ezdac~ to hear random pitch steps + → Increase the rate param to speed up the stepping +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: sample-and-hold random pitch generator +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# --- NOISE SOURCE --- +gen_patch.set_position(80, 50) +gen_patch.place("comment --- NOISE SOURCE ---", verbose=False)[0] + +gen_patch.set_position(80, 80) +noise = gen_patch.place("noise", verbose=False)[0] # white noise: output -1 to 1 + +# --- TRIGGER CHAIN --- +gen_patch.set_position(300, 50) +gen_patch.place("comment --- TRIGGER CHAIN ---", verbose=False)[0] + +# Rate param controls how many times per second the hold updates +gen_patch.set_position(300, 80) +rate_param = gen_patch.place("param rate 4", verbose=False)[0] # hold rate in Hz + +gen_patch.set_position(300, 150) +ph = gen_patch.place("phasor", verbose=False)[0] # ramp 0→1 at rate Hz + +# delta detects the wrap-around discontinuity in the phasor +gen_patch.set_position(300, 220) +dlt = gen_patch.place("delta", verbose=False)[0] # sample-to-sample difference + +# abs to get magnitude of the negative jump at the wrap +gen_patch.set_position(300, 290) +abso = gen_patch.place("abs", verbose=False)[0] # magnitude of delta + +# threshold: wrap produces a large negative delta, abs makes it large positive +gen_patch.set_position(300, 360) +thresh = gen_patch.place("> 0.5", verbose=False)[0] # 1 when wrap occurs, else 0 + +# --- SAMPLE AND HOLD --- +gen_patch.set_position(80, 360) +gen_patch.place("comment --- SAMPLE AND HOLD ---", verbose=False)[0] + +gen_patch.set_position(80, 390) +sah = gen_patch.place("sah", verbose=False)[0] # sah: holds input when triggered + +# --- SCALING --- +gen_patch.set_position(80, 460) +gen_patch.place("comment --- SCALING ---", verbose=False)[0] + +gen_patch.set_position(80, 490) +scale = gen_patch.place("* 500", verbose=False)[0] # scale noise (-1..1) to (-500..500) + +gen_patch.set_position(80, 560) +offset = gen_patch.place("+ 700", verbose=False)[0] # shift to (200..1200 Hz) + +# Output port +gen_patch.set_position(80, 630) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire trigger chain: rate_param → phasor → delta → abs → > 0.5 +gen_patch.connect( + [rate_param.outs[0], ph.ins[0]], # rate → phasor frequency + [ph.outs[0], dlt.ins[0]], # phasor ramp → delta + [dlt.outs[0], abso.ins[0]], # delta → abs + [abso.outs[0], thresh.ins[0]], # abs → threshold comparator + verbose=False, +) + +# Wire sah: noise → sah signal input, trigger → sah trigger input +gen_patch.connect( + [noise.outs[0], sah.ins[0]], # noise → sah signal + [thresh.outs[0], sah.ins[1]], # trigger pulse → sah trigger + verbose=False, +) + +# Wire scaling: sah → * 500 → + 700 → out +gen_patch.connect( + [sah.outs[0], scale.ins[0]], # held noise → scale + [scale.outs[0], offset.ins[0]], # scaled → offset + [offset.outs[0], gen_out.ins[0]], # frequency value → gen outlet + verbose=False, +) + +# ===================================================================== +# OUTER PATCH: gen~ output drives a cycle~ oscillator +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === GEN~ PITCH GENERATOR === +patch.set_position(30, 30) +patch.place("comment === GEN~ PITCH GENERATOR ===", verbose=False)[0] + +patch.set_position(30, 60) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === OSCILLATOR === +patch.set_position(30, 130) +patch.place("comment === OSCILLATOR ===", verbose=False)[0] + +patch.set_position(30, 160) +# cycle~ uses the stepped frequency from gen~ to produce the tone +osc = patch.place("cycle~", verbose=False)[0] + +# === GAIN CONTROL === +patch.set_position(30, 230) +patch.place("comment === GAIN CONTROL ===", verbose=False)[0] + +patch.set_position(30, 260) +gain = patch.place("*~ 0.2", verbose=False)[0] # gentle listening level + +# === OUTPUT === +patch.set_position(30, 330) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 360) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [gen_obj.outs[0], osc.ins[0]], # gen~ frequency → cycle~ frequency inlet + [osc.outs[0], gain.ins[0]], # oscillator → attenuator + [gain.outs[0], dac.ins[0]], # attenuated → left speaker + [gain.outs[0], dac.ins[1]], # attenuated → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_noise_and_hold.maxpat") diff --git a/examples/gen-onepole-filter/gen_onepole_filter.maxpat b/examples/gen-onepole-filter/gen_onepole_filter.maxpat new file mode 100644 index 0000000..764e818 --- /dev/null +++ b/examples/gen-onepole-filter/gen_onepole_filter.maxpat @@ -0,0 +1,601 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === NOISE SOURCE ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 60, + 44.0, + 22.0 + ], + "text": "noise~" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GEN~ FILTER ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- INPUTS ---" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 80, + 60.0, + 22.0 + ], + "text": "in 1" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 80, + 60.0, + 22.0 + ], + "text": "param cutoff 0.1" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 160, + 150.0, + 20.0 + ], + "text": "comment --- FEEDBACK STATE ---" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 190, + 60.0, + 22.0 + ], + "text": "history" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 270, + 150.0, + 20.0 + ], + "text": "comment --- FILTER MATH ---" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 300, + 18.0, + 22.0 + ], + "text": "-" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 370, + 18.0, + 22.0 + ], + "text": "*" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 160.0, + 440, + 18.0, + 22.0 + ], + "text": "+" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 530, + 150.0, + 20.0 + ], + "text": "comment --- OUTPUT ---" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 560, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-7", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-7", + 1 + ], + "source": [ + "obj-5", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-9", + 0 + ], + "source": [ + "obj-5", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-7", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-9", + 1 + ], + "source": [ + "obj-8", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-9", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-11", + 0 + ], + "source": [ + "obj-9", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 160, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === GAIN CONTROL ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 260, + 20.0, + 22.0 + ], + "text": "*~ 0.5" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 330, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 360, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-onepole-filter/main.py b/examples/gen-onepole-filter/main.py new file mode 100644 index 0000000..b8cc826 --- /dev/null +++ b/examples/gen-onepole-filter/main.py @@ -0,0 +1,158 @@ +""" +Gen~ One-Pole Lowpass Filter Example +====================================== +A one-pole IIR lowpass filter built from first principles inside gen~. +The classic feedback formula y[n] = y[n-1] + c * (x[n] - y[n-1]) is +wired explicitly using gen~ math and history operators, making the +signal flow transparent and educational. + +One-pole formula: + error = x[n] - y[n-1] (how far input is from last output) + correction = error * cutoff (fraction of error to close this sample) + y[n] = y[n-1] + correction (new output: previous + correction) + +Signal chain (gen~ interior): + in 1 ──────────────────────┐ + ▼ + history ──► - (error) ──► * (correction) ──► + (new output) ──► out 1 + ▲ │ ▲ │ + │ └───────────────┘ param cutoff │ + └────────────────────────────────────────────┘ (feedback) + +Signal chain (outer patch): + noise~ → gen~ → *~ 0.5 → ezdac~ + +Usage: + python main.py + → Generates gen_onepole_filter.maxpat + → Open in Max/MSP and click the ezdac~ to hear filtered white noise + → Send a float 0-1 to gen~'s cutoff param to sweep the filter + (low values = dark/muffled, high values = bright/full spectrum) +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: one-pole lowpass filter +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# --- INPUTS --- +gen_patch.set_position(80, 50) +gen_patch.place("comment --- INPUTS ---", verbose=False)[0] + +gen_patch.set_position(80, 80) +gen_in = gen_patch.place("in 1", verbose=False)[0] # audio input + +# cutoff coefficient: 0 = frozen (no update), 1 = no smoothing (bypass) +gen_patch.set_position(300, 80) +cutoff_param = gen_patch.place("param cutoff 0.1", verbose=False)[0] + +# --- FEEDBACK STATE --- +gen_patch.set_position(80, 160) +gen_patch.place("comment --- FEEDBACK STATE ---", verbose=False)[0] + +gen_patch.set_position(80, 190) +# history holds the previous output sample, initialised to 0 +hist = gen_patch.place("history", verbose=False)[0] + +# --- FILTER MATH --- +gen_patch.set_position(80, 270) +gen_patch.place("comment --- FILTER MATH ---", verbose=False)[0] + +# error = x[n] - y[n-1] +gen_patch.set_position(80, 300) +sub = gen_patch.place("-", verbose=False)[0] + +# correction = error * cutoff +gen_patch.set_position(80, 370) +mul = gen_patch.place("*", verbose=False)[0] + +# new output = y[n-1] + correction +gen_patch.set_position(80, 440) +add = gen_patch.place("+", verbose=False)[0] + +# --- OUTPUT --- +gen_patch.set_position(80, 530) +gen_patch.place("comment --- OUTPUT ---", verbose=False)[0] + +gen_patch.set_position(80, 560) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire error computation: in1 - prev_output +gen_patch.connect( + [gen_in.outs[0], sub.ins[0]], # x[n] → subtract left inlet + [hist.outs[0], sub.ins[1]], # y[n-1] → subtract right inlet (x - prev) + verbose=False, +) + +# Wire correction: error * cutoff +gen_patch.connect( + [sub.outs[0], mul.ins[0]], # error → multiply left inlet + [cutoff_param.outs[0], mul.ins[1]], # cutoff → multiply right inlet + verbose=False, +) + +# Wire new output: prev + correction, then feed back into history +gen_patch.connect( + [hist.outs[0], add.ins[0]], # y[n-1] → add left inlet + [mul.outs[0], add.ins[1]], # correction → add right inlet + verbose=False, +) + +# Feedback: new output → history (closes the loop) +gen_patch.connect( + [add.outs[0], hist.ins[0]], # y[n] → history (feedback) + verbose=False, +) + +# To output +gen_patch.connect( + [add.outs[0], gen_out.ins[0]], # y[n] → gen outlet + verbose=False, +) + +# ===================================================================== +# OUTER PATCH: filter white noise +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === NOISE SOURCE === +patch.set_position(30, 30) +patch.place("comment === NOISE SOURCE ===", verbose=False)[0] + +patch.set_position(30, 60) +noise = patch.place("noise~", verbose=False)[0] # broadband white noise + +# === GEN~ FILTER === +patch.set_position(30, 130) +patch.place("comment === GEN~ FILTER ===", verbose=False)[0] + +patch.set_position(30, 160) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === GAIN CONTROL === +patch.set_position(30, 230) +patch.place("comment === GAIN CONTROL ===", verbose=False)[0] + +patch.set_position(30, 260) +gain = patch.place("*~ 0.5", verbose=False)[0] # attenuate to safe level + +# === OUTPUT === +patch.set_position(30, 330) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 360) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [noise.outs[0], gen_obj.ins[0]], # white noise → gen~ audio inlet + [gen_obj.outs[0], gain.ins[0]], # filtered signal → attenuator + [gain.outs[0], dac.ins[0]], # attenuated → left speaker + [gain.outs[0], dac.ins[1]], # attenuated → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_onepole_filter.maxpat") diff --git a/examples/gen-passthrough/gen_passthrough.maxpat b/examples/gen-passthrough/gen_passthrough.maxpat new file mode 100644 index 0000000..f92824b --- /dev/null +++ b/examples/gen-passthrough/gen_passthrough.maxpat @@ -0,0 +1,298 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === SIGNAL SOURCE ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 60, + 43.0, + 22.0 + ], + "text": "cycle~ 440" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 120, + 150.0, + 20.0 + ], + "text": "comment === GEN~ PROCESSOR ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 80, + 60.0, + 22.0 + ], + "text": "in 1" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 180, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-2", + 0 + ], + "source": [ + "obj-1", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 150, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 220, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 250, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 1 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-passthrough/main.py b/examples/gen-passthrough/main.py new file mode 100644 index 0000000..e66951d --- /dev/null +++ b/examples/gen-passthrough/main.py @@ -0,0 +1,75 @@ +""" +Gen~ Passthrough Example +======================== +The simplest possible gen~ patch: audio enters, passes through unchanged, +and exits. This illustrates the basic input/output pattern inside gen~. + +Signal chain (gen~ interior): + in 1 → out 1 + +Signal chain (outer patch): + cycle~ 440 → gen~ → ezdac~ + +Usage: + python main.py + → Generates gen_passthrough.maxpat + → Open in Max/MSP and click the ezdac~ to hear a 440 Hz tone +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: build the sub-patcher that runs inside gen~ +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# Place gen input and output ports +gen_patch.set_position(100, 80) +gen_in = gen_patch.place("in 1", verbose=False)[0] # audio inlet of gen~ + +gen_patch.set_position(100, 180) +gen_out = gen_patch.place("out 1", verbose=False)[0] # audio outlet of gen~ + +# Wire in 1 → out 1 (direct passthrough — no processing) +gen_patch.connect( + [gen_in.outs[0], gen_out.ins[0]], # signal passes through unmodified + verbose=False, +) + +# ===================================================================== +# OUTER PATCH: the Max patcher that hosts gen~ +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === SIGNAL SOURCE === +patch.set_position(30, 30) +patch.place("comment === SIGNAL SOURCE ===", verbose=False)[0] + +patch.set_position(30, 60) +osc = patch.place("cycle~ 440", verbose=False)[0] # 440 Hz test tone + +# === GEN~ PROCESSOR === +patch.set_position(30, 120) +patch.place("comment === GEN~ PROCESSOR ===", verbose=False)[0] + +patch.set_position(30, 150) +# Embed the gen sub-patcher into the gen~ object +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === OUTPUT === +patch.set_position(30, 220) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 250) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [osc.outs[0], gen_obj.ins[0]], # test tone → gen~ inlet + [gen_obj.outs[0], dac.ins[0]], # gen~ left outlet → speaker left + [gen_obj.outs[0], dac.ins[1]], # gen~ right outlet → speaker right + verbose=False, +) + +# === SAVE === +patch.save("gen_passthrough.maxpat") diff --git a/examples/gen-ramp-to-click/gen_ramp_to_click.maxpat b/examples/gen-ramp-to-click/gen_ramp_to_click.maxpat new file mode 100644 index 0000000..b830d0a --- /dev/null +++ b/examples/gen-ramp-to-click/gen_ramp_to_click.maxpat @@ -0,0 +1,430 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === GEN~ CLICK GENERATOR ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 50, + 60.0, + 22.0 + ], + "text": "param rate 2" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 120, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 190, + 60.0, + 22.0 + ], + "text": "delta" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 260, + 60.0, + 22.0 + ], + "text": "abs" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 180.0, + 330, + 18.0, + 22.0 + ], + "text": "> 0.5" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 400, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-2", + 0 + ], + "source": [ + "obj-1", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-3", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-5", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 60, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GAIN CONTROL ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 160, + 20.0, + 22.0 + ], + "text": "*~ 0.5" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 260, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 1 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-ramp-to-click/main.py b/examples/gen-ramp-to-click/main.py new file mode 100644 index 0000000..9e72848 --- /dev/null +++ b/examples/gen-ramp-to-click/main.py @@ -0,0 +1,105 @@ +""" +Gen~ Ramp-to-Click Example +============================ +Generates rhythmic audio clicks by detecting the discontinuity in a +phasor's sawtooth waveform. When a phasor resets from ~1 back to 0, +the delta (sample-to-sample difference) produces a large negative spike. +Taking the absolute value and thresholding it yields a clean click pulse. + +This technique is widely used for metronomes, click tracks, and +synchronizing processes to a phasor's cycle rate. + +Signal chain (gen~ interior): + param rate 2 → phasor → delta → abs → > 0.5 → out 1 + +Signal chain (outer patch): + gen~ → *~ 0.5 → ezdac~ + +Usage: + python main.py + → Generates gen_ramp_to_click.maxpat + → Open in Max/MSP; you will hear clicks at 2 Hz (2 clicks per second) + → Change param rate to adjust click frequency +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: phasor discontinuity → click pulse +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# param rate sets the phasor frequency in Hz (default: 2 clicks/sec) +gen_patch.set_position(100, 50) +rate_param = gen_patch.place("param rate 2", verbose=False)[0] + +# phasor outputs a 0→1 sawtooth at the given rate +# At each cycle wrap, it jumps from ~1.0 back to 0 in one sample +gen_patch.set_position(100, 120) +ph = gen_patch.place("phasor", verbose=False)[0] + +# delta computes the difference between consecutive samples +# The wrap-around produces a large negative spike (~-1.0) +gen_patch.set_position(100, 190) +dlt = gen_patch.place("delta", verbose=False)[0] + +# abs makes the negative spike positive (~1.0), normal steps stay near 0 +gen_patch.set_position(100, 260) +ab = gen_patch.place("abs", verbose=False)[0] + +# > 0.5 outputs 1 only when the absolute delta exceeds 0.5 +# This fires exactly once per phasor cycle (at the discontinuity) +gen_patch.set_position(100, 330) +thresh = gen_patch.place("> 0.5", verbose=False)[0] + +# Output the 0/1 click pulse +gen_patch.set_position(100, 400) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire: param rate → phasor → delta → abs → > 0.5 → out 1 +gen_patch.connect( + [rate_param.outs[0], ph.ins[0]], # rate → phasor frequency + [ph.outs[0], dlt.ins[0]], # phasor → delta detector + [dlt.outs[0], ab.ins[0]], # delta → absolute value + [ab.outs[0], thresh.ins[0]], # abs delta → threshold comparator + [thresh.outs[0], gen_out.ins[0]], # pulse → output + verbose=False, +) + +# ===================================================================== +# OUTER PATCH +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === GEN~ CLICK GENERATOR === +patch.set_position(30, 30) +patch.place("comment === GEN~ CLICK GENERATOR ===", verbose=False)[0] + +patch.set_position(30, 60) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === GAIN CONTROL === +patch.set_position(30, 130) +patch.place("comment === GAIN CONTROL ===", verbose=False)[0] + +patch.set_position(30, 160) +# Scale the 0/1 click pulse to a safe amplitude +gain = patch.place("*~ 0.5", verbose=False)[0] + +# === OUTPUT === +patch.set_position(30, 230) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 260) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [gen_obj.outs[0], gain.ins[0]], # click pulse → gain attenuator + [gain.outs[0], dac.ins[0]], # attenuated click → left speaker + [gain.outs[0], dac.ins[1]], # attenuated click → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_ramp_to_click.maxpat") diff --git a/examples/gen-sample-counter/gen_sample_counter.maxpat b/examples/gen-sample-counter/gen_sample_counter.maxpat new file mode 100644 index 0000000..fdc3168 --- /dev/null +++ b/examples/gen-sample-counter/gen_sample_counter.maxpat @@ -0,0 +1,373 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === SIGNAL SOURCE ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 60, + 31.0, + 22.0 + ], + "text": "sig~ 1" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GEN~ COUNTER ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 140.0, + 50, + 60.0, + 22.0 + ], + "text": "in 1" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 240.0, + 130, + 18.0, + 22.0 + ], + "text": "+" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 360.0, + 130, + 60.0, + 22.0 + ], + "text": "history" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 240.0, + 220, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-2", + 0 + ], + "source": [ + "obj-1", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-3", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-2", + 1 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 160, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === DISPLAY ===" + } + }, + { + "box": { + "fontface": 0, + "fontname": "Arial", + "fontsize": 12.0, + "id": "obj-6", + "maxclass": "number~", + "mode": 2, + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ + "signal", + "float" + ], + "patching_rect": [ + 110.0, + 260, + 56.0, + 22.0 + ], + "sig": 0.0, + "text": "number~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-sample-counter/main.py b/examples/gen-sample-counter/main.py new file mode 100644 index 0000000..3eb4ff0 --- /dev/null +++ b/examples/gen-sample-counter/main.py @@ -0,0 +1,99 @@ +""" +Gen~ Sample Counter Example +============================ +Demonstrates the fundamental accumulator pattern inside gen~: using a +history object to feed the previous sample's value back into an adder. +Each time a non-zero signal arrives, the running total increments. + +This is the building block for many gen~ algorithms — any time you need +to "remember" a value across samples, history is the tool. + +Signal chain (gen~ interior): + in 1 ──→ + ──→ out 1 + ↑ │ + history ←──┘ (feedback: previous output feeds back into adder) + +Signal chain (outer patch): + sig~ 1 → gen~ → number~ + +Usage: + python main.py + → Generates gen_sample_counter.maxpat + → Open in Max/MSP; number~ will display a steadily climbing sample count + → Replace sig~ 1 with sig~ 0 to pause the counter +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: accumulator using history feedback +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# in 1 provides the per-sample increment value (e.g. 1 = count every sample) +gen_patch.set_position(60, 50) +gen_in = gen_patch.place("in 1", verbose=False)[0] + +# + adds the current increment to the stored previous total +gen_patch.set_position(160, 130) +adder = gen_patch.place("+", verbose=False)[0] + +# history stores one sample of state — the previous output of the adder +# On the very first sample, history outputs 0 (its initial value) +gen_patch.set_position(280, 130) +hist = gen_patch.place("history", verbose=False)[0] + +# out 1 sends the running total to the outer patch +gen_patch.set_position(160, 220) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire the accumulator loop: +# in 1 → left inlet of + (new increment each sample) +# history → right inlet of + (previously accumulated total) +# + → history (store this sample's total for next sample) +# + → out 1 (also send the total downstream) +gen_patch.connect( + [gen_in.outs[0], adder.ins[0]], # increment → adder left inlet + [hist.outs[0], adder.ins[1]], # previous total → adder right inlet + [adder.outs[0], hist.ins[0]], # new total → history (feedback) + [adder.outs[0], gen_out.ins[0]], # new total → output + verbose=False, +) + +# ===================================================================== +# OUTER PATCH +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === SIGNAL SOURCE === +patch.set_position(30, 30) +patch.place("comment === SIGNAL SOURCE ===", verbose=False)[0] + +patch.set_position(30, 60) +# sig~ 1 sends a constant 1.0 every sample — counter increments by 1 each sample +sig = patch.place("sig~ 1", verbose=False)[0] + +# === GEN~ COUNTER === +patch.set_position(30, 130) +patch.place("comment === GEN~ COUNTER ===", verbose=False)[0] + +patch.set_position(30, 160) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === DISPLAY === +patch.set_position(30, 230) +patch.place("comment === DISPLAY ===", verbose=False)[0] + +patch.set_position(30, 260) +# number~ displays a signal value updated once per vector +num = patch.place("number~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [sig.outs[0], gen_obj.ins[0]], # constant 1 → gen~ (increment each sample) + [gen_obj.outs[0], num.ins[0]], # running total → number~ display + verbose=False, +) + +# === SAVE === +patch.save("gen_sample_counter.maxpat") diff --git a/examples/gen-sine-oscillator/gen_sine_oscillator.maxpat b/examples/gen-sine-oscillator/gen_sine_oscillator.maxpat new file mode 100644 index 0000000..cfe17a9 --- /dev/null +++ b/examples/gen-sine-oscillator/gen_sine_oscillator.maxpat @@ -0,0 +1,364 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === GEN~ OSCILLATOR ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 50, + 60.0, + 22.0 + ], + "text": "param freq 440" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 120, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 190, + 60.0, + 22.0 + ], + "text": "cycle" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 180.0, + 260, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-2", + 0 + ], + "source": [ + "obj-1", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-3", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 60, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GAIN CONTROL ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 160, + 20.0, + 22.0 + ], + "text": "*~ 0.3" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 260, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 1 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-sine-oscillator/main.py b/examples/gen-sine-oscillator/main.py new file mode 100644 index 0000000..12c6602 --- /dev/null +++ b/examples/gen-sine-oscillator/main.py @@ -0,0 +1,89 @@ +""" +Gen~ Sine Oscillator Example +============================== +A self-contained sine oscillator built entirely inside gen~. +The frequency is controlled by a param object, making it tweakable +from the outer patch. This demonstrates how gen~ can encapsulate +a complete synthesis algorithm. + +Signal chain (gen~ interior): + param freq 440 → phasor → cycle → out 1 + +Signal chain (outer patch): + gen~ → *~ 0.3 → ezdac~ + +Usage: + python main.py + → Generates gen_sine_oscillator.maxpat + → Open in Max/MSP and click the ezdac~ to hear a 440 Hz sine wave + → Send a float to gen~'s freq param to change pitch +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: self-contained sine oscillator +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# Declare a named parameter for frequency (default 440 Hz) +gen_patch.set_position(100, 50) +freq_param = gen_patch.place("param freq 440", verbose=False)[0] + +# phasor generates a 0→1 sawtooth ramp at the given frequency +gen_patch.set_position(100, 120) +ph = gen_patch.place("phasor", verbose=False)[0] + +# cycle uses the phasor ramp as a phase index into one sine period +gen_patch.set_position(100, 190) +cyc = gen_patch.place("cycle", verbose=False)[0] + +# Output port +gen_patch.set_position(100, 260) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire: param freq → phasor (frequency input) → cycle (phase input) → out +gen_patch.connect( + [freq_param.outs[0], ph.ins[0]], # frequency → phasor + [ph.outs[0], cyc.ins[0]], # phasor ramp → cycle phase + [cyc.outs[0], gen_out.ins[0]], # sine output → gen outlet + verbose=False, +) + +# ===================================================================== +# OUTER PATCH +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === GEN~ OSCILLATOR === +patch.set_position(30, 30) +patch.place("comment === GEN~ OSCILLATOR ===", verbose=False)[0] + +patch.set_position(30, 60) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === GAIN CONTROL === +patch.set_position(30, 130) +patch.place("comment === GAIN CONTROL ===", verbose=False)[0] + +patch.set_position(30, 160) +# Attenuate to a safe listening level before sending to speakers +gain = patch.place("*~ 0.3", verbose=False)[0] + +# === OUTPUT === +patch.set_position(30, 230) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 260) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [gen_obj.outs[0], gain.ins[0]], # gen~ sine → attenuator + [gain.outs[0], dac.ins[0]], # attenuated signal → left speaker + [gain.outs[0], dac.ins[1]], # attenuated signal → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_sine_oscillator.maxpat") diff --git a/examples/gen-verification-test/gen_verification_test.maxpat b/examples/gen-verification-test/gen_verification_test.maxpat new file mode 100644 index 0000000..78209a9 --- /dev/null +++ b/examples/gen-verification-test/gen_verification_test.maxpat @@ -0,0 +1,751 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === GEN~ VERIFICATION TEST ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 130.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- MAIN SIGNAL PATH ---" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 130.0, + 80, + 60.0, + 22.0 + ], + "text": "param freq 220" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 130.0, + 130, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 130.0, + 180, + 60.0, + 22.0 + ], + "text": "cycle" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 130.0, + 230, + 18.0, + 22.0 + ], + "text": "* 0.8" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 130.0, + 350, + 60.0, + 22.0 + ], + "text": "out 1" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 380.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- VERIFICATION OPS ---" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 80, + 60.0, + 22.0 + ], + "text": "history" + } + }, + { + "box": { + "id": "obj-9", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 380.0, + 130, + 18.0, + 22.0 + ], + "text": "+" + } + }, + { + "box": { + "id": "obj-10", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 180, + 60.0, + 22.0 + ], + "text": "wrap 0 1" + } + }, + { + "box": { + "id": "obj-11", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 230, + 60.0, + 22.0 + ], + "text": "clip 0 1" + } + }, + { + "box": { + "id": "obj-12", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 280, + 60.0, + 22.0 + ], + "text": "fold 0 1" + } + }, + { + "box": { + "id": "obj-13", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 160.0, + 60.0, + 22.0 + ], + "text": "delta" + } + }, + { + "box": { + "id": "obj-14", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 210.0, + 60.0, + 22.0 + ], + "text": "abs" + } + }, + { + "box": { + "id": "obj-15", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 280.0, + 60.0, + 22.0 + ], + "text": "noise" + } + }, + { + "box": { + "id": "obj-16", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 330.0, + 60.0, + 22.0 + ], + "text": "sah" + } + }, + { + "box": { + "id": "obj-17", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 390.0, + 60.0, + 22.0 + ], + "text": "slide" + } + }, + { + "box": { + "id": "obj-18", + "maxclass": "newobj", + "numinlets": 6, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 80.0, + 450.0, + 60.0, + 22.0 + ], + "text": "scale" + } + }, + { + "box": { + "id": "obj-19", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 330, + 60.0, + 22.0 + ], + "text": "mix" + } + }, + { + "box": { + "id": "obj-20", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 380.0, + 380, + 60.0, + 22.0 + ], + "text": "switch 0" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-3", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-13", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-5", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-9", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-14", + 0 + ], + "source": [ + "obj-13", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-16", + 1 + ], + "source": [ + "obj-14", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-16", + 0 + ], + "source": [ + "obj-15", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-17", + 0 + ], + "source": [ + "obj-16", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 60, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 130, + 20.0, + 22.0 + ], + "text": "*~ 0.3" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 200, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "scope~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 280.0, + 130, + 130.0, + 130.0 + ], + "text": "scope~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-3", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 1 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-verification-test/main.py b/examples/gen-verification-test/main.py new file mode 100644 index 0000000..23723f9 --- /dev/null +++ b/examples/gen-verification-test/main.py @@ -0,0 +1,163 @@ +""" +Gen~ Verification Test Patch +============================= +A comprehensive test patch that exercises many gen operators to verify +they load and function correctly in Max. Open the generated patch in +Max and confirm: + +1. No errors in the Max console +2. The gen~ object shows its patcher when double-clicked +3. Audio plays when ezdac~ is enabled +4. The scope~ shows a waveform + +Signal chain (gen~ interior): + param freq 220 -> phasor -> cycle -> * 0.8 -> out 1 + Also includes: history feedback, wrap, delta, abs, sah, noise, + slide, clip, fold, scale operators (connected but mixed to zero + so they don't affect audio — just verifying they load). + +Signal chain (outer patch): + gen~ -> *~ 0.3 -> ezdac~ + gen~ -> scope~ + +Usage: + python main.py + -> Generates gen_verification_test.maxpat + -> Open in Max, enable ezdac~, double-click gen~ to inspect interior +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: exercises many operators +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# --- MAIN SIGNAL PATH --- +gen_patch.set_position(50, 50) +gen_patch.place("comment --- MAIN SIGNAL PATH ---", verbose=False) + +gen_patch.set_position(50, 80) +freq = gen_patch.place("param freq 220", verbose=False)[0] + +gen_patch.set_position(50, 130) +ph = gen_patch.place("phasor", verbose=False)[0] + +gen_patch.set_position(50, 180) +cyc = gen_patch.place("cycle", verbose=False)[0] + +gen_patch.set_position(50, 230) +gain = gen_patch.place("* 0.8", verbose=False)[0] + +gen_patch.set_position(50, 350) +out1 = gen_patch.place("out 1", verbose=False)[0] + +# Main signal: freq -> phasor -> cycle -> * 0.8 -> out +gen_patch.connect( + [freq.outs[0], ph.ins[0]], + [ph.outs[0], cyc.ins[0]], + [cyc.outs[0], gain.ins[0]], + [gain.outs[0], out1.ins[0]], + verbose=False, +) + +# --- VERIFICATION OPERATORS (connected but not audible) --- +gen_patch.set_position(300, 50) +gen_patch.place("comment --- VERIFICATION OPS ---", verbose=False) + +# history feedback test +gen_patch.set_position(300, 80) +hist = gen_patch.place("history", verbose=False)[0] +gen_patch.set_position(300, 130) +add = gen_patch.place("+", verbose=False)[0] +# Create a tiny feedback loop: add -> history -> add (won't affect output) +gen_patch.connect( + [add.outs[0], hist.ins[0]], + verbose=False, +) + +# wrap, clip, fold +gen_patch.set_position(300, 180) +wr = gen_patch.place("wrap 0 1", verbose=False)[0] +gen_patch.set_position(300, 230) +cl = gen_patch.place("clip 0 1", verbose=False)[0] +gen_patch.set_position(300, 280) +fo = gen_patch.place("fold 0 1", verbose=False)[0] + +# delta, abs +gen_patch.set_position(500, 80) +dlt = gen_patch.place("delta", verbose=False)[0] +gen_patch.set_position(500, 130) +ab = gen_patch.place("abs", verbose=False)[0] +gen_patch.connect( + [ph.outs[0], dlt.ins[0]], + [dlt.outs[0], ab.ins[0]], + verbose=False, +) + +# noise + sah +gen_patch.set_position(500, 200) +ns = gen_patch.place("noise", verbose=False)[0] +gen_patch.set_position(500, 250) +sh = gen_patch.place("sah", verbose=False)[0] +gen_patch.connect( + [ns.outs[0], sh.ins[0]], + [ab.outs[0], sh.ins[1]], + verbose=False, +) + +# slide +gen_patch.set_position(500, 310) +sl = gen_patch.place("slide", verbose=False)[0] +gen_patch.connect( + [sh.outs[0], sl.ins[0]], + verbose=False, +) + +# scale +gen_patch.set_position(500, 370) +sc = gen_patch.place("scale", verbose=False)[0] + +# mix +gen_patch.set_position(300, 330) +mx = gen_patch.place("mix", verbose=False)[0] + +# switch +gen_patch.set_position(300, 380) +sw = gen_patch.place("switch 0", verbose=False)[0] + +# ===================================================================== +# OUTER PATCH +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === GEN~ === +patch.set_position(30, 30) +patch.place("comment === GEN~ VERIFICATION TEST ===", verbose=False) + +patch.set_position(30, 60) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === GAIN === +patch.set_position(30, 130) +vol = patch.place("*~ 0.3", verbose=False)[0] + +# === OUTPUT === +patch.set_position(30, 200) +dac = patch.place("ezdac~", verbose=False)[0] + +# === SCOPE === +patch.set_position(200, 130) +scope = patch.place("scope~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [gen_obj.outs[0], vol.ins[0]], + [vol.outs[0], dac.ins[0]], + [vol.outs[0], dac.ins[1]], + [gen_obj.outs[0], scope.ins[0]], + verbose=False, +) + +# === SAVE === +patch.save("gen_verification_test.maxpat") diff --git a/examples/gen-waveshaper/gen_waveshaper.maxpat b/examples/gen-waveshaper/gen_waveshaper.maxpat new file mode 100644 index 0000000..92315aa --- /dev/null +++ b/examples/gen-waveshaper/gen_waveshaper.maxpat @@ -0,0 +1,445 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === SIGNAL SOURCE ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 60, + 43.0, + 22.0 + ], + "text": "cycle~ 220" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GEN~ WAVESHAPER ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 140.0, + 50, + 60.0, + 22.0 + ], + "text": "in 1" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 320.0, + 50, + 60.0, + 22.0 + ], + "text": "param drive 3" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "int" + ], + "patching_rect": [ + 230.0, + 140, + 18.0, + 22.0 + ], + "text": "*" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 230.0, + 220, + 60.0, + 22.0 + ], + "text": "tanh" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 230.0, + 300, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-3", + 0 + ], + "source": [ + "obj-1", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-3", + 1 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-3", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 160, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === GAIN CONTROL ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 260, + 20.0, + 22.0 + ], + "text": "*~ 0.3" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 330, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 360, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-4", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-waveshaper/main.py b/examples/gen-waveshaper/main.py new file mode 100644 index 0000000..5b438b5 --- /dev/null +++ b/examples/gen-waveshaper/main.py @@ -0,0 +1,117 @@ +""" +Gen~ Waveshaper Example +======================== +Soft-clip distortion using tanh waveshaping inside gen~. + +Multiplying the input signal by a drive factor increases its amplitude +before waveshaping. The tanh function compresses large values toward ±1 +with a smooth S-curve, producing warm harmonic distortion rather than +the harsh clipping of a hard limiter. + +At low drive values the signal passes through nearly unchanged. +At high drive values (10+) it approaches a square wave. + +Signal chain (gen~ interior): + in 1 ──→ * ──→ tanh → out 1 + ↑ + param drive 3 + +Signal chain (outer patch): + cycle~ 220 → gen~ → *~ 0.3 → ezdac~ + +Usage: + python main.py + → Generates gen_waveshaper.maxpat + → Open in Max/MSP; you will hear a distorted 220 Hz tone + → Send floats to gen~'s drive param to adjust distortion amount: + 1.0 = clean (barely any shaping) + 3.0 = mild overdrive (default) + 10.0 = heavy saturation +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: tanh soft-clip waveshaper +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# in 1 receives the raw audio signal to be shaped +gen_patch.set_position(60, 50) +gen_in = gen_patch.place("in 1", verbose=False)[0] + +# param drive sets the pre-gain before tanh shaping (default: 3) +# Higher drive = more compression = more harmonic distortion +gen_patch.set_position(240, 50) +drive_param = gen_patch.place("param drive 3", verbose=False)[0] + +# * multiplies the audio by the drive factor, boosting the amplitude +# This is what pushes the signal into the nonlinear tanh region +gen_patch.set_position(150, 140) +mul = gen_patch.place("*", verbose=False)[0] + +# tanh is the hyperbolic tangent: outputs in (-1, 1), smooth S-curve +# Small inputs → nearly linear; large inputs → compressed toward ±1 +gen_patch.set_position(150, 220) +th = gen_patch.place("tanh", verbose=False)[0] + +# Output the shaped (soft-clipped) signal +gen_patch.set_position(150, 300) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire: in 1 → left inlet of *, param drive → right inlet of * +# * → tanh → out 1 +gen_patch.connect( + [gen_in.outs[0], mul.ins[0]], # audio → multiplier left inlet + [drive_param.outs[0], mul.ins[1]], # drive amount → multiplier right inlet + [mul.outs[0], th.ins[0]], # driven signal → tanh shaper + [th.outs[0], gen_out.ins[0]], # shaped signal → output + verbose=False, +) + +# ===================================================================== +# OUTER PATCH +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === SIGNAL SOURCE === +patch.set_position(30, 30) +patch.place("comment === SIGNAL SOURCE ===", verbose=False)[0] + +patch.set_position(30, 60) +# 220 Hz sine wave (A3) — a clean input to feed into the waveshaper +osc = patch.place("cycle~ 220", verbose=False)[0] + +# === GEN~ WAVESHAPER === +patch.set_position(30, 130) +patch.place("comment === GEN~ WAVESHAPER ===", verbose=False)[0] + +patch.set_position(30, 160) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === GAIN CONTROL === +patch.set_position(30, 230) +patch.place("comment === GAIN CONTROL ===", verbose=False)[0] + +patch.set_position(30, 260) +# tanh output is already bounded in (-1, 1), attenuate further for safe listening +gain = patch.place("*~ 0.3", verbose=False)[0] + +# === OUTPUT === +patch.set_position(30, 330) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 360) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +patch.connect( + [osc.outs[0], gen_obj.ins[0]], # 220 Hz sine → waveshaper input + [gen_obj.outs[0], gain.ins[0]], # shaped signal → attenuator + [gain.outs[0], dac.ins[0]], # attenuated signal → left speaker + [gain.outs[0], dac.ins[1]], # attenuated signal → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_waveshaper.maxpat") diff --git a/examples/gen-wavetable-osc/gen_wavetable_osc.maxpat b/examples/gen-wavetable-osc/gen_wavetable_osc.maxpat new file mode 100644 index 0000000..6dff58a --- /dev/null +++ b/examples/gen-wavetable-osc/gen_wavetable_osc.maxpat @@ -0,0 +1,462 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "box", + "rect": [ + 34.0, + 87.0, + 1372.0, + 779.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 30, + 150.0, + 20.0 + ], + "text": "comment === WAVETABLE BUFFER ===" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ + "float", + "bang" + ], + "patching_rect": [ + 110.0, + 60, + 46.0, + 22.0 + ], + "text": "buffer~ mytable" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 130, + 150.0, + 20.0 + ], + "text": "comment === GEN~ OSCILLATOR ===" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [ + 0.0, + 0.0, + 600.0, + 450.0 + ], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [ + 15.0, + 15.0 + ], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [ + { + "box": { + "id": "obj-1", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 50, + 150.0, + 20.0 + ], + "text": "comment --- PARAMETERS ---" + } + }, + { + "box": { + "id": "obj-2", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 80, + 60.0, + 22.0 + ], + "text": "param freq 110" + } + }, + { + "box": { + "id": "obj-3", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ + "", + "" + ], + "patching_rect": [ + 380.0, + 80, + 60.0, + 22.0 + ], + "text": "buffer mytable" + } + }, + { + "box": { + "id": "obj-4", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 180, + 150.0, + 20.0 + ], + "text": "comment --- OSCILLATOR ---" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 210, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 290, + 60.0, + 22.0 + ], + "text": "peek mytable" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 160.0, + 380, + 150.0, + 20.0 + ], + "text": "comment --- OUTPUT ---" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 160.0, + 410, + 60.0, + 22.0 + ], + "text": "out 1" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-5", + 0 + ], + "source": [ + "obj-2", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-5", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + } + ] + }, + "patching_rect": [ + 110.0, + 160, + 36.0, + 22.0 + ], + "text": "gen~" + } + }, + { + "box": { + "id": "obj-5", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 230, + 150.0, + 20.0 + ], + "text": "comment === GAIN CONTROL ===" + } + }, + { + "box": { + "id": "obj-6", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "signal" + ], + "patching_rect": [ + 110.0, + 260, + 20.0, + 22.0 + ], + "text": "*~ 0.3" + } + }, + { + "box": { + "id": "obj-7", + "maxclass": "comment", + "numinlets": 1, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 330, + 150.0, + 20.0 + ], + "text": "comment === OUTPUT ===" + } + }, + { + "box": { + "id": "obj-8", + "maxclass": "ezdac~", + "numinlets": 2, + "numoutlets": 0, + "patching_rect": [ + 110.0, + 360, + 45.0, + 45.0 + ], + "text": "ezdac~" + } + } + ], + "lines": [ + { + "patchline": { + "destination": [ + "obj-6", + 0 + ], + "source": [ + "obj-4", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 0 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + }, + { + "patchline": { + "destination": [ + "obj-8", + 1 + ], + "source": [ + "obj-6", + 0 + ], + "midpoints": [ + null + ] + } + } + ], + "dependency_cache": [], + "autosave": 0 + } +} \ No newline at end of file diff --git a/examples/gen-wavetable-osc/main.py b/examples/gen-wavetable-osc/main.py new file mode 100644 index 0000000..26e51f4 --- /dev/null +++ b/examples/gen-wavetable-osc/main.py @@ -0,0 +1,120 @@ +""" +Gen~ Wavetable Oscillator Example +=================================== +A wavetable oscillator that reads a named buffer at audio rate inside +gen~. A phasor generates a 0→1 ramp at the desired frequency; peek +uses that ramp as a normalized read position into the buffer, allowing +any waveform stored in a Max buffer~ to be played back as an oscillator. + +Signal chain (gen~ interior): + param freq 110 → phasor → peek mytable → out 1 + buffer mytable (declares the buffer reference for peek) + +Signal chain (outer patch): + buffer~ mytable (holds the actual waveform data) + gen~ → *~ 0.3 → ezdac~ + +Usage: + python main.py + → Generates gen_wavetable_osc.maxpat + → Open in Max/MSP: the buffer~ mytable is created automatically + → Fill mytable with a waveform (e.g. send it a 'sinesf 1' message) + → Click the ezdac~ to hear the wavetable oscillator at 110 Hz + → Send a float to gen~'s freq param to change pitch +""" + +import maxpylang as mp + +# ===================================================================== +# GEN~ INTERIOR: wavetable oscillator +# ===================================================================== +gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + +# --- PARAMETERS --- +gen_patch.set_position(80, 50) +gen_patch.place("comment --- PARAMETERS ---", verbose=False)[0] + +# Frequency param: controls oscillator pitch +gen_patch.set_position(80, 80) +freq_param = gen_patch.place("param freq 110", verbose=False)[0] + +# Declare the buffer reference — must match the outer buffer~ name +gen_patch.set_position(300, 80) +# buffer declares the buffer reference inside gen~. +# peek finds it by matching names — no patchcord connection needed. +gen_patch.place("buffer mytable", verbose=False)[0] + +# --- OSCILLATOR --- +gen_patch.set_position(80, 180) +gen_patch.place("comment --- OSCILLATOR ---", verbose=False)[0] + +# phasor generates a normalized 0→1 ramp at the given frequency +gen_patch.set_position(80, 210) +ph = gen_patch.place("phasor", verbose=False)[0] + +# peek mytable reads the named buffer at the phasor's 0→1 position +# The buffer name in the argument links peek to the buffer declaration above +gen_patch.set_position(80, 290) +pk = gen_patch.place("peek mytable", verbose=False)[0] + +# --- OUTPUT --- +gen_patch.set_position(80, 380) +gen_patch.place("comment --- OUTPUT ---", verbose=False)[0] + +gen_patch.set_position(80, 410) +gen_out = gen_patch.place("out 1", verbose=False)[0] + +# Wire: freq → phasor (ramp rate), phasor ramp → peek position → out +# peek finds the buffer by the name in its argument — no extra connection needed +gen_patch.connect( + [freq_param.outs[0], ph.ins[0]], # frequency → phasor rate + [ph.outs[0], pk.ins[0]], # 0→1 ramp → peek read position + [pk.outs[0], gen_out.ins[0]], # sample value → gen outlet + verbose=False, +) + +# ===================================================================== +# OUTER PATCH: host the wavetable oscillator +# ===================================================================== +patch = mp.MaxPatch(verbose=False) + +# === WAVETABLE BUFFER === +patch.set_position(30, 30) +patch.place("comment === WAVETABLE BUFFER ===", verbose=False)[0] + +patch.set_position(30, 60) +# buffer~ holds the waveform data; name must match the gen~ buffer declaration +buf_obj = patch.place("buffer~ mytable", verbose=False)[0] + +# === GEN~ OSCILLATOR === +patch.set_position(30, 130) +patch.place("comment === GEN~ OSCILLATOR ===", verbose=False)[0] + +patch.set_position(30, 160) +gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + +# === GAIN CONTROL === +patch.set_position(30, 230) +patch.place("comment === GAIN CONTROL ===", verbose=False)[0] + +patch.set_position(30, 260) +gain = patch.place("*~ 0.3", verbose=False)[0] # attenuate to safe level + +# === OUTPUT === +patch.set_position(30, 330) +patch.place("comment === OUTPUT ===", verbose=False)[0] + +patch.set_position(30, 360) +dac = patch.place("ezdac~", verbose=False)[0] + +# === CONNECTIONS === +# Note: buffer~ has no audio connection — gen~ finds it by name +patch.connect( + [gen_obj.outs[0], gain.ins[0]], # wavetable oscillator → attenuator + [gain.outs[0], dac.ins[0]], # attenuated → left speaker + [gain.outs[0], dac.ins[1]], # attenuated → right speaker + verbose=False, +) + +# === SAVE === +patch.save("gen_wavetable_osc.maxpat") diff --git a/maxpylang/__init__.py b/maxpylang/__init__.py index 516b3d6..4a18014 100644 --- a/maxpylang/__init__.py +++ b/maxpylang/__init__.py @@ -60,10 +60,41 @@ osc = patch.place("cycle~ 440")[0] # string: has arguments dac = patch.place(ezdac_tilde)[0] # stub: no arguments needed +Gen Patchers +------------ + +Create gen~ sub-patchers using ``gen_type`` parameter:: + + # Inner gen patcher + gen_patch = mp.MaxPatch(gen_type="dsp.gen") + inp = gen_patch.place("in 1")[0] + cyc = gen_patch.place("cycle")[0] + outp = gen_patch.place("out 1")[0] + gen_patch.connect([inp.outs[0], cyc.ins[0]], + [cyc.outs[0], outp.ins[0]]) + + # Embed in outer patch + patch = mp.MaxPatch() + gen_obj = patch.place("gen~", gen_patcher=gen_patch)[0] + dac = patch.place("ezdac~")[0] + patch.connect([gen_obj.outs[0], dac.ins[0]]) + patch.save("my_gen_patch") + +Gen type options: + +- ``"dsp.gen"`` -- gen~ (audio-rate) +- ``"jit.gen"`` -- jit.gen (CPU matrix) +- ``"jit.pix"`` -- jit.pix (CPU pixel) +- ``"jit.gl.pix"`` -- jit.gl.pix (GPU pixel) + +Gen operator stubs are in ``maxpylang/objects/gen.py``:: + + from maxpylang.objects import gen + Available Objects ----------------- -All valid object names are in ``maxpylang/objects/`` (stubs by package: ``max.py``, ``msp.py``, ``jit.py``). +All valid object names are in ``maxpylang/objects/`` (stubs by package: ``max.py``, ``msp.py``, ``jit.py``, ``gen.py``). Common objects by category: diff --git a/maxpylang/data/OBJ_INFO/gen/!%.json b/maxpylang/data/OBJ_INFO/gen/!%.json new file mode 100644 index 0000000..a463f45 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/!%.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "!%" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: !%", + "description": "Gen operator '!%' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/!-.json b/maxpylang/data/OBJ_INFO/gen/!-.json new file mode 100644 index 0000000..5c58564 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/!-.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "!-" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: !-", + "description": "Gen operator '!-' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/!.json b/maxpylang/data/OBJ_INFO/gen/!.json new file mode 100644 index 0000000..0e10523 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/!.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "!" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: !", + "description": "Gen operator '!' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/!=.json b/maxpylang/data/OBJ_INFO/gen/!=.json new file mode 100644 index 0000000..dde02b6 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/!=.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "!=" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: !=", + "description": "Gen operator '!=' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/!=p.json b/maxpylang/data/OBJ_INFO/gen/!=p.json new file mode 100644 index 0000000..cb05399 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/!=p.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "!=p" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: !=p", + "description": "Gen operator '!=p' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/!_div_.json b/maxpylang/data/OBJ_INFO/gen/!_div_.json new file mode 100644 index 0000000..2eb80df --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/!_div_.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "!/" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: !/", + "description": "Gen operator '!/' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/%.json b/maxpylang/data/OBJ_INFO/gen/%.json new file mode 100644 index 0000000..22859d4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/%.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "%" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: %", + "description": "Gen operator '%' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/&&.json b/maxpylang/data/OBJ_INFO/gen/&&.json new file mode 100644 index 0000000..e1e0aaf --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/&&.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "&&" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: &&", + "description": "Gen operator '&&' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/*.json b/maxpylang/data/OBJ_INFO/gen/*.json new file mode 100644 index 0000000..a7326c3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/*.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "*" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: *", + "description": "Gen operator '*' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/*=.json b/maxpylang/data/OBJ_INFO/gen/*=.json new file mode 100644 index 0000000..28f708e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/*=.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "*=" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: *=", + "description": "Gen operator '*=' (category: Integrator)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/+.json b/maxpylang/data/OBJ_INFO/gen/+.json new file mode 100644 index 0000000..b0d0ccb --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/+.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "+" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: +", + "description": "Gen operator '+' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/+=.json b/maxpylang/data/OBJ_INFO/gen/+=.json new file mode 100644 index 0000000..8e4fe7a --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/+=.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "+=" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: +=", + "description": "Gen operator '+=' (category: Integrator)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/-.json b/maxpylang/data/OBJ_INFO/gen/-.json new file mode 100644 index 0000000..436e578 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/-.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "-" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: -", + "description": "Gen operator '-' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/<.json b/maxpylang/data/OBJ_INFO/gen/<.json new file mode 100644 index 0000000..bbe0232 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/<.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "<" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: <", + "description": "Gen operator '<' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/<=.json b/maxpylang/data/OBJ_INFO/gen/<=.json new file mode 100644 index 0000000..11d7990 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/<=.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "<=" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: <=", + "description": "Gen operator '<=' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/<=p.json b/maxpylang/data/OBJ_INFO/gen/<=p.json new file mode 100644 index 0000000..f23aac8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/<=p.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "<=p" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: <=p", + "description": "Gen operator '<=p' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/.json b/maxpylang/data/OBJ_INFO/gen/>.json new file mode 100644 index 0000000..ba2ad67 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/>.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": ">" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: >", + "description": "Gen operator '>' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/>=.json b/maxpylang/data/OBJ_INFO/gen/>=.json new file mode 100644 index 0000000..0b53bb4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/>=.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": ">=" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: >=", + "description": "Gen operator '>=' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/>=p.json b/maxpylang/data/OBJ_INFO/gen/>=p.json new file mode 100644 index 0000000..b76b042 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/>=p.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": ">=p" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: >=p", + "description": "Gen operator '>=p' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/>p.json b/maxpylang/data/OBJ_INFO/gen/>p.json new file mode 100644 index 0000000..efad239 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/>p.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": ">p" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: >p", + "description": "Gen operator '>p' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/?.json b/maxpylang/data/OBJ_INFO/gen/?.json new file mode 100644 index 0000000..1c13655 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/?.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "?" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ?", + "description": "Gen operator '?' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/PHI.json b/maxpylang/data/OBJ_INFO/gen/PHI.json new file mode 100644 index 0000000..3fe39be --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/PHI.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "phi" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: phi", + "description": "Gen operator 'phi' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/^^.json b/maxpylang/data/OBJ_INFO/gen/^^.json new file mode 100644 index 0000000..ac0b83f --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/^^.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "^^" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ^^", + "description": "Gen operator '^^' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/_div_.json b/maxpylang/data/OBJ_INFO/gen/_div_.json new file mode 100644 index 0000000..5e0815e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/_div_.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "/" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: /", + "description": "Gen operator '/' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/abs.json b/maxpylang/data/OBJ_INFO/gen/abs.json new file mode 100644 index 0000000..fc73d12 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/abs.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "abs" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: abs", + "description": "Gen operator 'abs' (category: Numeric)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/absdiff.json b/maxpylang/data/OBJ_INFO/gen/absdiff.json new file mode 100644 index 0000000..520f45c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/absdiff.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "absdiff" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: absdiff", + "description": "Gen operator 'absdiff' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/accum.json b/maxpylang/data/OBJ_INFO/gen/accum.json new file mode 100644 index 0000000..00c1daf --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/accum.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "accum" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: accum", + "description": "Gen operator 'accum' (category: Integrator)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/acos.json b/maxpylang/data/OBJ_INFO/gen/acos.json new file mode 100644 index 0000000..3c06d63 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/acos.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "acos" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: acos", + "description": "Gen operator 'acos' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/acosh.json b/maxpylang/data/OBJ_INFO/gen/acosh.json new file mode 100644 index 0000000..4c62dc7 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/acosh.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "acosh" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: acosh", + "description": "Gen operator 'acosh' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/add.json b/maxpylang/data/OBJ_INFO/gen/add.json new file mode 100644 index 0000000..ce6b3d7 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/add.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "add" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: add", + "description": "Gen operator 'add' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/and.json b/maxpylang/data/OBJ_INFO/gen/and.json new file mode 100644 index 0000000..3f88cfc --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/and.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "and" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: and", + "description": "Gen operator 'and' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/asin.json b/maxpylang/data/OBJ_INFO/gen/asin.json new file mode 100644 index 0000000..2c41fd8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/asin.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "asin" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: asin", + "description": "Gen operator 'asin' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/asinh.json b/maxpylang/data/OBJ_INFO/gen/asinh.json new file mode 100644 index 0000000..4ed36d3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/asinh.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "asinh" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: asinh", + "description": "Gen operator 'asinh' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/atan.json b/maxpylang/data/OBJ_INFO/gen/atan.json new file mode 100644 index 0000000..399b602 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/atan.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "atan" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: atan", + "description": "Gen operator 'atan' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/atan2.json b/maxpylang/data/OBJ_INFO/gen/atan2.json new file mode 100644 index 0000000..d551af4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/atan2.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "atan2" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: atan2", + "description": "Gen operator 'atan2' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/atanh.json b/maxpylang/data/OBJ_INFO/gen/atanh.json new file mode 100644 index 0000000..de71afe --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/atanh.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "atanh" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: atanh", + "description": "Gen operator 'atanh' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/atodb.json b/maxpylang/data/OBJ_INFO/gen/atodb.json new file mode 100644 index 0000000..59bb9f8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/atodb.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "atodb" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: atodb", + "description": "Gen operator 'atodb' (category: Convert)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/bool.json b/maxpylang/data/OBJ_INFO/gen/bool.json new file mode 100644 index 0000000..e2f736e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/bool.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "bool" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: bool", + "description": "Gen operator 'bool' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/buffer.json b/maxpylang/data/OBJ_INFO/gen/buffer.json new file mode 100644 index 0000000..4a469a8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/buffer.json @@ -0,0 +1,31 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 2, + "outlettype": [ + "", + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "buffer" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: buffer", + "description": "Gen operator 'buffer' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cartopol.json b/maxpylang/data/OBJ_INFO/gen/cartopol.json new file mode 100644 index 0000000..81ce501 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cartopol.json @@ -0,0 +1,31 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ + "", + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cartopol" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cartopol", + "description": "Gen operator 'cartopol' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ceil.json b/maxpylang/data/OBJ_INFO/gen/ceil.json new file mode 100644 index 0000000..6584622 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ceil.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ceil" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ceil", + "description": "Gen operator 'ceil' (category: Numeric)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cell.json b/maxpylang/data/OBJ_INFO/gen/cell.json new file mode 100644 index 0000000..2811b11 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cell.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cell" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cell", + "description": "Gen operator 'cell' (category: Coordinate)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/change.json b/maxpylang/data/OBJ_INFO/gen/change.json new file mode 100644 index 0000000..c24afb1 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/change.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "change" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: change", + "description": "Gen operator 'change' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/channels.json b/maxpylang/data/OBJ_INFO/gen/channels.json new file mode 100644 index 0000000..6e99a3b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/channels.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "channels" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: channels", + "description": "Gen operator 'channels' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/circle.json b/maxpylang/data/OBJ_INFO/gen/circle.json new file mode 100644 index 0000000..0b36004 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/circle.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "circle" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: circle", + "description": "Gen operator 'circle' (category: Surface)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/clamp.json b/maxpylang/data/OBJ_INFO/gen/clamp.json new file mode 100644 index 0000000..5d8a47c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/clamp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "clamp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: clamp", + "description": "Gen operator 'clamp' (category: Range)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/clip.json b/maxpylang/data/OBJ_INFO/gen/clip.json new file mode 100644 index 0000000..2de21b3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/clip.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "clip" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: clip", + "description": "Gen operator 'clip' (category: Range)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/concat.json b/maxpylang/data/OBJ_INFO/gen/concat.json new file mode 100644 index 0000000..b87cd6c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/concat.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "concat" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: concat", + "description": "Gen operator 'concat' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cone.json b/maxpylang/data/OBJ_INFO/gen/cone.json new file mode 100644 index 0000000..1ec2b37 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cone.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cone" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cone", + "description": "Gen operator 'cone' (category: Surface)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/constant.json b/maxpylang/data/OBJ_INFO/gen/constant.json new file mode 100644 index 0000000..2adda86 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/constant.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "constant" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: constant", + "description": "Gen operator 'constant' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cos.json b/maxpylang/data/OBJ_INFO/gen/cos.json new file mode 100644 index 0000000..c79a527 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cos.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cos" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cos", + "description": "Gen operator 'cos' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cosh.json b/maxpylang/data/OBJ_INFO/gen/cosh.json new file mode 100644 index 0000000..ef1df81 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cosh.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cosh" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cosh", + "description": "Gen operator 'cosh' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/counter.json b/maxpylang/data/OBJ_INFO/gen/counter.json new file mode 100644 index 0000000..f022bc5 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/counter.json @@ -0,0 +1,32 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 3, + "outlettype": [ + "", + "", + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "counter" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: counter", + "description": "Gen operator 'counter' (category: Integrator)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cross.json b/maxpylang/data/OBJ_INFO/gen/cross.json new file mode 100644 index 0000000..e615c4d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cross.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cross" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cross", + "description": "Gen operator 'cross' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cycle.json b/maxpylang/data/OBJ_INFO/gen/cycle.json new file mode 100644 index 0000000..300df1b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cycle.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cycle" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cycle", + "description": "Gen operator 'cycle' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/cylinder.json b/maxpylang/data/OBJ_INFO/gen/cylinder.json new file mode 100644 index 0000000..67caafc --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/cylinder.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "cylinder" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: cylinder", + "description": "Gen operator 'cylinder' (category: Surface)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/data.json b/maxpylang/data/OBJ_INFO/gen/data.json new file mode 100644 index 0000000..ccb5053 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/data.json @@ -0,0 +1,31 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 2, + "outlettype": [ + "", + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "data" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: data", + "description": "Gen operator 'data' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/dbtoa.json b/maxpylang/data/OBJ_INFO/gen/dbtoa.json new file mode 100644 index 0000000..91dbe03 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/dbtoa.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "dbtoa" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: dbtoa", + "description": "Gen operator 'dbtoa' (category: Convert)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/dcblock.json b/maxpylang/data/OBJ_INFO/gen/dcblock.json new file mode 100644 index 0000000..3cadf26 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/dcblock.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "dcblock" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: dcblock", + "description": "Gen operator 'dcblock' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/degrees.json b/maxpylang/data/OBJ_INFO/gen/degrees.json new file mode 100644 index 0000000..157d4e8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/degrees.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "degrees" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: degrees", + "description": "Gen operator 'degrees' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/degtorad.json b/maxpylang/data/OBJ_INFO/gen/degtorad.json new file mode 100644 index 0000000..252c48f --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/degtorad.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "degtorad" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: degtorad", + "description": "Gen operator 'degtorad' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/delay.json b/maxpylang/data/OBJ_INFO/gen/delay.json new file mode 100644 index 0000000..4615857 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/delay.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "delay" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: delay", + "description": "Gen operator 'delay' (category: Feedback)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/delta.json b/maxpylang/data/OBJ_INFO/gen/delta.json new file mode 100644 index 0000000..cda53a6 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/delta.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "delta" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: delta", + "description": "Gen operator 'delta' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/dim.json b/maxpylang/data/OBJ_INFO/gen/dim.json new file mode 100644 index 0000000..b46f012 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/dim.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "dim" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: dim", + "description": "Gen operator 'dim' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/div.json b/maxpylang/data/OBJ_INFO/gen/div.json new file mode 100644 index 0000000..7447df4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/div.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "div" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: div", + "description": "Gen operator 'div' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/dot.json b/maxpylang/data/OBJ_INFO/gen/dot.json new file mode 100644 index 0000000..45167e5 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/dot.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "dot" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: dot", + "description": "Gen operator 'dot' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/e.json b/maxpylang/data/OBJ_INFO/gen/e.json new file mode 100644 index 0000000..388989c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/e.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "e" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: e", + "description": "Gen operator 'e' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/elapsed.json b/maxpylang/data/OBJ_INFO/gen/elapsed.json new file mode 100644 index 0000000..d57001f --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/elapsed.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "elapsed" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: elapsed", + "description": "Gen operator 'elapsed' (category: Global)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/eq.json b/maxpylang/data/OBJ_INFO/gen/eq.json new file mode 100644 index 0000000..a57eac2 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/eq.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "eq" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: eq", + "description": "Gen operator 'eq' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/eqp.json b/maxpylang/data/OBJ_INFO/gen/eqp.json new file mode 100644 index 0000000..ef69265 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/eqp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "eqp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: eqp", + "description": "Gen operator 'eqp' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/exp.json b/maxpylang/data/OBJ_INFO/gen/exp.json new file mode 100644 index 0000000..8b66ea9 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/exp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "exp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: exp", + "description": "Gen operator 'exp' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/exp2.json b/maxpylang/data/OBJ_INFO/gen/exp2.json new file mode 100644 index 0000000..667f28b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/exp2.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "exp2" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: exp2", + "description": "Gen operator 'exp2' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/expr.json b/maxpylang/data/OBJ_INFO/gen/expr.json new file mode 100644 index 0000000..e47368a --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/expr.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "expr" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: expr", + "description": "Gen operator 'expr' (category: Expression)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/f.json b/maxpylang/data/OBJ_INFO/gen/f.json new file mode 100644 index 0000000..7a8afa2 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/f.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "f" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: f", + "description": "Gen operator 'f' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/faceforward.json b/maxpylang/data/OBJ_INFO/gen/faceforward.json new file mode 100644 index 0000000..cf54245 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/faceforward.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "faceforward" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: faceforward", + "description": "Gen operator 'faceforward' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fastcos.json b/maxpylang/data/OBJ_INFO/gen/fastcos.json new file mode 100644 index 0000000..7a83284 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fastcos.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fastcos" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fastcos", + "description": "Gen operator 'fastcos' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fastexp.json b/maxpylang/data/OBJ_INFO/gen/fastexp.json new file mode 100644 index 0000000..49e8cf9 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fastexp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fastexp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fastexp", + "description": "Gen operator 'fastexp' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fastpow.json b/maxpylang/data/OBJ_INFO/gen/fastpow.json new file mode 100644 index 0000000..bbe87d0 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fastpow.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fastpow" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fastpow", + "description": "Gen operator 'fastpow' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fastsin.json b/maxpylang/data/OBJ_INFO/gen/fastsin.json new file mode 100644 index 0000000..51c2cbb --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fastsin.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fastsin" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fastsin", + "description": "Gen operator 'fastsin' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fasttan.json b/maxpylang/data/OBJ_INFO/gen/fasttan.json new file mode 100644 index 0000000..692a1a6 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fasttan.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fasttan" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fasttan", + "description": "Gen operator 'fasttan' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fftfullspect.json b/maxpylang/data/OBJ_INFO/gen/fftfullspect.json new file mode 100644 index 0000000..850b6cb --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fftfullspect.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fftfullspect" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fftfullspect", + "description": "Gen operator 'fftfullspect' (category: Constants)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ffthop.json b/maxpylang/data/OBJ_INFO/gen/ffthop.json new file mode 100644 index 0000000..2bc34c6 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ffthop.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ffthop" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ffthop", + "description": "Gen operator 'ffthop' (category: Constants)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fftinfo.json b/maxpylang/data/OBJ_INFO/gen/fftinfo.json new file mode 100644 index 0000000..be68796 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fftinfo.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fftinfo" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fftinfo", + "description": "Gen operator 'fftinfo' (category: FFT)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fftoffset.json b/maxpylang/data/OBJ_INFO/gen/fftoffset.json new file mode 100644 index 0000000..b8ed891 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fftoffset.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fftoffset" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fftoffset", + "description": "Gen operator 'fftoffset' (category: Constants)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fftsize.json b/maxpylang/data/OBJ_INFO/gen/fftsize.json new file mode 100644 index 0000000..ba58554 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fftsize.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fftsize" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fftsize", + "description": "Gen operator 'fftsize' (category: Constants)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fixdenorm.json b/maxpylang/data/OBJ_INFO/gen/fixdenorm.json new file mode 100644 index 0000000..7f60d9c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fixdenorm.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fixdenorm" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fixdenorm", + "description": "Gen operator 'fixdenorm' (category: DSP)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fixnan.json b/maxpylang/data/OBJ_INFO/gen/fixnan.json new file mode 100644 index 0000000..e777763 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fixnan.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fixnan" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fixnan", + "description": "Gen operator 'fixnan' (category: DSP)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/float.json b/maxpylang/data/OBJ_INFO/gen/float.json new file mode 100644 index 0000000..d2975d5 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/float.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "float" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: float", + "description": "Gen operator 'float' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/floor.json b/maxpylang/data/OBJ_INFO/gen/floor.json new file mode 100644 index 0000000..7045da1 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/floor.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "floor" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: floor", + "description": "Gen operator 'floor' (category: Numeric)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fold.json b/maxpylang/data/OBJ_INFO/gen/fold.json new file mode 100644 index 0000000..aea3a21 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fold.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fold" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fold", + "description": "Gen operator 'fold' (category: Range)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/fract.json b/maxpylang/data/OBJ_INFO/gen/fract.json new file mode 100644 index 0000000..0eb5898 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/fract.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "fract" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: fract", + "description": "Gen operator 'fract' (category: Numeric)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ftom.json b/maxpylang/data/OBJ_INFO/gen/ftom.json new file mode 100644 index 0000000..e2ec463 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ftom.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ftom" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ftom", + "description": "Gen operator 'ftom' (category: Convert)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/gate.json b/maxpylang/data/OBJ_INFO/gen/gate.json new file mode 100644 index 0000000..048dbb2 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/gate.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "gate" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: gate", + "description": "Gen operator 'gate' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/gen.json b/maxpylang/data/OBJ_INFO/gen/gen.json new file mode 100644 index 0000000..dcc19e0 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/gen.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "gen" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: gen", + "description": "Gen operator 'gen' (category: Subpatcher)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/gt.json b/maxpylang/data/OBJ_INFO/gen/gt.json new file mode 100644 index 0000000..f6944bd --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/gt.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "gt" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: gt", + "description": "Gen operator 'gt' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/gte.json b/maxpylang/data/OBJ_INFO/gen/gte.json new file mode 100644 index 0000000..05e9352 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/gte.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "gte" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: gte", + "description": "Gen operator 'gte' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/gtep.json b/maxpylang/data/OBJ_INFO/gen/gtep.json new file mode 100644 index 0000000..81ea1da --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/gtep.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "gtep" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: gtep", + "description": "Gen operator 'gtep' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/gtp.json b/maxpylang/data/OBJ_INFO/gen/gtp.json new file mode 100644 index 0000000..a8d8503 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/gtp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "gtp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: gtp", + "description": "Gen operator 'gtp' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/halfpi.json b/maxpylang/data/OBJ_INFO/gen/halfpi.json new file mode 100644 index 0000000..a56e47c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/halfpi.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "halfpi" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: halfpi", + "description": "Gen operator 'halfpi' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/history.json b/maxpylang/data/OBJ_INFO/gen/history.json new file mode 100644 index 0000000..87b83e8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/history.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "history" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: history", + "description": "Gen operator 'history' (category: Feedback)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/hsl2rgb.json b/maxpylang/data/OBJ_INFO/gen/hsl2rgb.json new file mode 100644 index 0000000..b752a8a --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/hsl2rgb.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "hsl2rgb" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: hsl2rgb", + "description": "Gen operator 'hsl2rgb' (category: Color)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/hypot.json b/maxpylang/data/OBJ_INFO/gen/hypot.json new file mode 100644 index 0000000..3dad0d8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/hypot.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "hypot" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: hypot", + "description": "Gen operator 'hypot' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/i.json b/maxpylang/data/OBJ_INFO/gen/i.json new file mode 100644 index 0000000..c16245a --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/i.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "i" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: i", + "description": "Gen operator 'i' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/in.json b/maxpylang/data/OBJ_INFO/gen/in.json new file mode 100644 index 0000000..21f755b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/in.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "in" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: in", + "description": "Gen operator 'in' (category: Input-output)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/int.json b/maxpylang/data/OBJ_INFO/gen/int.json new file mode 100644 index 0000000..b5e2da9 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/int.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "int" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: int", + "description": "Gen operator 'int' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/interp.json b/maxpylang/data/OBJ_INFO/gen/interp.json new file mode 100644 index 0000000..290cdda --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/interp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 7, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "interp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: interp", + "description": "Gen operator 'interp' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/invpi.json b/maxpylang/data/OBJ_INFO/gen/invpi.json new file mode 100644 index 0000000..5b28b0e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/invpi.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "invpi" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: invpi", + "description": "Gen operator 'invpi' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/isdenorm.json b/maxpylang/data/OBJ_INFO/gen/isdenorm.json new file mode 100644 index 0000000..750e4f9 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/isdenorm.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "isdenorm" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: isdenorm", + "description": "Gen operator 'isdenorm' (category: DSP)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/isnan.json b/maxpylang/data/OBJ_INFO/gen/isnan.json new file mode 100644 index 0000000..f7f97a4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/isnan.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "isnan" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: isnan", + "description": "Gen operator 'isnan' (category: DSP)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/latch.json b/maxpylang/data/OBJ_INFO/gen/latch.json new file mode 100644 index 0000000..442b6dd --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/latch.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "latch" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: latch", + "description": "Gen operator 'latch' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/length.json b/maxpylang/data/OBJ_INFO/gen/length.json new file mode 100644 index 0000000..fd39729 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/length.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "length" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: length", + "description": "Gen operator 'length' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ln.json b/maxpylang/data/OBJ_INFO/gen/ln.json new file mode 100644 index 0000000..b5669a0 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ln.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ln" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ln", + "description": "Gen operator 'ln' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ln10.json b/maxpylang/data/OBJ_INFO/gen/ln10.json new file mode 100644 index 0000000..489d37f --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ln10.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ln10" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ln10", + "description": "Gen operator 'ln10' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ln2.json b/maxpylang/data/OBJ_INFO/gen/ln2.json new file mode 100644 index 0000000..3564772 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ln2.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ln2" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ln2", + "description": "Gen operator 'ln2' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/log.json b/maxpylang/data/OBJ_INFO/gen/log.json new file mode 100644 index 0000000..4940274 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/log.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "log" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: log", + "description": "Gen operator 'log' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/log10.json b/maxpylang/data/OBJ_INFO/gen/log10.json new file mode 100644 index 0000000..29046e8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/log10.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "log10" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: log10", + "description": "Gen operator 'log10' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/log10e.json b/maxpylang/data/OBJ_INFO/gen/log10e.json new file mode 100644 index 0000000..6df139f --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/log10e.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "log10e" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: log10e", + "description": "Gen operator 'log10e' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/log2.json b/maxpylang/data/OBJ_INFO/gen/log2.json new file mode 100644 index 0000000..720fd5a --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/log2.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "log2" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: log2", + "description": "Gen operator 'log2' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/log2e.json b/maxpylang/data/OBJ_INFO/gen/log2e.json new file mode 100644 index 0000000..b807adf --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/log2e.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "log2e" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: log2e", + "description": "Gen operator 'log2e' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/lookup.json b/maxpylang/data/OBJ_INFO/gen/lookup.json new file mode 100644 index 0000000..34f1584 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/lookup.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "lookup" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: lookup", + "description": "Gen operator 'lookup' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/lt.json b/maxpylang/data/OBJ_INFO/gen/lt.json new file mode 100644 index 0000000..7e2334c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/lt.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "lt" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: lt", + "description": "Gen operator 'lt' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/lte.json b/maxpylang/data/OBJ_INFO/gen/lte.json new file mode 100644 index 0000000..88d6057 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/lte.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "lte" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: lte", + "description": "Gen operator 'lte' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ltep.json b/maxpylang/data/OBJ_INFO/gen/ltep.json new file mode 100644 index 0000000..6de9a15 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ltep.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ltep" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ltep", + "description": "Gen operator 'ltep' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/ltp.json b/maxpylang/data/OBJ_INFO/gen/ltp.json new file mode 100644 index 0000000..0532a43 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/ltp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "ltp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ltp", + "description": "Gen operator 'ltp' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/max.json b/maxpylang/data/OBJ_INFO/gen/max.json new file mode 100644 index 0000000..e4f300f --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/max.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "max" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: max", + "description": "Gen operator 'max' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/maximum.json b/maxpylang/data/OBJ_INFO/gen/maximum.json new file mode 100644 index 0000000..eadf5cd --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/maximum.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "maximum" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: maximum", + "description": "Gen operator 'maximum' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mc_channel.json b/maxpylang/data/OBJ_INFO/gen/mc_channel.json new file mode 100644 index 0000000..ade0eb2 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mc_channel.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mc_channel" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mc_channel", + "description": "Gen operator 'mc_channel' (category: Global)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mc_channelcount.json b/maxpylang/data/OBJ_INFO/gen/mc_channelcount.json new file mode 100644 index 0000000..33837df --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mc_channelcount.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mc_channelcount" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mc_channelcount", + "description": "Gen operator 'mc_channelcount' (category: Global)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/min.json b/maxpylang/data/OBJ_INFO/gen/min.json new file mode 100644 index 0000000..eed5fda --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/min.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "min" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: min", + "description": "Gen operator 'min' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/minimum.json b/maxpylang/data/OBJ_INFO/gen/minimum.json new file mode 100644 index 0000000..93a84bc --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/minimum.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "minimum" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: minimum", + "description": "Gen operator 'minimum' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mix.json b/maxpylang/data/OBJ_INFO/gen/mix.json new file mode 100644 index 0000000..5c9fed5 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mix.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mix" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mix", + "description": "Gen operator 'mix' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mod.json b/maxpylang/data/OBJ_INFO/gen/mod.json new file mode 100644 index 0000000..247eda1 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mod.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mod" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mod", + "description": "Gen operator 'mod' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mstosamps.json b/maxpylang/data/OBJ_INFO/gen/mstosamps.json new file mode 100644 index 0000000..59de8f2 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mstosamps.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mstosamps" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mstosamps", + "description": "Gen operator 'mstosamps' (category: Convert)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mtof.json b/maxpylang/data/OBJ_INFO/gen/mtof.json new file mode 100644 index 0000000..4c0bda0 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mtof.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mtof" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mtof", + "description": "Gen operator 'mtof' (category: Convert)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mul.json b/maxpylang/data/OBJ_INFO/gen/mul.json new file mode 100644 index 0000000..e2a8862 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mul.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mul" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mul", + "description": "Gen operator 'mul' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/mulequals.json b/maxpylang/data/OBJ_INFO/gen/mulequals.json new file mode 100644 index 0000000..de202a8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/mulequals.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "mulequals" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: mulequals", + "description": "Gen operator 'mulequals' (category: Integrator)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/nearest.json b/maxpylang/data/OBJ_INFO/gen/nearest.json new file mode 100644 index 0000000..764db35 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/nearest.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "nearest" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: nearest", + "description": "Gen operator 'nearest' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/nearestpix.json b/maxpylang/data/OBJ_INFO/gen/nearestpix.json new file mode 100644 index 0000000..cdae2f1 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/nearestpix.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "nearestpix" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: nearestpix", + "description": "Gen operator 'nearestpix' (category: Sampling)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/neg.json b/maxpylang/data/OBJ_INFO/gen/neg.json new file mode 100644 index 0000000..958e70d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/neg.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "neg" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: neg", + "description": "Gen operator 'neg' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/neq.json b/maxpylang/data/OBJ_INFO/gen/neq.json new file mode 100644 index 0000000..7882ea5 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/neq.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "neq" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: neq", + "description": "Gen operator 'neq' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/neqp.json b/maxpylang/data/OBJ_INFO/gen/neqp.json new file mode 100644 index 0000000..5af3d24 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/neqp.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "neqp" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: neqp", + "description": "Gen operator 'neqp' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/noise.json b/maxpylang/data/OBJ_INFO/gen/noise.json new file mode 100644 index 0000000..239786d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/noise.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "noise" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: noise", + "description": "Gen operator 'noise' (category: Waveform)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/norm.json b/maxpylang/data/OBJ_INFO/gen/norm.json new file mode 100644 index 0000000..bbb285d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/norm.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "norm" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: norm", + "description": "Gen operator 'norm' (category: Coordinate)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/normalize.json b/maxpylang/data/OBJ_INFO/gen/normalize.json new file mode 100644 index 0000000..f4ba27c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/normalize.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "normalize" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: normalize", + "description": "Gen operator 'normalize' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/not.json b/maxpylang/data/OBJ_INFO/gen/not.json new file mode 100644 index 0000000..2262551 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/not.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "not" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: not", + "description": "Gen operator 'not' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/or.json b/maxpylang/data/OBJ_INFO/gen/or.json new file mode 100644 index 0000000..55d4af7 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/or.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "or" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: or", + "description": "Gen operator 'or' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/out.json b/maxpylang/data/OBJ_INFO/gen/out.json new file mode 100644 index 0000000..43ea66e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/out.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "out" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: out", + "description": "Gen operator 'out' (category: Input-output)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/param.json b/maxpylang/data/OBJ_INFO/gen/param.json new file mode 100644 index 0000000..898e22e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/param.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "param" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: param", + "description": "Gen operator 'param' (category: Declare)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/pass.json b/maxpylang/data/OBJ_INFO/gen/pass.json new file mode 100644 index 0000000..dacf273 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/pass.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "pass" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: pass", + "description": "Gen operator 'pass' (category: Ignore)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/peek.json b/maxpylang/data/OBJ_INFO/gen/peek.json new file mode 100644 index 0000000..945c1b3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/peek.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "peek" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: peek", + "description": "Gen operator 'peek' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/phasewrap.json b/maxpylang/data/OBJ_INFO/gen/phasewrap.json new file mode 100644 index 0000000..094e15f --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/phasewrap.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "phasewrap" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: phasewrap", + "description": "Gen operator 'phasewrap' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/phasor.json b/maxpylang/data/OBJ_INFO/gen/phasor.json new file mode 100644 index 0000000..ebaafcc --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/phasor.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "phasor" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: phasor", + "description": "Gen operator 'phasor' (category: Waveform)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/pi.json b/maxpylang/data/OBJ_INFO/gen/pi.json new file mode 100644 index 0000000..565fdb3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/pi.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "pi" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: pi", + "description": "Gen operator 'pi' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/plane.json b/maxpylang/data/OBJ_INFO/gen/plane.json new file mode 100644 index 0000000..8761470 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/plane.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "plane" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: plane", + "description": "Gen operator 'plane' (category: Surface)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/plusequals.json b/maxpylang/data/OBJ_INFO/gen/plusequals.json new file mode 100644 index 0000000..3f3ddd7 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/plusequals.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "plusequals" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: plusequals", + "description": "Gen operator 'plusequals' (category: Integrator)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/poke.json b/maxpylang/data/OBJ_INFO/gen/poke.json new file mode 100644 index 0000000..ef8e9ba --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/poke.json @@ -0,0 +1,28 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 0, + "outlettype": [], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "poke" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: poke", + "description": "Gen operator 'poke' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/poltocar.json b/maxpylang/data/OBJ_INFO/gen/poltocar.json new file mode 100644 index 0000000..4f0b3cd --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/poltocar.json @@ -0,0 +1,31 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 2, + "outlettype": [ + "", + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "poltocar" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: poltocar", + "description": "Gen operator 'poltocar' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/pow.json b/maxpylang/data/OBJ_INFO/gen/pow.json new file mode 100644 index 0000000..d7d31f4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/pow.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "pow" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: pow", + "description": "Gen operator 'pow' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/qconj.json b/maxpylang/data/OBJ_INFO/gen/qconj.json new file mode 100644 index 0000000..d1b8e1e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/qconj.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "qconj" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: qconj", + "description": "Gen operator 'qconj' (category: Quaternion)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/qmul.json b/maxpylang/data/OBJ_INFO/gen/qmul.json new file mode 100644 index 0000000..a844028 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/qmul.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "qmul" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: qmul", + "description": "Gen operator 'qmul' (category: Quaternion)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/qrot.json b/maxpylang/data/OBJ_INFO/gen/qrot.json new file mode 100644 index 0000000..ba0d188 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/qrot.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "qrot" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: qrot", + "description": "Gen operator 'qrot' (category: Quaternion)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/r.json b/maxpylang/data/OBJ_INFO/gen/r.json new file mode 100644 index 0000000..be66b21 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/r.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "r" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: r", + "description": "Gen operator 'r' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/radians.json b/maxpylang/data/OBJ_INFO/gen/radians.json new file mode 100644 index 0000000..87c0bc8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/radians.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "radians" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: radians", + "description": "Gen operator 'radians' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/radtodeg.json b/maxpylang/data/OBJ_INFO/gen/radtodeg.json new file mode 100644 index 0000000..3104e89 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/radtodeg.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "radtodeg" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: radtodeg", + "description": "Gen operator 'radtodeg' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/rate.json b/maxpylang/data/OBJ_INFO/gen/rate.json new file mode 100644 index 0000000..6c4d39b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/rate.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "rate" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: rate", + "description": "Gen operator 'rate' (category: Waveform)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/rdiv.json b/maxpylang/data/OBJ_INFO/gen/rdiv.json new file mode 100644 index 0000000..a70f26d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/rdiv.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "rdiv" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: rdiv", + "description": "Gen operator 'rdiv' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/receive.json b/maxpylang/data/OBJ_INFO/gen/receive.json new file mode 100644 index 0000000..a4baa6d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/receive.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "receive" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: receive", + "description": "Gen operator 'receive' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/reflect.json b/maxpylang/data/OBJ_INFO/gen/reflect.json new file mode 100644 index 0000000..6a2273a --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/reflect.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "reflect" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: reflect", + "description": "Gen operator 'reflect' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/refract.json b/maxpylang/data/OBJ_INFO/gen/refract.json new file mode 100644 index 0000000..cdc43e3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/refract.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "refract" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: refract", + "description": "Gen operator 'refract' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/rgb2hsl.json b/maxpylang/data/OBJ_INFO/gen/rgb2hsl.json new file mode 100644 index 0000000..7db1d17 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/rgb2hsl.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "rgb2hsl" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: rgb2hsl", + "description": "Gen operator 'rgb2hsl' (category: Color)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/rmod.json b/maxpylang/data/OBJ_INFO/gen/rmod.json new file mode 100644 index 0000000..438fc3d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/rmod.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "rmod" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: rmod", + "description": "Gen operator 'rmod' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/rotor.json b/maxpylang/data/OBJ_INFO/gen/rotor.json new file mode 100644 index 0000000..bf5cfca --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/rotor.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "rotor" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: rotor", + "description": "Gen operator 'rotor' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/round.json b/maxpylang/data/OBJ_INFO/gen/round.json new file mode 100644 index 0000000..1521a6c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/round.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "round" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: round", + "description": "Gen operator 'round' (category: Numeric)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/rsub.json b/maxpylang/data/OBJ_INFO/gen/rsub.json new file mode 100644 index 0000000..863be72 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/rsub.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "rsub" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: rsub", + "description": "Gen operator 'rsub' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/s.json b/maxpylang/data/OBJ_INFO/gen/s.json new file mode 100644 index 0000000..cec3720 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/s.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "s" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: s", + "description": "Gen operator 's' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sah.json b/maxpylang/data/OBJ_INFO/gen/sah.json new file mode 100644 index 0000000..c06ea02 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sah.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sah" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sah", + "description": "Gen operator 'sah' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sample.json b/maxpylang/data/OBJ_INFO/gen/sample.json new file mode 100644 index 0000000..bffd28e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sample.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sample" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sample", + "description": "Gen operator 'sample' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/samplepix.json b/maxpylang/data/OBJ_INFO/gen/samplepix.json new file mode 100644 index 0000000..c232857 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/samplepix.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "samplepix" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: samplepix", + "description": "Gen operator 'samplepix' (category: Sampling)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/samplerate.json b/maxpylang/data/OBJ_INFO/gen/samplerate.json new file mode 100644 index 0000000..4d945c3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/samplerate.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "samplerate" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: samplerate", + "description": "Gen operator 'samplerate' (category: Constants)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sampstoms.json b/maxpylang/data/OBJ_INFO/gen/sampstoms.json new file mode 100644 index 0000000..4128f4d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sampstoms.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sampstoms" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sampstoms", + "description": "Gen operator 'sampstoms' (category: Convert)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/scale.json b/maxpylang/data/OBJ_INFO/gen/scale.json new file mode 100644 index 0000000..19d2794 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/scale.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 6, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "scale" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: scale", + "description": "Gen operator 'scale' (category: Range)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/selector.json b/maxpylang/data/OBJ_INFO/gen/selector.json new file mode 100644 index 0000000..ca49c6b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/selector.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "selector" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: selector", + "description": "Gen operator 'selector' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/send.json b/maxpylang/data/OBJ_INFO/gen/send.json new file mode 100644 index 0000000..8f8f3c5 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/send.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "send" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: send", + "description": "Gen operator 'send' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/setparam.json b/maxpylang/data/OBJ_INFO/gen/setparam.json new file mode 100644 index 0000000..cbe1198 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/setparam.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 0, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "setparam" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: setparam", + "description": "Gen operator 'setparam' (category: Subpatcher)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sign.json b/maxpylang/data/OBJ_INFO/gen/sign.json new file mode 100644 index 0000000..c76b9e3 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sign.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sign" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sign", + "description": "Gen operator 'sign' (category: Numeric)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sin.json b/maxpylang/data/OBJ_INFO/gen/sin.json new file mode 100644 index 0000000..1ccb8e7 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sin.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sin" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sin", + "description": "Gen operator 'sin' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sinh.json b/maxpylang/data/OBJ_INFO/gen/sinh.json new file mode 100644 index 0000000..2c1d3ca --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sinh.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sinh" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sinh", + "description": "Gen operator 'sinh' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/slide.json b/maxpylang/data/OBJ_INFO/gen/slide.json new file mode 100644 index 0000000..8d535c6 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/slide.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "slide" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: slide", + "description": "Gen operator 'slide' (category: Filter)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/smoothstep.json b/maxpylang/data/OBJ_INFO/gen/smoothstep.json new file mode 100644 index 0000000..537c11c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/smoothstep.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "smoothstep" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: smoothstep", + "description": "Gen operator 'smoothstep' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/snorm.json b/maxpylang/data/OBJ_INFO/gen/snorm.json new file mode 100644 index 0000000..4d23749 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/snorm.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "snorm" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: snorm", + "description": "Gen operator 'snorm' (category: Coordinate)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sphere.json b/maxpylang/data/OBJ_INFO/gen/sphere.json new file mode 100644 index 0000000..a1b479c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sphere.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sphere" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sphere", + "description": "Gen operator 'sphere' (category: Surface)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/splat.json b/maxpylang/data/OBJ_INFO/gen/splat.json new file mode 100644 index 0000000..ed23bc4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/splat.json @@ -0,0 +1,28 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 0, + "outlettype": [], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "splat" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: splat", + "description": "Gen operator 'splat' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sqrt.json b/maxpylang/data/OBJ_INFO/gen/sqrt.json new file mode 100644 index 0000000..aa5b817 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sqrt.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sqrt" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sqrt", + "description": "Gen operator 'sqrt' (category: Powers)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sqrt1_2.json b/maxpylang/data/OBJ_INFO/gen/sqrt1_2.json new file mode 100644 index 0000000..e3a10e4 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sqrt1_2.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sqrt1_2" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sqrt1_2", + "description": "Gen operator 'sqrt1_2' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sqrt2.json b/maxpylang/data/OBJ_INFO/gen/sqrt2.json new file mode 100644 index 0000000..30f7c9b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sqrt2.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sqrt2" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sqrt2", + "description": "Gen operator 'sqrt2' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/step.json b/maxpylang/data/OBJ_INFO/gen/step.json new file mode 100644 index 0000000..2df86f0 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/step.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "step" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: step", + "description": "Gen operator 'step' (category: Comparison)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/sub.json b/maxpylang/data/OBJ_INFO/gen/sub.json new file mode 100644 index 0000000..d34bb7b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/sub.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "sub" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: sub", + "description": "Gen operator 'sub' (category: Math)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/switch.json b/maxpylang/data/OBJ_INFO/gen/switch.json new file mode 100644 index 0000000..eb1affa --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/switch.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "switch" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: switch", + "description": "Gen operator 'switch' (category: Route)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/swiz.json b/maxpylang/data/OBJ_INFO/gen/swiz.json new file mode 100644 index 0000000..5ec7e9a --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/swiz.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "swiz" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: swiz", + "description": "Gen operator 'swiz' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/t60.json b/maxpylang/data/OBJ_INFO/gen/t60.json new file mode 100644 index 0000000..d795f50 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/t60.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "t60" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: t60", + "description": "Gen operator 't60' (category: DSP)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/t60time.json b/maxpylang/data/OBJ_INFO/gen/t60time.json new file mode 100644 index 0000000..adec8c6 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/t60time.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "t60time" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: t60time", + "description": "Gen operator 't60time' (category: DSP)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/tan.json b/maxpylang/data/OBJ_INFO/gen/tan.json new file mode 100644 index 0000000..bf5bcb8 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/tan.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "tan" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: tan", + "description": "Gen operator 'tan' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/tanh.json b/maxpylang/data/OBJ_INFO/gen/tanh.json new file mode 100644 index 0000000..1974d0d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/tanh.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "tanh" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: tanh", + "description": "Gen operator 'tanh' (category: Trigonometry)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/torus.json b/maxpylang/data/OBJ_INFO/gen/torus.json new file mode 100644 index 0000000..6bb535b --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/torus.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "torus" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: torus", + "description": "Gen operator 'torus' (category: Surface)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/train.json b/maxpylang/data/OBJ_INFO/gen/train.json new file mode 100644 index 0000000..d740b13 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/train.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "train" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: train", + "description": "Gen operator 'train' (category: Waveform)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/triangle.json b/maxpylang/data/OBJ_INFO/gen/triangle.json new file mode 100644 index 0000000..8464b2d --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/triangle.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "triangle" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: triangle", + "description": "Gen operator 'triangle' (category: Waveform)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/trunc.json b/maxpylang/data/OBJ_INFO/gen/trunc.json new file mode 100644 index 0000000..fc6c79e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/trunc.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "trunc" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: trunc", + "description": "Gen operator 'trunc' (category: Numeric)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/twopi.json b/maxpylang/data/OBJ_INFO/gen/twopi.json new file mode 100644 index 0000000..8d57fb5 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/twopi.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "twopi" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: twopi", + "description": "Gen operator 'twopi' (category: Constant)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/vec.json b/maxpylang/data/OBJ_INFO/gen/vec.json new file mode 100644 index 0000000..7d2dc82 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/vec.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "vec" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: vec", + "description": "Gen operator 'vec' (category: Vector)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/vectorsize.json b/maxpylang/data/OBJ_INFO/gen/vectorsize.json new file mode 100644 index 0000000..3183d1e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/vectorsize.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "vectorsize" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: vectorsize", + "description": "Gen operator 'vectorsize' (category: Constants)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/voice.json b/maxpylang/data/OBJ_INFO/gen/voice.json new file mode 100644 index 0000000..1075906 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/voice.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "voice" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: voice", + "description": "Gen operator 'voice' (category: Global)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/voicecount.json b/maxpylang/data/OBJ_INFO/gen/voicecount.json new file mode 100644 index 0000000..ea95231 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/voicecount.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 0, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "voicecount" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: voicecount", + "description": "Gen operator 'voicecount' (category: Global)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/wave.json b/maxpylang/data/OBJ_INFO/gen/wave.json new file mode 100644 index 0000000..a520da9 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/wave.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 4, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "wave" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: wave", + "description": "Gen operator 'wave' (category: Buffer)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/wrap.json b/maxpylang/data/OBJ_INFO/gen/wrap.json new file mode 100644 index 0000000..ba9154c --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/wrap.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 3, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "wrap" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: wrap", + "description": "Gen operator 'wrap' (category: Range)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/xor.json b/maxpylang/data/OBJ_INFO/gen/xor.json new file mode 100644 index 0000000..6bbdf1e --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/xor.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "xor" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: xor", + "description": "Gen operator 'xor' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/OBJ_INFO/gen/||.json b/maxpylang/data/OBJ_INFO/gen/||.json new file mode 100644 index 0000000..2a04972 --- /dev/null +++ b/maxpylang/data/OBJ_INFO/gen/||.json @@ -0,0 +1,30 @@ +{ + "default": { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 2, + "numoutlets": 1, + "outlettype": [ + "" + ], + "patching_rect": [ + 0.0, + 0.0, + 60.0, + 22.0 + ], + "text": "||" + } + }, + "args": { + "required": [], + "optional": [] + }, + "attribs": [], + "in/out": {}, + "doc": { + "digest": "Gen operator: ||", + "description": "Gen operator '||' (category: Logic)" + } +} \ No newline at end of file diff --git a/maxpylang/data/PATCH_TEMPLATES/gen_template.json b/maxpylang/data/PATCH_TEMPLATES/gen_template.json new file mode 100644 index 0000000..6bb0644 --- /dev/null +++ b/maxpylang/data/PATCH_TEMPLATES/gen_template.json @@ -0,0 +1,43 @@ +{ + "patcher": { + "fileversion": 1, + "appversion": { + "major": 8, + "minor": 1, + "revision": 11, + "architecture": "x64", + "modernui": 1 + }, + "classnamespace": "dsp.gen", + "rect": [0.0, 0.0, 600.0, 450.0], + "bglocked": 0, + "openinpresentation": 0, + "default_fontsize": 12.0, + "default_fontface": 0, + "default_fontname": "Arial", + "gridonopen": 1, + "gridsize": [15.0, 15.0], + "gridsnaponopen": 1, + "objectsnaponopen": 1, + "statusbarvisible": 2, + "toolbarvisible": 1, + "lefttoolbarpinned": 0, + "toptoolbarpinned": 0, + "righttoolbarpinned": 0, + "bottomtoolbarpinned": 0, + "toolbars_unpinned_last_save": 0, + "tallnewobj": 0, + "boxanimatetime": 200, + "enablehscroll": 1, + "enablevscroll": 1, + "devicewidth": 0.0, + "description": "", + "digest": "", + "tags": "", + "style": "", + "subpatcher_template": "", + "assistshowspatchername": 0, + "boxes": [], + "lines": [] + } +} diff --git a/maxpylang/maxpatch.py b/maxpylang/maxpatch.py index ce5ed31..5a4934f 100644 --- a/maxpylang/maxpatch.py +++ b/maxpylang/maxpatch.py @@ -33,7 +33,7 @@ class MaxPatch: patch_templates_path, ) #: Path to the patch templates folder MaxPy/maxpy/data/PATCH_TEMPLATES. - def __init__(self, template=None, load_file=None, reorder=True, verbose=True): + def __init__(self, template=None, load_file=None, reorder=True, verbose=True, gen_type=None): """ Constructor method. """ @@ -44,6 +44,7 @@ def __init__(self, template=None, load_file=None, reorder=True, verbose=True): self._patcher_dict = {} #: the patch's JSON data self._curr_position = [0.0, 0.0] #: 'cursor' position at which to place objects self._filename = "default.maxpat" #: the file where the patch is saved + self._gen_type = gen_type # load existing maxpatch if load_file: @@ -51,11 +52,19 @@ def __init__(self, template=None, load_file=None, reorder=True, verbose=True): # or, make copy from template else: - if template is None: - template = os.path.join( - self.patch_templates_path, "empty_template.json" - ) - self.load_template(template, verbose=verbose) + if gen_type is not None: + if template is None: + template = os.path.join( + self.patch_templates_path, "gen_template.json" + ) + self.load_template(template, verbose=verbose) + self._patcher_dict["patcher"]["classnamespace"] = gen_type + else: + if template is None: + template = os.path.join( + self.patch_templates_path, "empty_template.json" + ) + self.load_template(template, verbose=verbose) return diff --git a/maxpylang/objects/__init__.py b/maxpylang/objects/__init__.py index dbe8887..4863ade 100644 --- a/maxpylang/objects/__init__.py +++ b/maxpylang/objects/__init__.py @@ -17,3 +17,7 @@ from .msp import * except ImportError: pass + try: + from .gen import * + except ImportError: + pass diff --git a/maxpylang/objects/gen.py b/maxpylang/objects/gen.py new file mode 100644 index 0000000..7f41141 --- /dev/null +++ b/maxpylang/objects/gen.py @@ -0,0 +1,1698 @@ +"""MaxObject stubs for gen operators. Auto-generated by gen_scraper.""" +import os as _os +import sys as _sys +from maxpylang.maxobject import MaxObject + +__all__ = [ + 'DEGTORAD', + 'E', + 'FFTFULLSPECT', + 'FFTHOP', + 'FFTOFFSET', + 'FFTSIZE', + 'HALFPI', + 'INVPI', + 'LN10', + 'LN2', + 'LOG10E', + 'LOG2E', + 'PHI', + 'PI', + 'Param', + 'RADTODEG', + 'SAMPLERATE', + 'SQRT1_2', + 'SQRT2', + 'TWOPI', + 'VECTORSIZE', + 'abs_', + 'absdiff', + 'accum', + 'acos', + 'acosh', + 'add', + 'add_op', + 'and_', + 'and_op', + 'asin', + 'asinh', + 'atan', + 'atan2', + 'atanh', + 'atodb', + 'bool_', + 'buffer', + 'cartopol', + 'ceil', + 'cell', + 'change', + 'channels', + 'circle', + 'clamp', + 'clip', + 'concat', + 'cone', + 'constant', + 'cos', + 'cosh', + 'counter', + 'cross', + 'cycle', + 'cylinder', + 'data', + 'dbtoa', + 'dcblock', + 'degrees', + 'degtorad', + 'delay', + 'delta', + 'dim', + 'div', + 'div_op', + 'dot', + 'e', + 'elapsed', + 'eq', + 'eq_op', + 'eqp', + 'eqp_op', + 'exp', + 'exp2', + 'expr', + 'f', + 'faceforward', + 'fastcos', + 'fastexp', + 'fastpow', + 'fastsin', + 'fasttan', + 'fftfullspect', + 'ffthop', + 'fftinfo', + 'fftoffset', + 'fftsize', + 'fixdenorm', + 'fixnan', + 'float_', + 'floor', + 'fold', + 'fract', + 'ftom', + 'gate', + 'gen', + 'gt', + 'gt_op', + 'gte', + 'gte_op', + 'gtep', + 'gtep_op', + 'gtp', + 'gtp_op', + 'halfpi', + 'history', + 'hsl2rgb', + 'hypot', + 'i', + 'in_', + 'int_', + 'interp', + 'invpi', + 'isdenorm', + 'isnan', + 'latch', + 'length', + 'ln', + 'ln10', + 'ln2', + 'log', + 'log10', + 'log10e', + 'log2', + 'log2e', + 'lookup', + 'lt', + 'lt_op', + 'lte', + 'lte_op', + 'ltep', + 'ltep_op', + 'ltp', + 'ltp_op', + 'max_', + 'maximum', + 'mc_channel', + 'mc_channelcount', + 'min_', + 'minimum', + 'mix', + 'mod', + 'mod_op', + 'mstosamps', + 'mtof', + 'mul', + 'mul_op', + 'mulequals', + 'mulequals_op', + 'nearest', + 'nearestpix', + 'neg', + 'neq', + 'neq_op', + 'neqp', + 'neqp_op', + 'noise', + 'norm', + 'normalize', + 'not_', + 'not_op', + 'or_', + 'or_op', + 'out', + 'param', + 'pass_', + 'peek', + 'phasewrap', + 'phasor', + 'phi', + 'pi', + 'plane', + 'plusequals', + 'plusequals_op', + 'poke', + 'poltocar', + 'pow_', + 'qconj', + 'qmul', + 'qrot', + 'r', + 'radians', + 'radtodeg', + 'rate', + 'rdiv', + 'rdiv_op', + 'receive', + 'reflect', + 'refract', + 'rgb2hsl', + 'rmod', + 'rmod_op', + 'rotor', + 'round_', + 'rsub', + 'rsub_op', + 's', + 'sah', + 'sample', + 'samplepix', + 'samplerate', + 'sampstoms', + 'scale', + 'selector', + 'send', + 'setparam', + 'sign', + 'sin', + 'sinh', + 'slide', + 'smoothstep', + 'snorm', + 'sphere', + 'splat', + 'sqrt', + 'sqrt1_2', + 'sqrt2', + 'step', + 'sub', + 'sub_op', + 'switch', + 'switch_op', + 'swiz', + 't60', + 't60time', + 'tan', + 'tanh', + 'torus', + 'train', + 'triangle', + 'trunc', + 'twopi', + 'vec', + 'vectorsize', + 'voice', + 'voicecount', + 'wave', + 'wrap', + 'xor', + 'xor_op', +] + +_NAMES = { + 'DEGTORAD': 'DEGTORAD', + 'E': 'E', + 'FFTFULLSPECT': 'FFTFULLSPECT', + 'FFTHOP': 'FFTHOP', + 'FFTOFFSET': 'FFTOFFSET', + 'FFTSIZE': 'FFTSIZE', + 'HALFPI': 'HALFPI', + 'INVPI': 'INVPI', + 'LN10': 'LN10', + 'LN2': 'LN2', + 'LOG10E': 'LOG10E', + 'LOG2E': 'LOG2E', + 'PHI': 'PHI', + 'PI': 'PI', + 'Param': 'Param', + 'RADTODEG': 'RADTODEG', + 'SAMPLERATE': 'SAMPLERATE', + 'SQRT1_2': 'SQRT1_2', + 'SQRT2': 'SQRT2', + 'TWOPI': 'TWOPI', + 'VECTORSIZE': 'VECTORSIZE', + 'abs_': 'abs', + 'absdiff': 'absdiff', + 'accum': 'accum', + 'acos': 'acos', + 'acosh': 'acosh', + 'add': 'add', + 'add_op': '+', + 'and_': 'and', + 'and_op': '&&', + 'asin': 'asin', + 'asinh': 'asinh', + 'atan': 'atan', + 'atan2': 'atan2', + 'atanh': 'atanh', + 'atodb': 'atodb', + 'bool_': 'bool', + 'buffer': 'buffer', + 'cartopol': 'cartopol', + 'ceil': 'ceil', + 'cell': 'cell', + 'change': 'change', + 'channels': 'channels', + 'circle': 'circle', + 'clamp': 'clamp', + 'clip': 'clip', + 'concat': 'concat', + 'cone': 'cone', + 'constant': 'constant', + 'cos': 'cos', + 'cosh': 'cosh', + 'counter': 'counter', + 'cross': 'cross', + 'cycle': 'cycle', + 'cylinder': 'cylinder', + 'data': 'data', + 'dbtoa': 'dbtoa', + 'dcblock': 'dcblock', + 'degrees': 'degrees', + 'degtorad': 'degtorad', + 'delay': 'delay', + 'delta': 'delta', + 'dim': 'dim', + 'div': 'div', + 'div_op': '/', + 'dot': 'dot', + 'e': 'e', + 'elapsed': 'elapsed', + 'eq': 'eq', + 'eq_op': '==', + 'eqp': 'eqp', + 'eqp_op': '==p', + 'exp': 'exp', + 'exp2': 'exp2', + 'expr': 'expr', + 'f': 'f', + 'faceforward': 'faceforward', + 'fastcos': 'fastcos', + 'fastexp': 'fastexp', + 'fastpow': 'fastpow', + 'fastsin': 'fastsin', + 'fasttan': 'fasttan', + 'fftfullspect': 'fftfullspect', + 'ffthop': 'ffthop', + 'fftinfo': 'fftinfo', + 'fftoffset': 'fftoffset', + 'fftsize': 'fftsize', + 'fixdenorm': 'fixdenorm', + 'fixnan': 'fixnan', + 'float_': 'float', + 'floor': 'floor', + 'fold': 'fold', + 'fract': 'fract', + 'ftom': 'ftom', + 'gate': 'gate', + 'gen': 'gen', + 'gt': 'gt', + 'gt_op': '>', + 'gte': 'gte', + 'gte_op': '>=', + 'gtep': 'gtep', + 'gtep_op': '>=p', + 'gtp': 'gtp', + 'gtp_op': '>p', + 'halfpi': 'halfpi', + 'history': 'history', + 'hsl2rgb': 'hsl2rgb', + 'hypot': 'hypot', + 'i': 'i', + 'in_': 'in', + 'int_': 'int', + 'interp': 'interp', + 'invpi': 'invpi', + 'isdenorm': 'isdenorm', + 'isnan': 'isnan', + 'latch': 'latch', + 'length': 'length', + 'ln': 'ln', + 'ln10': 'ln10', + 'ln2': 'ln2', + 'log': 'log', + 'log10': 'log10', + 'log10e': 'log10e', + 'log2': 'log2', + 'log2e': 'log2e', + 'lookup': 'lookup', + 'lt': 'lt', + 'lt_op': '<', + 'lte': 'lte', + 'lte_op': '<=', + 'ltep': 'ltep', + 'ltep_op': '<=p', + 'ltp': 'ltp', + 'ltp_op': ' - Gen operator (Comparison) +""" +gt_op = MaxObject('>') + +""" +gte - Gen operator (Comparison) +""" +gte = MaxObject('gte') + +""" +>= - Gen operator (Comparison) +""" +gte_op = MaxObject('>=') + +""" +gtep - Gen operator (Comparison) +""" +gtep = MaxObject('gtep') + +""" +>=p - Gen operator (Comparison) +""" +gtep_op = MaxObject('>=p') + +""" +gtp - Gen operator (Comparison) +""" +gtp = MaxObject('gtp') + +""" +>p - Gen operator (Comparison) +""" +gtp_op = MaxObject('>p') + +""" +halfpi - Gen operator (Constant) +""" +halfpi = MaxObject('halfpi') + +""" +history - Gen operator (Feedback) +""" +history = MaxObject('history') + +""" +hsl2rgb - Gen operator (Color) +""" +hsl2rgb = MaxObject('hsl2rgb') + +""" +hypot - Gen operator (Trigonometry) +""" +hypot = MaxObject('hypot') + +""" +i - Gen operator (Constant) +""" +i = MaxObject('i') + +""" +in - Gen operator (Input-output) +""" +in_ = MaxObject('in') + +""" +int - Gen operator (Constant) +""" +int_ = MaxObject('int') + +""" +interp - Gen operator (Filter) +""" +interp = MaxObject('interp') + +""" +invpi - Gen operator (Constant) +""" +invpi = MaxObject('invpi') + +""" +isdenorm - Gen operator (DSP) +""" +isdenorm = MaxObject('isdenorm') + +""" +isnan - Gen operator (DSP) +""" +isnan = MaxObject('isnan') + +""" +latch - Gen operator (Filter) +""" +latch = MaxObject('latch') + +""" +length - Gen operator (Vector) +""" +length = MaxObject('length') + +""" +ln - Gen operator (Powers) +""" +ln = MaxObject('ln') + +""" +ln10 - Gen operator (Constant) +""" +ln10 = MaxObject('ln10') + +""" +ln2 - Gen operator (Constant) +""" +ln2 = MaxObject('ln2') + +""" +log - Gen operator (Powers) +""" +log = MaxObject('log') + +""" +log10 - Gen operator (Powers) +""" +log10 = MaxObject('log10') + +""" +log10e - Gen operator (Constant) +""" +log10e = MaxObject('log10e') + +""" +log2 - Gen operator (Powers) +""" +log2 = MaxObject('log2') + +""" +log2e - Gen operator (Constant) +""" +log2e = MaxObject('log2e') + +""" +lookup - Gen operator (Buffer) +""" +lookup = MaxObject('lookup') + +""" +lt - Gen operator (Comparison) +""" +lt = MaxObject('lt') + +""" +< - Gen operator (Comparison) +""" +lt_op = MaxObject('<') + +""" +lte - Gen operator (Comparison) +""" +lte = MaxObject('lte') + +""" +<= - Gen operator (Comparison) +""" +lte_op = MaxObject('<=') + +""" +ltep - Gen operator (Comparison) +""" +ltep = MaxObject('ltep') + +""" +<=p - Gen operator (Comparison) +""" +ltep_op = MaxObject('<=p') + +""" +ltp - Gen operator (Comparison) +""" +ltp = MaxObject('ltp') + +""" +

]*>([^<]+)<', html) + seen = set() + unique = [] + for name in names: + name = name.strip() + if name and name not in seen: + seen.add(name) + unique.append(name) + result[key] = unique + except Exception: + result[key] = [] + return result + + +def compare_local_vs_online(gen_docs_path=None): + """ + Compare local and online gen operator catalogs. + Returns dict with local_only, online_only, both, local_total, online_total. + """ + local = extract_local_gen_operators(gen_docs_path) + online = extract_online_gen_operators() + + local_names = set() + for ops in local.values(): + for op in ops: + local_names.add(op["name"]) + + online_names = set() + for ops in online.values(): + for name in ops: + online_names.add(name) + + return { + "local_only": sorted(local_names - online_names), + "online_only": sorted(online_names - local_names), + "both": sorted(local_names & online_names), + "local_total": len(local_names), + "online_total": len(online_names), + } + + +def generate_comparison_report(gen_docs_path=None, output_path=None): + """Generate a markdown comparison report and write to output_path.""" + report = compare_local_vs_online(gen_docs_path) + + lines = [ + "# Gen Operator Comparison: Local vs. Cycling '74 Online Docs", + "", + f"**Local operators:** {report['local_total']}", + f"**Online operators:** {report['online_total']}", + f"**In both:** {len(report['both'])}", + f"**Local only:** {len(report['local_only'])}", + f"**Online only:** {len(report['online_only'])}", + "", + ] + + if report["local_only"]: + lines.append("## Operators Found Only in Local Installation") + lines.append("") + for name in report["local_only"]: + lines.append(f"- `{name}`") + lines.append("") + + if report["online_only"]: + lines.append("## Operators Found Only in Online Docs") + lines.append("") + for name in report["online_only"]: + lines.append(f"- `{name}`") + lines.append("") + + if report["both"]: + lines.append("## Operators Found in Both Sources") + lines.append("") + for name in report["both"]: + lines.append(f"- `{name}`") + lines.append("") + + content = "\n".join(lines) + + if output_path: + with open(output_path, "w") as f: + f.write(content) + + return content + + +def _make_gen_obj_info(name, category=""): + """ + Create an OBJ_INFO-compatible dict for a gen operator. + """ + default_box = { + "box": { + "id": "obj-1", + "maxclass": "newobj", + "numinlets": 1, + "numoutlets": 1, + "outlettype": [""], + "patching_rect": [0.0, 0.0, 60.0, 22.0], + "text": name, + } + } + + # --- Inlet/outlet counts for gen operators --- + # Verified against https://docs.cycling74.com/userguide/gen/gen~_operators + # + # 0 inlets, 1 outlet: sources, constants, parameters + _0in_1out = { + "in", "in1", "in2", "in3", "in4", "in5", + "param", "Param", + "noise", + "constant", + "samplerate", "SAMPLERATE", "vectorsize", "VECTORSIZE", + "elapsed", "voice", "voicecount", + "mc_channel", "mc_channelcount", + "pi", "PI", "twopi", "TWOPI", "e", "E", + "halfpi", "HALFPI", "invpi", "INVPI", + "degtorad", "DEGTORAD", "radtodeg", "RADTODEG", + "ln2", "LN2", "ln10", "LN10", + "log2e", "LOG2E", "log10e", "LOG10E", + "sqrt2", "SQRT2", "sqrt1_2", "SQRT1_2", + "PHI", "phi", + "fftfullspect", "FFTFULLSPECT", + "ffthop", "FFTHOP", + "fftoffset", "FFTOFFSET", + "fftsize", "FFTSIZE", + "fftinfo", + } + # 1 inlet, 0 outlets: sinks + _1in_0out = { + "out", "out1", "out2", "out3", "out4", "out5", + } + # 1 inlet, 1 outlet: unary operators + _1in_1out = { + "round", "phasewrap", + "change", "dcblock", "delta", + "history", + "atodb", "dbtoa", "mstosamps", "sampstoms", + "fixdenorm", "fixnan", "isdenorm", "isnan", + "t60", "t60time", + } + # 2 inlets, 1 outlet: binary operators + _2in_1out = { + # math + "+", "add", "-", "sub", "*", "mul", "/", "div", + "!-", "rsub", "!/", "rdiv", "!%", "rmod", + "%", "mod", "pow", "atan2", "absdiff", "hypot", + # comparison + "==", "eq", "!=", "neq", ">", "gt", "<", "lt", + ">=", "gte", "<=", "lte", + "==p", "eqp", "!=p", "neqp", ">p", "gtp", "=p", "gtep", "<=p", "ltep", + "max", "maximum", "min", "minimum", "step", + # logic + "&&", "and", "||", "or", "^^", "xor", + # gen~ specific + "delay", "latch", + "+=", "plusequals", "accum", + "*=", "mulequals", + # waveform + "cycle", "triangle", "rate", "phasor", + # convert (2-inlet variants) + "ftom", "mtof", + # buffer + "peek", "sample", "nearest", "lookup", + # routing + "gate", # choose, input + } + # 3 inlets, 1 outlet: ternary operators + _3in_1out = { + "?", "switch", "selector", + "sah", # input, trigger, threshold + "slide", # input, slideup, slidedown + "train", # frequency, width, phase + "clip", # input, min, max + "clamp", # input, min, max + "fold", # input, min, max + "wrap", # input, min, max + "mix", # loval, hival, interp + "smoothstep", # loval, hival, interp + } + # Special multi-inlet/outlet operators + _special_io = { + "counter": (3, 3), # increment, reset, max -> count, carry, underflow + "wave": (4, 1), # phase, start, end, channel + "poke": (3, 0), # value, index, channel + "splat": (3, 0), # value, index, channel + "buffer": (1, 2), # name -> length, channels + "data": (0, 2), # -> length, channels + "cartopol": (2, 2), # x, y -> magnitude, angle + "poltocar": (2, 2), # r, theta -> x, y + "scale": (6, 1), # input, ilo, ihi, olo, ohi, exp + "interp": (7, 1), # t, a, b, c, d, e, f + } + + if name in _0in_1out: + default_box["box"]["numinlets"] = 0 + default_box["box"]["numoutlets"] = 1 + elif name in _1in_0out: + default_box["box"]["numinlets"] = 1 + default_box["box"]["numoutlets"] = 0 + elif name in _1in_1out: + default_box["box"]["numinlets"] = 1 + default_box["box"]["numoutlets"] = 1 + elif name in _2in_1out: + default_box["box"]["numinlets"] = 2 + default_box["box"]["numoutlets"] = 1 + elif name in _3in_1out: + default_box["box"]["numinlets"] = 3 + default_box["box"]["numoutlets"] = 1 + elif name in _special_io: + nin, nout = _special_io[name] + default_box["box"]["numinlets"] = nin + default_box["box"]["numoutlets"] = nout + default_box["box"]["outlettype"] = [""] * nout + elif name in ("r", "receive"): + default_box["box"]["numinlets"] = 0 + default_box["box"]["numoutlets"] = 1 + elif name in ("s", "send"): + default_box["box"]["numinlets"] = 1 + default_box["box"]["numoutlets"] = 0 + elif name in ("setparam",): + default_box["box"]["numinlets"] = 1 + default_box["box"]["numoutlets"] = 0 + elif name in ("gen",): + # gen subpatcher: variable, default 1/1 + pass + elif name in ("codebox", "expr"): + # variable I/O depending on code + pass + # Jitter-specific operators + elif name in ("vec",): + default_box["box"]["numinlets"] = 2 + default_box["box"]["numoutlets"] = 1 + elif name in ("swiz",): + default_box["box"]["numinlets"] = 1 + default_box["box"]["numoutlets"] = 1 + elif name in ("concat",): + default_box["box"]["numinlets"] = 2 + default_box["box"]["numoutlets"] = 1 + elif name in ("cross",): + default_box["box"]["numinlets"] = 2 + default_box["box"]["numoutlets"] = 1 + elif name in ("dot",): + default_box["box"]["numinlets"] = 2 + default_box["box"]["numoutlets"] = 1 + elif name in ("norm", "snorm", "cell"): + default_box["box"]["numinlets"] = 0 + default_box["box"]["numoutlets"] = 1 + elif name in ("nearestpix", "samplepix"): + default_box["box"]["numinlets"] = 2 + default_box["box"]["numoutlets"] = 1 + elif name in ("sphere", "torus", "circle", "plane", "cone", "cylinder"): + default_box["box"]["numinlets"] = 1 + default_box["box"]["numoutlets"] = 1 + elif name in ("hsl2rgb", "rgb2hsl"): + default_box["box"]["numinlets"] = 1 + default_box["box"]["numoutlets"] = 1 + elif name in ("qconj", "qmul", "qrot"): + default_box["box"]["numinlets"] = 2 if name != "qconj" else 1 + default_box["box"]["numoutlets"] = 1 + elif name in ("length", "normalize", "faceforward", "reflect", "refract", "rotor"): + nin = 1 if name in ("length", "normalize") else 2 + default_box["box"]["numinlets"] = nin + default_box["box"]["numoutlets"] = 1 + + return { + "default": default_box, + "args": {"required": [], "optional": []}, + "attribs": [], + "in/out": {}, + "doc": { + "digest": f"Gen operator: {name}", + "description": f"Gen operator '{name}' (category: {category})", + }, + } + + +def generate_gen_obj_info(gen_docs_path=None, output_dir=None): + """ + Generate OBJ_INFO JSON files for all gen operators. + If output_dir is None, writes to maxpylang/data/OBJ_INFO/gen/. + """ + if output_dir is None: + output_dir = os.path.join(obj_info_folder, "gen") + + os.makedirs(output_dir, exist_ok=True) + + local_ops = extract_local_gen_operators(gen_docs_path) + + # Flatten all operators, deduplicating by name + all_ops = {} + for group, ops in local_ops.items(): + for op in ops: + name = op["name"] + if name not in all_ops: + all_ops[name] = op + + # Generate info file for each operator + for name, op in all_ops.items(): + info = _make_gen_obj_info(name, category=op.get("category", "")) + # Sanitize filename for filesystem safety: + # - replace '/' with '_div_' to avoid path separator issues + # - skip uppercase variants that collide with lowercase on + # case-insensitive filesystems (e.g., 'PI' vs 'pi' on macOS). + # These are handled via case-insensitive fallback in get_ref(). + safe_name = name.replace("/", "_div_") + if safe_name != safe_name.lower() and safe_name.lower() in all_ops: + continue # skip; lowercase version covers this + filepath = os.path.join(output_dir, f"{safe_name}.json") + with open(filepath, "w") as f: + json.dump(info, f, indent=2) + + return len(all_ops) + + +def _sanitize_gen_py_name(name): + """Convert a gen operator name to a valid Python identifier.""" + symbol_map = { + "+": "add_op", + "-": "sub_op", + "*": "mul_op", + "/": "div_op", + "%": "mod_op", + "!": "not_op", + "!=": "neq_op", + "!=p": "neqp_op", + "==": "eq_op", + "==p": "eqp_op", + ">": "gt_op", + ">=": "gte_op", + ">p": "gtp_op", + ">=p": "gtep_op", + "<": "lt_op", + "<=": "lte_op", + " gen_name mapping + names_map = {} + for name in sorted(all_ops.keys()): + py_name = _sanitize_gen_py_name(name) + names_map[py_name] = name + + # Build stub file + stub_lines = [] + stub_lines.append('"""MaxObject stubs for gen operators. Auto-generated by gen_scraper."""') + stub_lines.append("import os as _os") + stub_lines.append("import sys as _sys") + stub_lines.append("from maxpylang.maxobject import MaxObject") + stub_lines.append("") + + all_names = sorted(names_map.keys()) + stub_lines.append("__all__ = [") + for py_name in all_names: + stub_lines.append(f" '{py_name}',") + stub_lines.append("]") + stub_lines.append("") + + stub_lines.append("_NAMES = {") + for py_name in all_names: + stub_lines.append(f" '{py_name}': '{names_map[py_name]}',") + stub_lines.append("}") + stub_lines.append("") + + stub_lines.append("_devnull = open(_os.devnull, 'w')") + stub_lines.append("_old_stdout = _sys.stdout") + stub_lines.append("_sys.stdout = _devnull") + stub_lines.append("") + + for py_name in all_names: + gen_name = names_map[py_name] + op = all_ops[gen_name] + category = op.get("category", "") + docstring = f"{gen_name} - Gen operator ({category})" + docstring = docstring.replace('"""', '\\"""') + + stub_lines.append('"""') + stub_lines.append(docstring) + stub_lines.append('"""') + stub_lines.append(f"{py_name} = MaxObject('{gen_name}')") + stub_lines.append("") + + stub_lines.append("_sys.stdout = _old_stdout") + stub_lines.append("_devnull.close()") + stub_lines.append("del _devnull, _old_stdout") + stub_lines.append("") + + with open(output_path, "w") as f: + f.write("\n".join(stub_lines)) + + return output_path diff --git a/maxpylang/tools/objfuncs/reffile.py b/maxpylang/tools/objfuncs/reffile.py index d8fc080..9100f50 100644 --- a/maxpylang/tools/objfuncs/reffile.py +++ b/maxpylang/tools/objfuncs/reffile.py @@ -40,6 +40,18 @@ def get_ref(self, name): if os.path.exists(ref_file): return ref_file + #case-insensitive fallback for gen operators (e.g., PI -> pi, SAMPLERATE -> samplerate) + #needed because case-insensitive filesystems can't store both pi.json and PI.json + #checks both directions: name.lower() in list, AND list entries whose .lower() matches + name_lower = name.lower() + for package, obj_list in self.known_objs.items(): + for obj_name in obj_list: + if obj_name.lower() == name_lower: + package_folder = os.path.join(self.obj_info_folder, package) + ref_file = os.path.join(package_folder, obj_name + ".json") + if os.path.exists(ref_file): + return ref_file + if ref_file is None: #look for possible abstraction file in current directory if os.path.exists(name) or os.path.exists(name + '.maxpat'): diff --git a/maxpylang/tools/patchfuncs/placing.py b/maxpylang/tools/patchfuncs/placing.py index a3216ad..a055e01 100644 --- a/maxpylang/tools/patchfuncs/placing.py +++ b/maxpylang/tools/patchfuncs/placing.py @@ -34,6 +34,7 @@ def place( spacing=[80.0, 80.0], starting_pos=None, verbose=False, + gen_patcher=None, ) -> list[MaxObject]: """ Place objects in the patch. @@ -82,15 +83,15 @@ def place( # place objects according to spacing if spacing_type == "grid": - placed_objs = self.place_grid(picked_objs, spacing, verbose=verbose) + placed_objs = self.place_grid(picked_objs, spacing, verbose=verbose, gen_patcher=gen_patcher) elif spacing_type == "custom": - placed_objs = self.place_custom(picked_objs, spacing, verbose=verbose) + placed_objs = self.place_custom(picked_objs, spacing, verbose=verbose, gen_patcher=gen_patcher) elif spacing_type == "random": if seed is None: # generate seed if not given seed = random.randrange(2 ** 32 - 1) - placed_objs = self.place_random(picked_objs, seed, verbose=verbose) + placed_objs = self.place_random(picked_objs, seed, verbose=verbose, gen_patcher=gen_patcher) elif spacing_type == "vertical": - placed_objs = self.place_vertical(picked_objs, spacing, verbose=verbose) + placed_objs = self.place_vertical(picked_objs, spacing, verbose=verbose, gen_patcher=gen_patcher) return placed_objs @@ -231,7 +232,7 @@ def place_pick_objs(self, objs, randpick, num_objs, seed, weights, verbose): # spacing -def place_grid(self, objs, spacing, verbose=False): +def place_grid(self, objs, spacing, verbose=False, gen_patcher=None): """ Helper function for placing. Places objects in a grid. @@ -260,7 +261,7 @@ def place_grid(self, objs, spacing, verbose=False): if curr_x > (canvas_x - x_space): curr_x = x_space curr_y += y_space - placedObj = self.place_obj(obj, position=[curr_x, curr_y], verbose=verbose) + placedObj = self.place_obj(obj, position=[curr_x, curr_y], verbose=verbose, gen_patcher=gen_patcher) createdObjs.append(placedObj) self._curr_position = [curr_x, curr_y] @@ -269,7 +270,7 @@ def place_grid(self, objs, spacing, verbose=False): # spacing -def place_random(self, objs, seed, verbose=False): +def place_random(self, objs, seed, verbose=False, gen_patcher=None): """ Helper function for placing. Places objects randomly. @@ -287,14 +288,14 @@ def place_random(self, objs, seed, verbose=False): createdObjs = [] for obj in objs: position = [np.random.random() * x, np.random.random() * y] - placedObj = self.place_obj(obj, position=position, verbose=verbose) + placedObj = self.place_obj(obj, position=position, verbose=verbose, gen_patcher=gen_patcher) createdObjs.append(placedObj) return createdObjs # spacing -def place_custom(self, objs, positions, verbose=False): +def place_custom(self, objs, positions, verbose=False, gen_patcher=None): """ Helper function for placing. Places objects according to custom positions. @@ -307,7 +308,7 @@ def place_custom(self, objs, positions, verbose=False): createdObjs = [] for obj, pos in zip(objs, positions): - placedObj = self.place_obj(obj, position=pos, verbose=verbose) + placedObj = self.place_obj(obj, position=pos, verbose=verbose, gen_patcher=gen_patcher) createdObjs.append(placedObj) self._curr_position = pos @@ -316,7 +317,7 @@ def place_custom(self, objs, positions, verbose=False): # spacing -def place_vertical(self, objs, spacing, verbose=False): +def place_vertical(self, objs, spacing, verbose=False, gen_patcher=None): """ Helper function for placing. Places objects vertically. @@ -333,7 +334,7 @@ def place_vertical(self, objs, spacing, verbose=False): createdObjs = [] for obj in objs: y += spacing - placedObj = self.place_obj(obj, position=[x, y], verbose=verbose) + placedObj = self.place_obj(obj, position=[x, y], verbose=verbose, gen_patcher=gen_patcher) createdObjs.append(placedObj) self._curr_position = [x, y] @@ -342,7 +343,7 @@ def place_vertical(self, objs, spacing, verbose=False): # actual placement of a single object -def place_obj(self, obj, position=[0.0, 0.0], verbose=False, replace_id=None): +def place_obj(self, obj, position=[0.0, 0.0], verbose=False, replace_id=None, gen_patcher=None): """ Helper function for placing. If obj denoted by string, creates obj; otherwise, adds existing object to patcher at specified position. @@ -351,6 +352,7 @@ def place_obj(self, obj, position=[0.0, 0.0], verbose=False, replace_id=None): position --> patcher position verbose --> debug commands replace_id --> 'obj-num' string of object being replaced + gen_patcher --> MaxPatch instance to embed as a gen sub-patcher inside this object """ # get object from specification @@ -366,6 +368,10 @@ def place_obj(self, obj, position=[0.0, 0.0], verbose=False, replace_id=None): obj._dict["box"]["patching_rect"][0:2] = position # change position + # embed gen patcher if provided + if gen_patcher is not None: + obj._dict["box"]["patcher"] = gen_patcher.get_json()["patcher"] + # add to various dictionaries of patch objects by obj-id obj_id = obj._dict["box"]["id"] self._objs[obj_id] = obj diff --git a/tests/test_gen.py b/tests/test_gen.py new file mode 100644 index 0000000..f349483 --- /dev/null +++ b/tests/test_gen.py @@ -0,0 +1,361 @@ +"""Tests for Gen patcher support in MaxPyLang.""" + +import os +import sys +import json +import tempfile + +import pytest + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) +import maxpylang as mp + +# Skip marker for tests that require Max installed locally +_MAX_GEN_DOCS = "/Applications/Max.app/Contents/Resources/C74/docs/userguide/content/gen/" +requires_max = pytest.mark.skipif( + not os.path.exists(_MAX_GEN_DOCS), + reason="Max not installed — gen reference files not available" +) + + +class TestGenPatcherCreation: + """Test creating gen patchers with gen_type parameter.""" + + def test_gen_type_dsp_gen(self): + """MaxPatch with gen_type='dsp.gen' should have correct classnamespace.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + json_dict = gen_patch.get_json() + assert json_dict["patcher"]["classnamespace"] == "dsp.gen" + + def test_gen_type_jit_gen(self): + """MaxPatch with gen_type='jit.gen' should have correct classnamespace.""" + gen_patch = mp.MaxPatch(gen_type="jit.gen", verbose=False) + json_dict = gen_patch.get_json() + assert json_dict["patcher"]["classnamespace"] == "jit.gen" + + def test_gen_type_jit_pix(self): + """MaxPatch with gen_type='jit.pix' should have correct classnamespace.""" + gen_patch = mp.MaxPatch(gen_type="jit.pix", verbose=False) + json_dict = gen_patch.get_json() + assert json_dict["patcher"]["classnamespace"] == "jit.pix" + + def test_gen_type_jit_gl_pix(self): + """MaxPatch with gen_type='jit.gl.pix' should have correct classnamespace.""" + gen_patch = mp.MaxPatch(gen_type="jit.gl.pix", verbose=False) + json_dict = gen_patch.get_json() + assert json_dict["patcher"]["classnamespace"] == "jit.gl.pix" + + def test_default_patch_has_box_classnamespace(self): + """Normal MaxPatch (no gen_type) should still use 'box' classnamespace.""" + patch = mp.MaxPatch(verbose=False) + json_dict = patch.get_json() + assert json_dict["patcher"]["classnamespace"] == "box" + + def test_gen_patch_can_place_objects(self): + """Gen patcher should support place() just like a normal patch.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + assert gen_patch.num_objs == 2 + + def test_gen_patch_can_connect_objects(self): + """Gen patcher should support connect() just like a normal patch.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + gen_patch.connect([inp.outs[0], outp.ins[0]], verbose=False) + assert len(outp.ins[0].sources) == 1 + + +class TestGenPatcherEmbedding: + """Test embedding gen patchers inside gen~ objects.""" + + def test_place_gen_tilde_with_gen_patcher(self): + """Placing gen~ with gen_patcher should embed the patcher dict.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + gen_patch.connect([inp.outs[0], outp.ins[0]], verbose=False) + + patch = mp.MaxPatch(verbose=False) + gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + + assert "patcher" in gen_obj._dict["box"] + assert gen_obj._dict["box"]["patcher"]["classnamespace"] == "dsp.gen" + + def test_embedded_gen_patcher_has_boxes(self): + """Embedded gen patcher should contain the placed objects.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + gen_patch.place("in 1", verbose=False) + gen_patch.place("out 1", verbose=False) + + patch = mp.MaxPatch(verbose=False) + gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + + boxes = gen_obj._dict["box"]["patcher"]["boxes"] + texts = [b["box"]["text"] for b in boxes] + assert "in 1" in texts + assert "out 1" in texts + + def test_embedded_gen_patcher_has_lines(self): + """Embedded gen patcher should contain patchcord connections.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + gen_patch.connect([inp.outs[0], outp.ins[0]], verbose=False) + + patch = mp.MaxPatch(verbose=False) + gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + + lines = gen_obj._dict["box"]["patcher"]["lines"] + assert len(lines) == 1 + + def test_save_patch_with_embedded_gen(self, tmp_path): + """Patch with embedded gen~ should save and reload correctly.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + gen_patch.connect([inp.outs[0], outp.ins[0]], verbose=False) + + patch = mp.MaxPatch(verbose=False) + gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + dac = patch.place("ezdac~", verbose=False)[0] + patch.connect([gen_obj.outs[0], dac.ins[0]], verbose=False) + + filepath = str(tmp_path / "test_gen_embed.maxpat") + patch.save(filepath, verbose=False, check=False) + + assert os.path.exists(filepath) + with open(filepath, "r") as f: + saved = json.load(f) + + gen_boxes = [b for b in saved["patcher"]["boxes"] + if b["box"].get("text", "") == "gen~"] + assert len(gen_boxes) == 1 + assert gen_boxes[0]["box"]["patcher"]["classnamespace"] == "dsp.gen" + + def test_place_without_gen_patcher_unchanged(self): + """Normal place() without gen_patcher should work as before.""" + patch = mp.MaxPatch(verbose=False) + osc = patch.place("cycle~ 440", verbose=False)[0] + assert "patcher" not in osc._dict["box"] + + +@requires_max +class TestGenScraper: + """Test gen operator extraction from local Max files.""" + + def test_extract_common_operators(self): + """Should extract common gen operators from local file.""" + from maxpylang.tools.gen_scraper import extract_local_gen_operators + result = extract_local_gen_operators() + assert "common" in result + assert len(result["common"]) > 100 # we know there are 150 + + def test_extract_gen_tilde_operators(self): + """Should extract gen~ specific operators from local file.""" + from maxpylang.tools.gen_scraper import extract_local_gen_operators + result = extract_local_gen_operators() + assert "gen_tilde" in result + assert len(result["gen_tilde"]) > 50 # we know there are 63 + + def test_extract_jitter_operators(self): + """Should extract jitter gen operators from local file.""" + from maxpylang.tools.gen_scraper import extract_local_gen_operators + result = extract_local_gen_operators() + assert "jitter" in result + assert len(result["jitter"]) > 20 # we know there are 30 + + def test_operators_have_names(self): + """Each operator should have at least a name.""" + from maxpylang.tools.gen_scraper import extract_local_gen_operators + result = extract_local_gen_operators() + for category, ops in result.items(): + for op in ops: + assert "name" in op, f"Operator missing name in {category}" + assert len(op["name"]) > 0 + + def test_operators_have_categories(self): + """Each operator should have a category.""" + from maxpylang.tools.gen_scraper import extract_local_gen_operators + result = extract_local_gen_operators() + for group, ops in result.items(): + for op in ops: + assert "category" in op, f"Operator {op['name']} missing category in {group}" + + +@requires_max +class TestGenObjInfo: + """Test gen operator OBJ_INFO metadata generation.""" + + def test_generate_gen_obj_info(self, tmp_path): + """Should create JSON files for gen operators.""" + from maxpylang.tools.gen_scraper import generate_gen_obj_info + generate_gen_obj_info(output_dir=str(tmp_path)) + + json_files = [f for f in os.listdir(tmp_path) if f.endswith(".json")] + assert len(json_files) > 200 # we expect ~243 operators + + def test_gen_obj_info_file_structure(self, tmp_path): + """Each OBJ_INFO JSON should have expected keys.""" + from maxpylang.tools.gen_scraper import generate_gen_obj_info + generate_gen_obj_info(output_dir=str(tmp_path)) + + history_path = os.path.join(tmp_path, "history.json") + if os.path.exists(history_path): + with open(history_path, "r") as f: + info = json.load(f) + assert "default" in info + assert "args" in info + assert "attribs" in info + assert "in/out" in info + assert "doc" in info + + def test_gen_obj_info_default_has_box(self, tmp_path): + """Each OBJ_INFO default should contain a valid box dict.""" + from maxpylang.tools.gen_scraper import generate_gen_obj_info + generate_gen_obj_info(output_dir=str(tmp_path)) + + # Check a known operator - use 'noise.json' since 'in' might have naming issues + noise_path = os.path.join(tmp_path, "noise.json") + if os.path.exists(noise_path): + with open(noise_path, "r") as f: + info = json.load(f) + box = info["default"]["box"] + assert "id" in box + assert "maxclass" in box + assert "text" in box + + +@requires_max +class TestGenComparison: + """Test comparison between local and online gen operator catalogs.""" + + def test_generate_comparison_report(self): + """Should produce a comparison dict with expected keys.""" + from maxpylang.tools.gen_scraper import compare_local_vs_online + report = compare_local_vs_online() + assert "local_only" in report + assert "online_only" in report + assert "both" in report + assert "local_total" in report + assert "online_total" in report + + +@requires_max +class TestGenStubs: + """Test gen.py stub generation and imports.""" + + def test_generate_gen_stubs(self, tmp_path): + """Should create a gen.py stub file.""" + from maxpylang.tools.gen_scraper import generate_gen_stubs + stub_path = str(tmp_path / "gen.py") + generate_gen_stubs(output_path=stub_path) + assert os.path.exists(stub_path) + + def test_gen_stubs_contain_known_operators(self, tmp_path): + """Generated stubs should contain known gen operators.""" + from maxpylang.tools.gen_scraper import generate_gen_stubs + stub_path = str(tmp_path / "gen.py") + generate_gen_stubs(output_path=stub_path) + with open(stub_path, "r") as f: + content = f.read() + assert "history" in content + assert "phasor" in content + assert "cycle" in content + assert "noise" in content + + def test_gen_stubs_sanitize_names(self, tmp_path): + """Operators with special chars should get sanitized Python names.""" + from maxpylang.tools.gen_scraper import generate_gen_stubs + stub_path = str(tmp_path / "gen.py") + generate_gen_stubs(output_path=stub_path) + with open(stub_path, "r") as f: + content = f.read() + # 'in' is a Python keyword -> should become 'in_' + assert "in_ = MaxObject(" in content + + +class TestGenEndToEnd: + """End-to-end tests: create gen patchers, embed them, save, and verify output.""" + + def test_passthrough_patch(self, tmp_path): + """Recreate the ex1_passthrough.maxpat using the new API.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + gen_patch.connect([inp.outs[0], outp.ins[0]], verbose=False) + + patch = mp.MaxPatch(verbose=False) + gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + dac = patch.place("dac~", verbose=False)[0] + patch.connect([gen_obj.outs[0], dac.ins[0]], verbose=False) + + filepath = str(tmp_path / "passthrough.maxpat") + patch.save(filepath, verbose=False, check=False) + + with open(filepath, "r") as f: + saved = json.load(f) + + assert len(saved["patcher"]["boxes"]) == 2 + + gen_boxes = [b for b in saved["patcher"]["boxes"] + if b["box"].get("text", "").startswith("gen~")] + assert len(gen_boxes) == 1 + + gen_box = gen_boxes[0]["box"] + assert "patcher" in gen_box + assert gen_box["patcher"]["classnamespace"] == "dsp.gen" + assert len(gen_box["patcher"]["boxes"]) == 2 + assert len(gen_box["patcher"]["lines"]) == 1 + + def test_gen_with_cycle_operator(self, tmp_path): + """Create a gen~ patch that uses the cycle operator.""" + gen_patch = mp.MaxPatch(gen_type="dsp.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + cyc = gen_patch.place("cycle", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + gen_patch.connect( + [inp.outs[0], cyc.ins[0]], + [cyc.outs[0], outp.ins[0]], + verbose=False, + ) + + patch = mp.MaxPatch(verbose=False) + gen_obj = patch.place("gen~", gen_patcher=gen_patch, verbose=False)[0] + dac = patch.place("ezdac~", verbose=False)[0] + patch.connect([gen_obj.outs[0], dac.ins[0]], verbose=False) + + filepath = str(tmp_path / "gen_cycle.maxpat") + patch.save(filepath, verbose=False, check=False) + + with open(filepath, "r") as f: + saved = json.load(f) + + gen_box = [b for b in saved["patcher"]["boxes"] + if b["box"].get("text", "").startswith("gen~")][0] + inner_texts = [b["box"]["text"] for b in gen_box["box"]["patcher"]["boxes"]] + assert "in 1" in inner_texts + assert "cycle" in inner_texts + assert "out 1" in inner_texts + assert len(gen_box["box"]["patcher"]["lines"]) == 2 + + def test_jit_gen_patcher(self, tmp_path): + """Create a jit.gen patch with correct classnamespace.""" + gen_patch = mp.MaxPatch(gen_type="jit.gen", verbose=False) + inp = gen_patch.place("in 1", verbose=False)[0] + outp = gen_patch.place("out 1", verbose=False)[0] + gen_patch.connect([inp.outs[0], outp.ins[0]], verbose=False) + + patch = mp.MaxPatch(verbose=False) + gen_obj = patch.place("jit.gen", gen_patcher=gen_patch, verbose=False)[0] + + filepath = str(tmp_path / "jit_gen_test.maxpat") + patch.save(filepath, verbose=False, check=False) + + with open(filepath, "r") as f: + saved = json.load(f) + + gen_box = [b for b in saved["patcher"]["boxes"] + if "patcher" in b["box"]][0] + assert gen_box["box"]["patcher"]["classnamespace"] == "jit.gen"