Python and Max

whatamidoing's icon

Hi Everyone!

What is the best way (if there is any) to run a python script with multiple outputs in max. Jython seems to run only in older versions than current Max 7. I tried to download a mxo-object from net.loadbang.jython but the website is offline since several days...

thank you for your help! :)

stoersignal's icon

have you found it? if yes, i would be very thankful if you could provide me a link
thx in advance

measure's icon

I am using [csound~], which contains several python opcodes.
see http://www.csounds.com/manual/html/py.html

One can use python libraries, numpy etc.

to_the_sun's icon

@Measure, that's very intriguing. Do you know where a Windows version of [csound~] can be found? http://www.davixology.com/csound~.html returns a 404 error.

OCH's icon

@TO_THE_SUN
https://web.archive.org/web/20160223121606/http://www.davixology.com/csound~.html
can you please try it out and come back here to give a report on it?

I'd be very impressed if that would allow you to easily use python.

OCH's icon

Also, I'm aware it is probably irrelevant for @WHATAMIDOING now but:
https://github.com/cassiel/net.loadbang.jython

I've been very interested for some time on a possible Python4Max package that would allow one to run a modern Python version like 3.6 (Jython is 2.7). If anyone has any good pointers lmk.

Source Audio's icon

https://github.com/csound/csound_tilde/

https://github.com/csound/csound_tilde/releases

version 1.1.2 - max 8 ok

Iain Duncan's icon

