Thinking out loud: a scripting language for Cantabile

Are we still talking about a scripting language, or are you envisioning a plugin API for user-compiled binary extensions to Cantabile (e.g., DLLs)?

The latter seems to me like the ideal solution, since it would allow C programmers to write super-fast real-time code when needed, while also allowing you (or anyone) to write a plugin that implements a safer, more user-friendly scripting language (e.g., a plugin that interprets or JIT-compiles user-supplied scripts and calls the underlying C API to effect script actions). That would give you the freedom to develop scripting capabilities as an optional plugin without adding that code complexity directly to Cantabile’s core.

1 Like

@brad I could definitely live with C as the language. My memory needs are pretty small (20 or less variables), and I’m not looking to print out messages on the UI or anything. I could live with the suggestion of defining all variables at the top of the script; this would both speed execution and eliminate the need for complex memory cleanup.

Here are three things that I found difficult or impossible to program in Cantabile via MIDI:

  1. Thinning data – i.e., sending only the nth event of some type
  2. Creating last-note priority for mono leads
  3. Storing the current value of a pedal or knob
  4. Mapping all notes of any velocity to the same note on a different channel.

I know the 4th one can be done with the current generation of Filters, but it takes 3-4 of them, as well as both a little imagination and careful ordering. It could probably be done with 1-2 lines of C code.

Regards
-BW

I like the three things adding up to 4 :joy:

All of this is pretty easy using ReaJS - and I’d expect it to be even easier in a future MIDI processor

1 Like

Everything starts at “Hello World”…

4 Likes

That’s excellent!!!

One thing I wonder about, since it’s compiling to real C and executing it. If this eventually makes it into Cantabile, will it be possible to protect the Cantabile session from crashes in any way?

2 Likes

One small step for a Brad, one giant leap for Cantabile users, I hope. :slightly_smiling_face:
I know, it’s not a original thought, but I really like this Hello World.

1 Like

Only in so much as the language itself would be “safe”: bounds checking on arrays, no direct pointer references, support for exceptions etc…

1 Like

Maybe a dumb question, but what is this all meant to do? Can anyone please give me an example?

There are no dumb questions, but this requires some background and forward thinking…

The idea behind all of this is to provide the ability to do user scripting in Cantabile - both in the audio engine (eg: MIDI processing) and in general (app level control like load a song, switch states etc…). The whole idea started because support for binding expressions were so well received, but also so limited (only supports expressions, no flow control and can’t run on the audio thread).

I got to thinking about what it would take to add a more capable scripting language but wanted some feedback on whether it would useful and what it would be used for - hence the reason I posted this topic in the first place and you can read back through the replies to see some interesting suggestions.

But before I can add scripting, I need a scripting language. But for it to run on the audio thread, there are some very strict requirements so it can run without stalling and causing glitches. This makes me very wary of using an existing language - either because they use garbage collectors that are known to stall, or because they’re loosely typed which makes them slower, or because they’re just too unknown, or because I just don’t like the language, or because I have “not invented here syndrome”.

So I decided to do a little proof-of-concept for a language that:

  • Has well controlled memory management. In this case it has a garbage collector but is designed to be very incremental so as to not cause stalls. It also supports plugging in a heap allocator so it can use Cantabile’s non-blocking heap to run on the audio thread
  • Strongly typed - for performance reasons
  • Compiled to machine code - again for performance reasons
  • Is strictly single threaded, but only on a per-script basis - for simplicity
  • Is very focused on scripting - ie: designed for small automation and processing tasks, not for building entire applications, has top-level statements and minimal to no “plumbing” code.
  • Is modern and clean - I’m modelling it very closely on C#.

And that’s all this is… a proof-of-concept language to see if the above is possible.

So far it certainly looks possible - I’ve built a tiny language that will meet all of the above but is so far very limited and barely does anything.

It’s also probably too much work to be worth it - but I’m continuing to play with it mostly because I find it interesting but also because it might pay off in the long run. For now, don’t expect this to see the light of day but I might continue to ramble on about it (although I think I’ll shift the discussion from Cantabile forum to the Topten Software blog).

So far, I’ve treated this as a holiday period project but will probably move it to a side project as I don’t want it to interfere with on-going Cantabile development once I switch back into work mode.

Also, in the meantime I hit on the idea of using C for the audio thread scripting - that is much more likely to happen.

3 Likes

Thanks. All good. Just thought it worth asking as I don’t understand the uses for this level of configurability.

For myself… I grew up with BASIC and COBOL. C remains baffling to me, so I doubt I’ll be dabbling! But never say never…

I think that regardless of how straightforward the resulting language is, it is likely to remain something only a small portion of users write scripts for. That would suggest to me another requirement worth considering - ease of sharing of scripts. That way a broader group of people can benefit from the shared work of those who delve into the coding. So the ability to pass small text files around holding scripts, and for them to be as minimally tied to a person’s particular setup as possible, such as keeping them agnostic to things like port names.

6 Likes

Hi @Neil_Durant,

This is a good point. My thoughts here were to not store the script content in the song/rack files directly. But rather have a directory of scripts, that are referenced from the songs. I guess similar to how you add a plugin, you could add a script. Something like that…

It’s a long way off yet, but definitely worth thinking about.

Brad

2 Likes

For those interested in following along with the development of this (it’ll be a side project to Cantabile) I’m moving the discussion to the Topten Software Blog where I’ll be publishing a new article about it each week - second one coming out tomorrow.

Please feel free to comment if so inclined (you’ll need to subscribe to a free member account to leave comments).

2 Likes

Just one thought/question from me. Where in Cantabile will we be able to use this scripting language?

I am asking as it occurred to me it would be good to be able to script your own custom MIDI filters in MIDI routes, but cannot recollect that being discussed as an option

Too early to say all the places where scripting would be available. What I want to avoid if I can is different languages in different places. So I’m focusing on building a language that can be used on the audio thread but is also nice to use for higher level app automation type stuff.

MIDI scripting was discussed in the context of a midi processor script, which is similar to midi filter but not exactly the same. Scripted midi filter definitely makes sense though.

1 Like

Agreed that a consistent language would be good

1 Like

Sounds great!

2 Likes

I have often built racks in Cantabile to handle midi controllers. Largely this has worked well but I have always come across the same issue which is the lack of user variables. If you need to have Cantabile “remember” things it can be difficult. I have used rack states to remember foot switch states for example and more recently I have used rack output gain to remember fader positions. For example, I have a 16 channel mackie controller and use Cantabile to control the midi between that and Cubase. I have built racks in Cantabile to switch between using the faders as track volume or track CC faders. I needed to remember fader positions when switching between these functions. User variables would be a better solution. I would assume a scripting language may offer that?

Hi Alan,

Thanks for the feedback. User variables is something that I’m considering adding regardless of a scripting language.

Brad

2 Likes

Yesssss! This will come in handy in so many scenarios…

1 Like