Home | ER-101 | ER-102 | ER-301 | Wiki | Contact

Middle Layer SDK (aka patching with Lua)



Hey Brian, are these files available for examination and learning or are they part of the proprietary code base?


Here you go:

er-301-lua-v0.3.19pre.zip (257.4 KB)

:skull_and_crossbones: Enter at your own risk :skull_and_crossbones:


Oh boy. That is a lot to digest. :slight_smile: Thanks, I think it will be helpful in understanding the middle layer, though!


These places where you have MixMax objects e.g.

local f0Range = self:createObject("MinMax","f0Range")

These are all about the graphic display and nothing to do with the audio/CV signal, right? Is this the piece that feeds into the real-time readout on the right side of a control, like for the example above, the f0 control, eg. in the LUA:

range = objects.f0Range


Crumbs, quite a lot to go at there - thanks @odevices :smiley:

Keyboard > Init.lua is the easiest to understand I have found so far, there’s some really obvious stuff in here that makes the rest easier to parse.

edit: Hehe - nice to see the full list of adjectives and nouns :wink:


Hmm, the API documentation and Lua framework is looking pretty good. Much better than trying to deduce the parameters from the Lua files alone. Should be enough for anyone with moderate programming experience to get started, although I imagine it looks a little overwhelming at first glance. I hope I get some time to try some experiments soon. Looks like fun.


I agree!!

I highly recommend watching @Joe’s excellent introduction video here - I am pretty sure you will be coding in no time :smiley:


Sorry. :sweat_smile:

It was never my intention to just dump a bunch of code on you guys and let you fend for yourselves. And yet, that is exactly what I’ve ended up resorting to…at least in the short-term.


That is exactly right. In fact, one of these days that stuff is probably going to disappear into the background like it already has for the scopes and level meters.

Just one of the many places where you will catch me with my pants down as you go through the code. :blush:


Ha. I don’t know enough to know better. Just trying to figure out how it works now. :wink:


Intentional or not, I am not bothered in the slightest, of course I’ll take any support I can get, but it’s not the first time I’ve had nothing to go on but the code base and a few hints :wink:

Anyway, @Joe is doing a fine job of pioneering this mountain! :smiley:


I have found a few critical pieces of information that I was looking for in the LUA lib. For example examining Encoder.lua was very helpful in understanding what is possible with the control ranges and scales, as well as the files in the ViewControl folder. In general, I think there’s way more here than a person needs to understand in order to develop units.

@odevices, would it be helpful if I (and perhaps any other volunteers out on the bleeding edge here) start a placeholder page on the wiki with some of the relevant info we find? You could eventually replace it with the way you want it to be done, but maybe having something in place when you go to do that would be helpful?


Thanks @Joe - I’ll check that out :slight_smile:

Sounds like a plan!!


The wiki is for you guys, so by all means create and edit pages as you see fit. You can even it use as a public notepad if you like. Just label it as such (Joe’s notes on unit development) and I will stay away from it otherwise I will feel free to edit your content at will :wink: Lastly, I highly suggest not becoming too attached to any documentation that you create now. :bowing_man:


It seems like one of the potential benefits of building in the middle layer is resource efficiency (CPU, memory) as compared to building in the UI layer. For example in another post we were discussing setting an inlet’s value in LUA, and you mentioned:

The Constant object will output the value of the Value parameter at audio rate which is what the SineOscillator’s Fundamental inlet needs.

I am looking, for example, at the Sine OSC unit. It contains a builtin VCA that was added to the unit - not part of the actual DSP object. If that is not used, it could be eliminated, and that is something that the ER-301 doesn’t need to do 48,000 or 96,000 times per second.

Just thinking about some of the larger community submitted patches (e.g. Evil Twin, Ultraviolet), and potentially there are enough of these savings to become substantial in terms of CPU usage?

Just trying to confirm my understanding, I suppose. Any rough idea of what % of CPU a constant object consumes? Or having a branch that will never be modulated?


I recommend just creating the unit in the way that feels most natural to you and not worry about counting CPU cycles at this point. But just to give you a taste, here you go:

  • Empty Chain: 0.015%
  • Constant Object: 0.020%
  • Multiply Object: 0.025%
  • MinMax Object: 0.025%
  • GainBias Object: 0.030%
  • Comparator Object: 0.090%
  • SineOscillator Object: 0.700%

Here is a typical profiling of the Sine Oscillator Unit on 48kHz firmware:

Object Timing
[osc]: 0.7008% (18669 ticks, 375 Hz) 
[tune]: 0.0256% (682 ticks, 375 Hz) 
[tuneRange]: 0.0248% (662 ticks, 375 Hz) 
[f0]: 0.0359% (957 ticks, 375 Hz) 
[f0Range]: 0.0240% (640 ticks, 375 Hz) 
[phase]: 0.0298% (794 ticks, 375 Hz) 
[phaseRange]: 0.0239% (638 ticks, 375 Hz) 
[feedback]: 0.0294% (783 ticks, 375 Hz) 
[feedbackRange]: 0.0235% (627 ticks, 375 Hz) 
[vca]: 0.0251% (669 ticks, 375 Hz) 
[level]: 0.0294% (784 ticks, 375 Hz) 
[levelRange]: 0.0235% (627 ticks, 375 Hz) 
[sync]: 0.0884% (2355 ticks, 375 Hz) 

Sub-chain Timing (all empty)
[Sine Osc(V/oct)]: 0.0150% (400 ticks, 375 Hz) 
[Sine Osc(level)]: 0.0120% (321 ticks, 375 Hz) 
[Sine Osc(feedback)]: 0.0114% (305 ticks, 375 Hz) 
[Sine Osc(phase)]: 0.0129% (343 ticks, 375 Hz) 
[Sine Osc(f0)]: 0.0115% (307 ticks, 375 Hz) 
[Sine Osc(sync)]: 0.0115% (307 ticks, 375 Hz) 

Total Unit Timing
[Sine Osc]: 1.1727% (31240 ticks, 375 Hz) 

Here we can see that adding the internal VCA (consisting of vca, level and levelRange objects) in the Sine Osc unit adds about 0.08%


Looking at what the SDK does, just hooks up internal objects, I’m thinking, it would be possible to build a visual “patcher” of those objects, that then generate LUA modules, kind of like reaktor… I will look into it after the SDK has been documented a bit more…


There’s a compressor in the docs, how come it’s not exposed as a device? :smiley:


Is feedback inside a unit graph possible using a microdelay? Or won’t it compile/work?
I meaning, specifically, can I connect an out to an input at an earlier stage and use a delay to resolve the feedback-loop?


You can implement feedback without Lua using custom unit parameter chains. Set a parameter’s source signal to be itself. No delay needed (necessarily).