Please take this in the spirit of helpfulness, as I'm not trying to dissuade you, but what is your reason for wanting Python specifically? I ask because I was previously in the same boat, and years ago did a lot of work with Csound and python. The problems I had, which eventually led me to give up on Python as a music scripting language, is that you can't really get away from Python's GIL problem. Take this with a grain of salt, because it's been over 10 years, but I believe that the Csound implementation embeds the cpython interpreter, which I think will mean that if you end up with patches with many csound objects embedding many pythons that you can create threading issues in Max, giving you poor responsiveness or blocking a thread and resulting in timing issues. If you want access to Python's library ecosystem (which can't be beat I admit) but don't need it running in true embedded fashion , you might be better off using the shell object and an external Python process, which is really the same as how Node for Max works. If you want true "in-max" embedded scripting in an interpreted language I don't think Python is a great choice (I say this as someone who's been doing Python for a living for a long time, so not a Python hater by any stretch). I wound up going with Scheme myself, but I believe others have had success with Lua as well.

If someone with more recent and thorough knowledge of Python embedding issues knows otherwise though, I'm all ears!

OCH's icon

Dear @IAIN DUNCAN,
Thank you very much for your feedback!
Yes, I am trying to make use of some Python-only libraries.
The "shell object + external Python process" is a good idea, but I'm not sure there is still a true cross-compatible (windows & mac) shell object out there (?). {there is! here}
"(...) which is really the same as how Node for Max works" - that leads me to believe that it wouldn't actually be that "difficult" to then add a Python for Max. If only it would be officially offered by Cycling74...

Best

OCH's icon

@SOURCE AUDIO
Thanks for the github links!

to_the_sun's icon

Thanks for those links. I'm using Python for its machine learning libraries (Tensorflow) run as external scripts, but when sending a lot of data back and forth latency can become an issue under heavy loads. I'm not really at the point of needing to try a different method like [csound~] yet; I was mainly just curious.

There is indeed a cross-platform [shell] out there, but my experience with it is that you still need to send platform-specific commands to it. I launch my Python scripts with a JS script from node.script, which utilizes the shelljs package, and that's not a problem. I'll attach it in case it's useful to someone.

scriptHandler.js
text/javascript 9.17 KB

Iain Duncan's icon

I would think that if you can get python scripts firing through the shell, you could likely avoid needing platform specific commands if you use Python's own platform agnostic system abstractions like the system module? What exactly are you wanting to do with Python? I might be able to advise, I've not used Python in Max, but I've done an awful lot of Python.

to_the_sun's icon

Well, maybe I'm just remembering wrong, but I was just talking about firing the scripts in the first place (i.e. replacing forwardslashes with backslashes on Windows). Actually it's entirely possible I'm remembering that wrong, so don't quote me on that…

to_the_sun's icon

I am indeed running into problems trying to get a heavy stream of data to Tensorflow now (dropped packets, latency). I was about to install csound but it looks like it requires Python 2.7 and I really need 3.7. Can anyone confirm this?

AudioMatt's icon

This seems a little crazy. Node for max was amazing but I feel like if you wanted to really bring max into the 21st century, python would be where it's at. The the fact that we're relying on obscure third party objects for this feels like an undue barrier to a world of cutting edge algorithms.

What happened to the py object? Is that completely gone? I tried it ten years ago and it seemed super buggy.

Iain Duncan's icon

I think many folks in music wind up abandoning Python, as I did. It's a nice language (I built my career on it), but the implementation is just full of roadblocks for getting it to work in a high performance embedded context. The GIL, the general pain in the ass of embedding it in C, etc. I jumped ship to Scheme personally, but I know of others who wound up preferring Lua for similar reasons.

AudioMatt's icon

@iain, this is very interesting. Coming from someone who can barely hack on python, my experience is that every time I google some algorithm that’s been published/hacked on in the last ten years it’s almost inevitably on GitHub in python. like I just googled “edge tangent flow“ and the first result was a python git and I couldn’t find c implementations. It seems to be replacing matlab mostly.

it’s this reason I keep telling myself “just bite the bullet and teach yourself in a week”

Are you saying its not worth it?

Iain Duncan's icon

Not at all, Python is totally worth it, it is by far the dominant language for doing machine learning analysis and natural language processing, and is the most popular general purpose language for stats and scientific analysis. (As in, if you need something less one-trick-pony that R). And it has a massive package ecosystem, so is great for any kind of text hacking, system plumbing, etc. I use it all the time, but I gave up on using it for real time music/audio specifically. And if you are an Abelton live user, you can write control surface scripts in it (mind you, this is because the control surface scripts don't execute in the audio thread, so again, reliable low latency and tight timing is not really possible...)

Scheme is much weaker in terms of a polished language for doing general work (unusably weak one might say!) but it's the cat's pajamas for embedding because there are so many different compiler and interpreters out there and the core language is ultra-ultra minimal. Also, lisps just lend themselves beautifully to expressing high level musical ideas in code. There do exist folks who prefer Haskell (Tidal Cycles, Euterpea), but for my money I'd rather write music domain code in a lisp than anything else, having experimented with a bunch.

AudioMatt's icon

got it. Sounds like my instincts were mostly on. For the most part, I'm more intense interested in non-real-time work.

nick rothwell | project cassiel's icon

The Jython package at https://github.com/cassiel/net.loadbang.jython still works - and I still use it - though it requires a working Java environment, and is only Python 2.

I've been thinking about trying to get something like pyjs or Brython running inside Node, but don't really have the time to look at it. But they're both rather web-oriented so it might be tricky. (Also I'm mostly working in Clojure for Max scripting these days, and that works in MXJ and Node pretty well.)

Iain Duncan's icon

A few other Clojure-ish languages I've been keeping a watch on for possible use with Max are Fennel (compiles to Lua), Janet, and Carp (lisp 1 with no garbage collector and static types). Nick, have you taken a look at any of those? I'm pretty firmly on the S7 bandwagon for the time being, but I imagine if they have a decent FFI it would not be impossible for me to take what I've learnt and developed with Scheme For Max and do it again with Carp or Fennel, so I'm watching them! Carp especially, as it is quite active and real time synthesis is one of the stated goals.

There is also a similar thing from the Extempore guys, they made a scheme variant with static typing and manual memory management called xtlang for the extempore project.

Shakeeb Alireza's icon

I've been working on a project which implements a python3 interpreter in a number of different max externals. https://github.com/shakfu/py-js

As Ian Duncan has remarked, Python has its issues to embed as I have discovered developing this project, but it's nonetheless interesting and quite educational to see how far one can go to surmount such challenges.

OCH's icon

@Shakeeb
Really interesting project! Thank you for sharing.
I'm starting an issue there to ask you questions :)

Best,
OCH

to_the_sun's icon

Just thought I'd comment that I've switched to using the python-shell NPM package within node.script to great success. Superfast transfer of messages, handles Tensorflow, can plot with Matplotlib, etc.

OCH's icon

"can plot with Matplotlib, etc.""
How?

to_the_sun's icon

Run a Python script that plots using Matplotlib

OCH's icon

Oh, but the plot does not appear inside Max, right?

to_the_sun's icon

Right, but it still pops up its own window for it just fine, which initially I was worried it would have problems with.

Shakeeb Alireza's icon

@Omar Thanks for checking it out. As for your question "can one plot with Matplotlib, etc..", the answer it depends on which variation you use. If you just don't care about packaging python in your Mac package or standalone then all of the packages of your system homebrew python are available to the embedded interpreter in the [py] object. This is the default build. Then you need to figure out how to get the data from Max to your python script, generate the matplotlib graph and then load it into max.

One way to think about the [py] object is that it's an independent python namespace and you can populate by 'import', 'exec' and 'execfile' which modifies the namespace and you can get stuff out into Max by using 'eval'. So you can write a function in your system pythonpath or a custom pythonpath which is added to the object namespace and then import it with an import message and then send Max data: lists, etc.. or have it read a dict or a coll and then you can generate a png to /tmp and then load into max.

Maybe easier to read the file representation from dict or coll and then just trigger a script and load.

In any case, best way to get familiar is check out the demo patches..

Shakeeb Alireza's icon

@TO_THE_SUN I wasn't aware of python-shell. It be great to check out another way to get python into Max. Is it pretty straightforward to do this?

to_the_sun's icon

Yeah it wasn't too bad at all actually. The package page has a lot of examples for getting it set up. One thing that was a little tricky to figure out was that to get return messages from the python script you need to use sys.stdout.flush() and that will send everything that you've print()ed since the last time you flushed. Here's the hacked together little JavaScript script I'm using in case you want to look at it.

python-shell.js
text/javascript 1.24 KB

Shakeeb Alireza's icon

@TO_THE_SUN thanks a lot for sharing your script. I was just about to check it out.
Very cool.

Shakeeb Alireza's icon

I checked out the Python-Shell method thanks to @TO_THE_SUN, it worked nicely. Very cool. I had no idea how easy it was to use nodejs packages in Max. (I really should spend some more time on this).

Also @OmarHamido, I made a pre-release of a couple of my python3 externals (see: https://github.com/shakfu/py-js/releases ) since you asked (-:

Shakeeb Alireza's icon

Just a quick followup to my prior post: I'm re-releasing macOS builds of my two python3 externals (py and pyjs) after fixing a local dependency error spotted by @OmarHamido.

The externals each contain an embedded python3 interpreter with a zipped stdlib in the Resources folder of their bundle which also has a site-packages directory for your own code. The python interpreter in each external is statically compiled and self-contained without any non-system dependencies so should be usable in Max Packages and Standalones.

I've also included better docs and a demo standalone in the release to demonstrate this.

see: https://github.com/shakfu/py-js/releases

Phivos-Angelos Kollias's icon

Shakeeb Alireza
thank you for your contribution
I just "installed" the lib
then tried
"make projects" and some of the externals never came to life.

I have reported the error also to the repo

here the full installation log including the errors:

py-js % make projects
Makefile:454: warning: overriding commands for target `check'
Makefile:248: warning: ignoring old commands for target `check'
~/Unity_projects/py-js ~/Unity_projects/py-js
-- The C compiler identification is AppleClang 14.0.3.14030022
-- The CXX compiler identification is AppleClang 14.0.3.14030022
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMAKE_OSX_ARCHITECTURES set to x86_64
CMAKE_SOURCE_DIR/source/projects/cmx: /Users/soklamon/Unity_projects/py-js/source/projects/cmx
CMAKE_BINARY_DIR}/include: /Users/soklamon/Unity_projects/py-js/build/include
-- Found Python3: /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11 (found version "3.11.4") found components: Interpreter Development Development.Module Development.Embed
CMAKE_LIBRARY_OUTPUT_DIRECTORY: /Users/soklamon/Unity_projects/py-js/source/projects/py/../../../externals
CMAKE_CURRENT_BINARY_DIR: /Users/soklamon/Unity_projects/py-js/build/source/projects/py
Python3_VERSION: 3.11.4
Python3_VERSION_MAJOR: 3
Python3_VERSION_MINOR: 11
Python3_FOUND: TRUE
Python3_Interpreter_FOUND: TRUE
Python3_Development_FOUND: TRUE
Python3_EXECUTABLE: /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11
Python3_INTERPRETER_ID: Python
Python3_STDARCH: /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11
Python3_STDLIB: /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11
Python3_SITELIB: /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages
Python3_SITEARCH: /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages
Python3_SOABI: cpython-311-darwin
Python3_LIBRARIES: /Library/Frameworks/Python.framework/Versions/3.11/lib/libpython3.11.dylib
Python3_INCLUDE_DIRS: /Library/Frameworks/Python.framework/Versions/3.11/include/python3.11
Python3_LINK_OPTIONS: LINKER:-rpath,/Library/Frameworks
Python3_LIBRARY_DIRS: /Library/Frameworks/Python.framework/Versions/3.11/lib
Python3_RUNTIME_LIBRARY_DIRS: /Library/Frameworks/Python.framework/Versions/3.11/lib
using standard local configuration
using standard local configuration
-- Configuring done (4.5s)
-- Generating done (0.2s)
-- Build files have been written to: /Users/soklamon/Unity_projects/py-js/build
[ 3%] Building C object source/projects/cmx/CMakeFiles/cmx.dir/cmx.c.o
[ 6%] Linking C static library libcmx.a
[ 6%] Built target cmx
[ 10%] Building C object source/projects/demo/CMakeFiles/demo.dir/demo.c.o
[ 13%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/demo.mxo/Contents/MacOS/demo
Copy PkgInfo
[ 13%] Built target demo
[ 17%] Building CXX object source/projects/krait/CMakeFiles/krait.dir/krait.cpp.o
[ 20%] Linking CXX CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/krait.mxo/Contents/MacOS/krait
Copy PkgInfo
[ 20%] Built target krait
[ 24%] Building C object source/projects/mamba/CMakeFiles/mamba.dir/mamba.c.o
[ 27%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/mamba.mxo/Contents/MacOS/mamba
Copy PkgInfo
[ 27%] Built target mamba
[ 31%] Building C object source/projects/mxpy/CMakeFiles/mxpy.dir/mxpy.c.o
[ 34%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/mxpy.mxo/Contents/MacOS/mxpy
Copy PkgInfo
[ 34%] Built target mxpy
[ 37%] Building CXX object source/projects/pktpy/CMakeFiles/pktpy.dir/pktpy.cpp.o
[ 41%] Linking CXX CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/pktpy.mxo/Contents/MacOS/pktpy
Copy PkgInfo
[ 41%] Built target pktpy
[ 41%] Built target api_c
[ 44%] Building C object source/projects/py/CMakeFiles/py.dir/py.c.o
[ 48%] Building C object source/projects/py/CMakeFiles/py.dir/api.c.o
/Users/soklamon/Unity_projects/py-js/source/projects/py/api.c:26131:21: warning: fallthrough annotation in unreachable code [-Wunreachable-code-fallthrough]
CYTHON_FALLTHROUGH;
^
/Users/soklamon/Unity_projects/py-js/source/projects/py/api.c:345:34: note: expanded from macro 'CYTHON_FALLTHROUGH'
#define CYTHON_FALLTHROUGH __attribute__((fallthrough))
^
/Users/soklamon/Unity_projects/py-js/source/projects/py/api.c:26142:21: warning: fallthrough annotation in unreachable code [-Wunreachable-code-fallthrough]
CYTHON_FALLTHROUGH;
^
/Users/soklamon/Unity_projects/py-js/source/projects/py/api.c:345:34: note: expanded from macro 'CYTHON_FALLTHROUGH'
#define CYTHON_FALLTHROUGH __attribute__((fallthrough))
^
2 warnings generated.
[ 51%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/py.mxo/Contents/MacOS/py
Copy PkgInfo
[ 55%] Built target py
[ 58%] Building C object source/projects/pyjs/CMakeFiles/pyjs.dir/pyjs.c.o
[ 62%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/pyjs.mxo/Contents/MacOS/pyjs
Copy PkgInfo
[ 62%] Built target pyjs
[ 65%] Building CXX object source/projects/shell/CMakeFiles/shell.dir/shell.cpp.o
[ 68%] Linking CXX CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/shell.mxo/Contents/MacOS/shell
Copy PkgInfo
[ 68%] Built target shell
[ 72%] Building C object source/projects/zpy/CMakeFiles/zpy.dir/zpy.c.o
[ 75%] Building C object source/projects/zpy/CMakeFiles/zpy.dir/__/__/max-sdk-base/c74support/max-includes/common/commonsyms.c.o
[ 79%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/zpy.mxo/Contents/MacOS/zpy
ld: warning: dylib (/usr/local/lib/libczmq.dylib) was built for newer macOS version (13.0) than being linked (12.0)
ld: warning: dylib (/usr/local/lib/libzmq.dylib) was built for newer macOS version (13.0) than being linked (12.0)
ld: warning: dylib (/usr/local/lib/libsodium.dylib) was built for newer macOS version (13.0) than being linked (12.0)
Copy PkgInfo
[ 79%] Built target zpy
[ 82%] Building C object source/projects/zthread/CMakeFiles/zthread.dir/zthread.c.o
[ 86%] Building C object source/projects/zthread/CMakeFiles/zthread.dir/__/__/max-sdk-base/c74support/max-includes/common/commonsyms.c.o
[ 89%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/zthread.mxo/Contents/MacOS/zthread
ld: warning: dylib (/usr/local/lib/libzmq.dylib) was built for newer macOS version (13.0) than being linked (12.0)
ld: warning: dylib (/usr/local/lib/libsodium.dylib) was built for newer macOS version (13.0) than being linked (12.0)
Copy PkgInfo
[ 89%] Built target zthread
[ 93%] Building C object source/projects/zedit/CMakeFiles/zedit.dir/mongoose.c.o
[ 96%] Building C object source/projects/zedit/CMakeFiles/zedit.dir/zedit.c.o
/Users/soklamon/Unity_projects/py-js/source/projects/zedit/zedit.c:113:23: warning: unused variable 'toggle' [-Wunused-variable]
t_object *toggle, *metro;
^
/Users/soklamon/Unity_projects/py-js/source/projects/zedit/zedit.c:113:32: warning: unused variable 'metro' [-Wunused-variable]
t_object *toggle, *metro;
^
/Users/soklamon/Unity_projects/py-js/source/projects/zedit/zedit.c:119:13: warning: code will never be executed [-Wunreachable-code]
newobject_fromboxtext(patcher, "cycle~ 440");
^~~~~~~~~~~~~~~~~~~~~
/Users/soklamon/Unity_projects/py-js/source/projects/zedit/zedit.c:112:13: note: silence by adding parentheses to mark code as explicitly dead
if (1) {
^
/* DISABLES CODE */ ( )
/Users/soklamon/Unity_projects/py-js/source/projects/zedit/zedit.c:460:9: warning: code will never be executed [-Wunreachable-code]
systhread_mutex_lock(x->x_mutex);
^~~~~~~~~~~~~~~~~~~~
/Users/soklamon/Unity_projects/py-js/source/projects/zedit/zedit.c:34:20: warning: unused variable 's_enable_hexdump' [-Wunused-variable]
static const char* s_enable_hexdump = "no";
^
5 warnings generated.
[100%] Linking C CFBundle shared module /Users/soklamon/Unity_projects/py-js/externals/zedit.mxo/Contents/MacOS/zedit
Copy PkgInfo
[100%] Built target zedit
~/Unity_projects/py-js

Phivos-Angelos Kollias's icon

another question, I am wondering if the lib works for Windows also, because the project I am working on is a cross platform one (i.e. MacOS and Win)

Shakeeb Alireza's icon

Hi Phivos,

The project is really a collection of python3 or python-related Max externals. Currently, there is no option to run any of the external subprojects on Windows, mainly because I just don't develop on Windows myself, but there is no intrinsic technical reason why it shouldn't work per se.

Incidentally, I'm just seeing compilation warnings in your build output but I can't find a specific error (note the absence of the word 'error') in what you posted. Please feel free to post any issues you may continue to have in the repo issue tracker.

S

Shakeeb Alireza's icon

FYI, just wanted to update here that the main python3 externals (py and pyjs) are now windows compatible and the Max api wrapper code for the 'py' external has been enhanced quite a bit lately so things like writing and reading to/from buffer~ objects via python code include numpy is now possible. There are quite a few max patches and python scripts to demonstrate this.

Iain Duncan's icon

Wow, congrats! That's great. :-)

Shakeeb Alireza's icon

Thanks Iain! (-:

Phivos-Angelos Kollias's icon
Shakeeb Alireza's icon

For anyone interested in using python3 in Max, I just released v0.2.6 of py-js which provides two python3 externals for use in Max/MSP built on the latest python 3.12.4 engine. The first wraps a subset of the Max c-api and the second enables python interop via a jsextension. Both macOS externals are fully codesigned and notarized.

Please let me know if you have any issues!

S

OCH's icon

Thanks again for sharing! It is so good to know this project continues being updated and improved :)

Warm regards, 

OCH

Shakeeb Alireza's icon

@OCH

Thanks.. I'm focusing now on refinements, improving stability and dealing with corner cases. Also each new version of python creates its own issues.. Feedback is always welcome!

Shakeeb Alireza's icon

Here is another release which updates the py and pyjs externals to the recently released Python 3.13.0 engine. Besides the usual features and incremental performance improvements which come with a new version of Python, a number of deprecated modules were finally removed, so the externals in this release are measurably smaller than the prior 3.12.x series.

Iain Duncan's icon

Hi Shakeeb, have you thought of trying with this Roger Dannenberg's Serpent? It's a Python derivative that he built specifically for real time music use, with a real-time GC and more appropriate thread/process architecture. I only recently encountered it but plan on digging in. It looks like it could be very fruitfull for using with Max, and he is using it in his new project, Arco.

Shakeeb Alireza's icon

@Iain Duncan

Thanks, I wasn't aware of serpent. It definitely sounds interesting. I tried to build arco and cserpent in his GitHub repos but didn't get very far...

Iain Duncan's icon

Hi Shakeeb, Arco is in alpha, so not surprising that you had issues, but Serpent has been around much longer and is available outside of arco. I think the main download page is on sourceforge.

Shakeeb Alireza's icon

Getting back to the 0.30 py-js release mentioned above: one thing to note in this release is that many build variants now embed the numpy module in the external. Along with the builtin api module which gives python access to the Max c-api, this means you can read and write buffers using numpy. For example:

import math
import numpy as np
import api # <- this builtin modules gives access to max c-api

def test_create_empty_buffer():
    name = "drum"
    duration_ms = 500
    buf = api.create_empty_buffer(name, duration_ms)
    api.post(f"created buffer name: '{name}' duration(ms): '{duration_ms}'")
    api.post(f"framecount: {buf.framecount}")

def test_buffer_get_samples():
    name = "drum1"
    sample_file = "jongly.aif"
    buf = api.create_buffer(name, sample_file)
    api.post(f"created buffer name: '{name}' sample_file: '{sample_file}'")
    n_samples = buf.n_samples
    xs = np.array(buf.get_samples())
    assert len(xs) == n_samples
    api.post(f"get {n_samples} samples from buffer {name}")

def test_buffer_set_samples():
    name = "drum1"
    duration_ms = 500
    buf = api.create_empty_buffer(name, duration_ms)
    api.post("buffer.set_samples example with numpy")
    api.post(f"created buffer name: '{name}' duration(ms): '{duration_ms}'")
    api.post(f"framecount: {buf.framecount}")
    n_samples = buf.n_samples
    t = np.linspace(0, 1, n_samples, endpoint=False, dtype=np.float32)
    xs = np.sin(t * 2 * math.pi * 5)
    buf.set_samples(xs)
    api.post(f"set {n_samples} samples to buffer {name}")

def test_buffer_set_samples2():
    name = "drum1"
    duration_ms = 500
    buf = api.create_empty_buffer(name, duration_ms)
    api.post(f"testing auto-resizing of buffer size")
    api.post("buffer.set_sample example with numpy and scipy.signal")
    api.post(f"created buffer name: '{name}' duration(ms): '{duration_ms}'")
    api.post(f"framecount: {buf.framecount}")
    n_samples = buf.n_samples * 2
    t = np.linspace(0, 1, n_samples, endpoint=False, dtype=np.float32)
    xs = np.sin(t * 2 * math.pi * 5)
    buf.set_samples(xs)
    api.post(f"set {buf.n_samples} samples to buffer {name}")

def test_buffer_set_samples3():
    name = "drum1"
    duration_ms = 500
    buf = api.create_empty_buffer(name, duration_ms)
    t = np.linspace(0, 1, buf.n_samples, endpoint=False, dtype=np.float32)
    buf.set_samples(t)

def test_buffer_protocol_read():
    name = "drum1"
    sample_file = "jongly.aif"
    buf = api.create_buffer(name, sample_file)
    api.post(f"created buffer name: '{name}' sample_file: '{sample_file}'")
    xs = np.asarray(buf)
    assert len(xs) == buf.n_samples
    api.post(f"len(x): {len(xs)} == buf.n_samples: {buf.n_samples}")

def test_buffer_protocol_write():
    name = "drum1"
    duration_ms = 500
    buf = api.create_empty_buffer(name, duration_ms)
    api.post("buffer.set_sample example with numpy and scipy.signal")
    api.post(f"created buffer name: '{name}' duration(ms): '{duration_ms}'")
    api.post(f"framecount: {buf.framecount}")
    xs = np.asarray(buf, dtype=np.float32)
    t = np.linspace(0, 1, buf.framecount, endpoint=False, dtype=np.float32)
    xs[:] = np.sin(t * 2 * math.pi * 5)

OCH's icon

this is really cool :)

speaking of the multiple versions... i had a little bit of a hard time figuring out which one is which. I was about to suggest some updates to readme, but then got lost in time...

OCH

Shakeeb Alireza's icon

Hi OCH

Any feedback is welcome :-)

For a brief guide about the 'build variants': in general the '-ext' suffix means self-contained external, the '-pkg' suffix means a Max package where the externals in the 'externals' folder depend on the python library in the 'support' folder:

- shared-ext - self-contained external, fully loaded, dynamically linked.

- shared-ext-tiny - self-contained external, size-minimized, dynamically linked.

- static-ext - self-contained external, fully loaded, statically linked.

- static-ext-tiny - self-contained external, size-minimized, statically linked.

- framework-ext - self-contained external, fully loaded, built as a framework (dynamically linked).

- framework-pkg - package-structure, Python.framework is in the support folder of the package with the py and pyjs externals linked to it.

- homebrew-ext - self-contained external, fully loaded, built as a framework, (dynamically linked) but smaller than framework-ext.

- homebrew-pkg - package-structure, Python.framework is in the support folder of the package with the py and pyjs externals linked to it (smaller than framework-pkg).

Variants which embed numpy have the -np suffix in their name.

Hope the above helps.

S

OCH's icon

Yes, that definitely helps <3