i am working on a new script/formula module called FormulaOne.
A pre release can be found at https://github.com/docb/dbRackFormulaOne. I have made a small manual in the Readme which shows how to make
Oscillators, Phase controlled Oscillators, Wave folders, Filters, Comb Filters, Stereo Delays,
Random and Hold, CV Sequencers, Gate Sequencers, Chord Sequencers, Envelope Generators.
Of course it is not intended for replacing native modules because they still will be faster i.e. consume less CPU and provide more usability. It is for experimenting, learning and making special things.
It is only tested for linux so far. Tests on other platforms, opinions, requests are welcome.
On Windows unfortunately the module will be slower as i had to disable optimizations of exprtk
which cause that the compiled obj file exceeds the accepted size of the mingw compiler (provided in the rack-plugin-toolchain). Due to the docs of exprtk it should compile fine with the MVSC++ compiler (which i don’t have).
it seems to be a known issue, mingw32 seems to have a signed short for the size of the sections in the obj file (2^16) and the option -Wa,-mbig-obj did not work, so may be i need here another version of mingw – i will continue to investigate. I do not have a windows installation either(and don’t want to), and i still would like to be able to compile my modules with the rack-plugin-toolchain on linux.
If someone gives a try - in the Makefile this entry should be commented out.
include $(RACK_DIR)/arch.mk
ifdef ARCH_WIN
# the exprtk cannot compiled on mingw because a too big obj file is generated
# with this option it is under the limit but it is slower
FLAGS += -Dexprtk_disable_enhanced_features
# the option -Wa,-mbig-obj did not work so far
endif
however the module is still usable but it appears to consume 20-30% more CPU.
hi, its not a fork. you could make a diff of the two and tell me which code lines match .
You also could look at the manual and see that almost all examples are not doable with
Frank Buss Formula and you could also compare the cpu usage of the two.
I have utilized one concept of this module and that is the blinker if the compilation fails.
It’s interesting that you decided to go for the traditional single module solution. It could have been a master & expander (aka player & editor) combo.
Well, i like the compact scripts where all things fit into the window.
So i decided to make a single module. The second problem would be, that the module without the editor does not tell you what exactly is present at the moment.
But thanks very much for the input, I will consider this option.
Btw. currently there is an expander for editing in the module:
I’m very much looking forward to seeing (and using) this in the library. It appears to be more of a full scripting language, and not just the ability to enter a single formula. So my guess is it could just about replace or substitute for the VCV Prototype module that still is missing from V2.
I see you can have user defined variables. What about user defined functions?
It appears there is implicit iteration of the polyphonic channels. That could be good for a majority of situations - streamlining development of polyphonic applications. But I’m concerned about operations that need to operate on inputs and/or outputs of multiple channels simultaneously. A simplistic example is something like a polyphonic split/merge. Is there a way to take control of the channel iteration?
That script entry window looks like a golden opportunity for additional functionality. It would be great if there were at least two modes for the display:
script display and editing
script defined text output. It could be used to give documentation for knobs/inputs/outputs. It could also give dynamic feedback on input/output values and or computed values.
Maybe a reach - but what about a graphical display option, so it could have its own built in scope and/or frequency plots. It would be cool if that was built in. But if you also had a scripting interface, we could have a platform for user defined visualizations. Maybe a reach, but it sounds cool to me.
hi Dave, thanks for your input:
FormulaOne was not intended to be a full scripting interface. May be rather a simple formula evaluator – “x+y” does still work polyphonic – with some scripting capabilities which provides state and buffers for enabling the implementation of dsp algorithms. For a full scripting interface i would rather make it like the LUA module from Wrong People similar as you pointed out in your third point - with description, scope etc …, Here and also in the VCV Prototype the script is in a file edited with a common editor and there is much space to make such things like descriptions which are displayed when loaded. With the current interface it will get messy. (NB it has already stolen some time to adapt the textfield of the vcvrack api for doing needed stuff).
User defined functions are is not directly provided by the underlying engine. It seems to be possible but this has a bigger effort, as so far i can see it the docs i would have to parse the script by my self first, extract the function and register it in the c++ code before compiling.
The single loop for polyphonic stuff requires a different api which may be not so simple as you would need either variables e.g. w1,…,w16 or a function getW(0) … and same for the outputs. Eventually this leads to a different module or mode, which provides the rack C++ API inside the script (getVoltage(channel), setVoltage(value,channel), getPolyVoltage(channel), getParam(), setChannels(), getChannels(), isConnected(),… and this for each input,output, knob. This could be feasible (may be it is slower) but i am not sure if this is purposeful. Shouldn’t i use simply for these polyphony usecases the LUA Module from Wrong People? Because this module has exactly this interface.
Bottom Line: My intention was to have a reasonably fast and easy interface where i can experiment, learn and do special things i cannot find in other modules. The media discontinuity to have the script in a file and the switch to an external application is eliminated with the drawback that you cannot make scripts with 1000 lines, which anyway would cost too much CPU.
hi Arash,
first, very thanks for your great library. So far i have not recognized the exprtk-extras repository.
So far understood, you have introduced a syntax for separating function definitions and the main program, by using directives starting with $. The $function directive is parsed (all methods for this are provided) and the resulting function eventually passed to the compositor. I will try to integrate this in the next version. Thanks!
Hi DocB - The $ is something I used for the repl to denote multi-line inputs, as it uses a simple std::cin mechanism.
Given you’ve got a full edit widget you can simply parse as-is. There is code in the repl that parses functions out from a string and using the function compositor generates functions and registers them in the symbol_table.
Yeah the mechanism used to perform return in ExprTk is extremely slow when compiled with msvc on windows. Are your perf numbers based on a windows build?
Though it should be fine from a performance POV on linux and macos. Furthermore Section 20 of the readme has a more detailed explanation, with alternatives to return.