Max RNBO template - user created modules

Today, I’m releasing a new project, one that allows non-developers to create new modules for the SSP.

I hope not only will this help individuals to get more from their SSP, but allow end-users to contribute to development, and share their endeavours.

This work is all based around Cycling 74’s RNBO, being used with my ‘SSP template’.

what is RNBO?

some important facts:

  • SSP modules created can be used by anyone, without additional software or licenses
  • you may not sell created modules without purchase a JUCE licence, or open sourcing code.
  • any modules you distribute should be open sourced
  • Max/RNBO can be used license free
    though, with the limitation that you cannot save patches, saving requires a license.

generally this means, anyone can use the modules created, and as a developer you’re ok, if you distribute source code (e.g. on GitHub)

more details are in the project readme, pay particular attention to licensing if you are considering distribution of any kind.

Max/Rnbo version

tested against : Max 8.5.3 / RNBO v1.1.0

Release

note: given stage of this project its likely there will be changes as we move forward.
I’ll try to remember to post here to inform of important changes.

Current limitations

  • no midi support
  • macOS / Linux support only
    - I’ve not included an example patch yet
    (this is not really needed as the documentation shows how to do this yourself!)

    - max 16 parameters

Window’s users, I have no plans to natively support windows for a variety of technical reasons.
however, you can still use this project by install a linux virtual machine.
There are many flavours of VM, and some are free… so this is not really an impediment for windows users, and frankly is better than using a native windows dev environment :wink:

Support

Due to time required for development support, including setting up development environments, I can only give a limited support - however, there are plenty of resources to help you on your way.

Initially, I will prioritise support to current ko-fi supporters, as a thank you for your support.

If you need more extensive help, please contact me via DM…
we could arrange private lessons via skype/zoom, if this interests you.

Original topic

some history behind this idea, is in this topic

as mentioned previously, very excited by this project and the opportunities it opens up for the user community.

7 Likes

Update regularly !

(see details below about updating)
for now, this is a very active project… updating frequently, and you’ll likely wan the changes, which might add feature, of fix issues Ive found.

the nice thing is, git pull will tell you about file changes.
if nothing has changed, you will see this, and not having to do anything…so costs nothing to check :slight_smile:

if it has, then you can update your modules… see below for more details.

tip: git log will list my comments about what has change, though they will be ‘sparse’.

Updating template (when it changes)

Occasionally, I will update the template, fortunately it’s easy to update !

cd ~/projects/rnbo.example.ssp
git pull

this will give you latest copy of template.
however, as stated, any projects you have created are a copy
(this means I don’t break anyone’s who has customised the code)

if you have not created any custom C++ code,
then Id recommend you delete your existing module, and just re-create it.

if you are using custom code… then I guess you know what to do
look for difference in PluginProcessor.h/cpp * PluginEditor.h/cpp
and decide how you want to integrate your changes.
(hey if you are ‘whizz’ with git and patch files, you might even be able to do it automatically ;))

also the above assumes you didn’t fork the repo… if you did, then I guess you know how to merge upstream git :wink:

Tips for sharing

  • share both the generated C++ code and the RNBO patch.
  • I’d recommend using GitHub.com for sharing code.
    there is a GitHub client application, which can make things a bit easier to newcomers.
    the easiest approach is to ‘fork’ my repository, rnbo.example.ssp (you can rename), as this has required structure etc, and means you can easily get updates to the template.
    placing on GitHub.com also is a good way of backing up your work :slight_smile:

SSP wiki

I’ll add some tips n’ tricks, as I think of them to to the SSP wiki,
on this page

Extra resources

a post I created to hopefully inspire beginners to module development

2 Likes

Congratulations on the release!

I have a question about the SSP plugin exported with the Max RNBO template.
Will a patch that reads an external wave file in Buffer~ and converted to an SSP plugin work?
I have created a simple patch in RNBO and am checking to see if each element of the patch I want to create will work in SSP.
I tried a plugin that I created by reading a wave file and building it with the copy sample dependence checked, but it did not work with SSP.

The following is what I tried.

  1. I put the .so file in the plugin folder and copied the Media folder and put it in the SSP plugin folder.

  2. I exported c++ with RNBO, copied the media folder to the plugin folder of the SD card of SSP, rewrote the path of the dependencies json file to the media folder of SSP, and put the built .so file in the plugin folder.

The RNBO patch I tried is in the figure.
It worked on MAX, but maybe the RNBO patch itself is wrong.



1 Like

no, not ‘out of the box’

you can think of my (template) code, as like a host for the code generated by RNBO.
RNBO code has no access to resources, like files,IO, midi etc, it assumes the code surrounding, will handle all of this… and in particular buffer~ need to use so called external buffers.


however, I am currently experimenting in this area … but it needs (alot of) custom c++ code.

in particular, Ive created a 4 track looper, and Im displaying the waveforms on the UI.
(this could obviously be extended to load/save these buffers to files.)

basically, I generated the initial module with the template,
then I’ve (highly) customised the surrounding code.
In particularly, this looper code now creates/manages/displays all the buffers that are used internally by RNBO.


so how does this relate? will I add the ability for the c++ template to load files?

short answer is probably not… and there are two reasons…
RNBO code does not know file name…

this is becoming a ‘common limitation’ of RNBO, the generated code does include a lot of meta data that you see in Max/RNBO.
instead this metadata can be found in a couple of accompanying json files.
this could be used either
a) running my own generator script to generate additional c++ classes.
b) read at run time (on ssp)
I dont want to do (b), since I dont want modules to include ‘other files’
I might do (a) in the future, but I want to see how necessary it really is…

BUT Im not sure this is the best way forward for file handling on the SSP anyway !

what I already know from my coding, is that the C++ code knows which buffers are used by RNBO (test in your example), it just doest know the file (loop2.wav)

so Im wondering if at some point the way forward is to allow file selection for buffers… this seems more ‘useful’ that just loading up static files.
I think this could possibly work… as RNBO already differentiates between internal and external buffers.

I would only allow file selection on external buffers…, however, internal buffers e.g. things like delay lines, would therefore NOT be shown.

so if we go back to my looper example.
these are already external buffers, so you’d be able to load a file into them, and save them.

note: I can think of one small exception, where this doesn’t work well…
imagine you want to display a delay line in your C++ code, it’d have to external.
but you dont really want to allow a file to loaded into it!
however, thats not really ‘an issue’…
a) even, if someone loaded a waveform into the delay line… so what
b) Im unlikely to support displaying waveforms in the generic UI in the short term.
c) the generic ui will handle all use-cases anyway, this is why you can customise.
… and if you customise the code, you can easily stop this unwanted behaviour.


tl;dr;

not there currently, without customise code.

but I may have something in the future.
however, it wont be till after Ive done the looper, and so ironed these things out a bit.
once I’ve done in a specific case (looper), I’ll have a better idea of what feasible for the generic template.

2 Likes

Thanks for the explanation.

I understand that it cannot be used ‘out of the box’ for now.
We already have a sampler module for SSP, so it doesn’t matter if I can’t read the sample right now.
I will first think about creating a module with other elements.

I have lots of ideas for things I want to make, such as burst triggers that can be synchronized to tempo to control probabilities and patterns, etc., so I’m having fun trying them out!

2 Likes

yeah, I dont see it as a big deal at the moment…

but its an interesting topic…
as it goes to illustrate the relations between the template code vs the generated RNBO code.
so I thought a detailed answer might interest some.

I’ll also say, I’d not be surprised if this ‘relationship’ evolved as RNBO moves forward. e.g. 1.1 or2.0… as its very much where the limits of RNBO can be felt.
(limits, may be too a strong word… but, I mean more the ‘boundary’)

getting the hang of RNBO … finding some good techniques to keep things tidy… and scale

had a lot of fun with it today, doing the audio backend is so quick.

here’s where im at…and a peak at how I develop and test ssp modules on my Mac :slight_smile:

all working, as the mechanics are pretty much done, as is the RNBO patch, at least for v1.0

you can see custom waveform display… start/end points, real time position feedback.

next step remove the ‘generic’ parameter display…
basically there’ll be a page per ‘layer’, and then a general (mostly recording) page.
things like record, play/stop, loop will also move to buttons.

currently its fixed at 10 seconds recording, and no file load/save, but this can change.
mainly thats just more UI work, as I need to create things like file dialogs/naming etc - which frankly is very tedious/unexciting work!

Id also like to add a zoom/position feature to the waveform display… though thats more for other modules…

because whats interesting is… this base could be used for at least 2 other very nice modules :wink:

though frankly, theres so many things I could do for a looper module, Im going to need to careful to not get too carried away for v.1 (actually, thats no worries really… this is always the case.

4 Likes

UPDATE for rnbo.example.ssp

I’ve just updated rnbo.example.ssp template…
it now has pages of 16 parameters, which you can switch between using PG+/.
(so no practical limit to number of parameters… though, your user will get bored of paging thru :wink:

see second post, on how to update template, if you have already downloaded it.

UPDATE: small update, made the ssp-sdk and this repos docs consistent… i.e. devenv.md is the same.

wow. this seems like the start of something really great. exciting

&e

1 Like

yeah, I think so… key thing is im actively using it, so this ensures that its actually useful.

related, users should update regularly!

the project is very active at the moment , as I notice issues, or need something… I will add it.
and frankly, at this stage, Im not going to come here and post for every small update I do :slight_smile:

fortunately, to check for updates is very easy.
just type, git pull, it’ll pull new changes, and tell you what has changed , if anything !
for now, I’d recommend doing this every time you start some ‘work’ in this area, and of course, if you find an issue… to check its not been already fixed.

if nothing has changed, you’ll see this, so you’ll know no further action is needed.
otherwise, you can update your modules (or not) (as detailed in the second post on this topic)

2 Likes

It needs a little more tweaking, but I could create a burst-trigger plugin that is tempo-sync and probability-controllable.
MAX RNBO template is fantastic!


5 Likes

cool… glad you got it working.
this is always the fun bit, once you have the basics working, and you can start to add extras :slight_smile:

as you can see, one you have a way to code the dsp, and get some parameters and cv in, pretty much the skies the limit.
if you remember, my early plugins on the SSP had a pretty similar (simple) ui… and its still enough for a lot.

in fact, these have a bit more than my early ones, since they should also have midi learn :slight_smile:

btw: have a look at CMakeFile.txt, this is where you will find things like plugin name, so if you edit that , you can get the title a bit nice on the screen…


I’ve been pretty busy with stuff too… adding some stuff, to my underlying code base, so I can add something that people are going to like in LOOP.
(and opens up some other ideas :wink: )

1 Like

Could you explain a bit more on the internal and external buffers?
I’m still not sure about the boundary between internal and external buffers.
For example, if I create a Gen~ object in RNBO and use the Data object in Gen~ to create a fixed-length array for sample data (For exsample, “Data Loop 480000 1”), is that an internal buffer? or an external buffer?
Is there an easy way to check if the code exported from RNBO uses external buffers?

internal/external buffers.

its a bit tricky to explain without viewing the bigger picture.

so the first thing we have to understand is an RNBO patch is NOT a standalone thing.
it is just DSP code… its has to be ‘hosted’ in something , e.g a VST , or a max external or a module in the SSP.

this mean rnbo patches (and gen~) cannot access thing like files, or even audio hardware.

so if we create something like buffer~ or data within an rnbo patch, its just some memory.
of course, we can fill the buffer, and that useful for things like delay Iines.
but we cannot fill it with data from a file (see above, about hosting)
so in this case buffers are internal (to the rnbo patch)

if we want to start filling it with things like samples from a file, then this is the responsibly of the host…
at which point, it is now considered to be an external buffer (with respect to the rnbo patch)

there is an easy way to see this…

a) create a max msp patch
b) place in it , and rnbo patch
c) in the rnbo patch, put a buffer~ object , called mybuf1
d) now in the (parent) max/msp patch a buffer~ object called mybuf1

what happens here is these two buffers are actually the same… since the buffer~ in the rnbo patch is actually now an ‘external’ buffer which is using the max/msp buffer object.
i.e max/msp owns it.
(if you look at the help for rnbo~ buffer, it shows this)

so in max/msp we can now load the buffer object from a file… since max/msp has this function!


the issue is… unfortunately, C74 blurred the lines a bit… by adding the @file attribute to the rnbo buffer~.
this was a dumb idea on their part!
(theres a few examples of this in rnbo, things that are not ‘pure’, and are going to confuse users!)

basically this @file attribute is just a hint to the ‘host’ to load a file on behalf of the rnbo patch, and put it into this buffer… the RNBO code generates has NO code to do this loading… even worst the filename is just metadata, contained in a completely separate file… so even that is not available in the generated code.
I guess the idea is hosts could ‘read’ this metadata (and presets) at runtime,

but frankly, that is absolute nonsense, and ill thought out…
sure its ok, if you are doing web development, but no plugin developer is going to want to ship these extra files… also even if you shipped the meta data, you dont want to start shipping resources like wav files!

so really, it should never have been part of rnbo that the ‘user’ sees, as its complete misleading once we get beyond running the rnbo patch within max.


unfortunately, when it comes to the SSP, I cannot really see how to expose these buffers as files in a nice generic way… basically, because to do so, makes too many assumptions to make them useful.

I know this, as Ive just added loading/saving into LOOP which uses these external buffers,
but the circumstances, and the way I had to handle it, is very specific to that module.

anyway, never say never, but it is what it is for now.

1 Like

Thanks for explaining the details.
I need to check further details, but I understood that mine is an internal buffer since the need is arrary not linked to a file.
I’ll try to figure out how to make a feedback looper for RNBO practice with what you’ve taught me.

1 Like

if you create a buffer/dat within the rnbo patch, indeed its internal… and these completely functional.
I could have kept the buffers ‘internal’ for LOOP, and it can be fully functional.

however, the reason LOOP ends up using external buffers is because
a) I wanted to display the recorded data
b) I wanted to save/load the waveforms.

so thats the point,
a buffer can be internal, so created managed within RNBO… and cannot have any interaction outside the buffer. or external, create/managed externally … but accessible by the ‘host’.

honestly, this only comes into play if you are writing the code embeds the rnbo patch.
(and if it were for the stupid @file attribute, users could be blissfully unaware of all this )

anyway, just use buffer~ (or data, they are the same object :wink: ) , but be aware there is no way (currently) within this template to load/save the contents (without writing c++ code)

Although it has only a few simple features, but I was able to create my own Feedback looper!
I think I can use it by adding fade-ins and fade-outs within a few samples during REC, and by adding REC timing quantization.

1 Like

cool… if you are using groove~ for the playback, then this has a crossfade parameter.
(otherwise, you can apply a window on playback to apply a fade)


btw: I think, it would be useful for others if you shared the RNBO patch that you create.

the main hope for this project is that we will help promote sharing in the community, allow more people to get involved.

if you share the rnbo patch, then others can simply download this template project, and then not only try to use your patches. perhaps create your own topic in SSP Modules - ( Handsonicsuki’s modules?) , then you can include the videos, and also the patch itself… and any other info you’d like ( * )

( *) make sure to link back to this topic, so others will know how to use your patches.

I think it’d be pretty cool, we’d get some more juicy details about what your up to, and your adventures,
and also it might be inspirational too…


also an important reminder to others… “Have a go!” - it’s very quick to get this all working…
you can use Cycling 74’s RNBO for free, you do not have to buy it.

also lets remember… we have a real community possibility here…

the more users that create and share patches, the more experience there will be to help others do the same. not only technically, but also inspirationally.
and the more users that share patches, and the community grows around it, the more likely I am to develop this concept further…

so really… this is an opportunity for the community to help itself, to help each other…
that is my motivation behind this project !

1 Like

I use poke~ and peek~ for recording and playback.
I made this patch based on a sample from the Cycling’74 forum and @thetechnobear
your advice (position of reading head and writing head) to the simple feedback looper topics I made in the past. :slight_smile:

Simple feedback looper - SSP Features and Ideas - Percussa Forum

Of course I’m happy to share plugins like this if it helps someone else.
I’m noob with this kind of thing, but where would you suggest uploading the RNBO patch to? GitHub?
If it’s GitHub, I’ll have to learn how to use it since I don’t know how to use it at all.

I’ll upload it when I’ve fixed it a bit more, but I still have to name the plugin TEST, so I’ll have to name it something! (LOL)

2 Likes