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

Middle Layer SDK (aka patching with Lua)



Will lua programming for monome norns have any bearing on lua programming for er-301?


The idea is probably similar - Lua is used for the mapping of controls and basic logic to a DSP backend. Probably nothing notable beyond that.


So, is anyone actively building their own units using Lua in the middle layer? Unless I’ve missed some posts, the only ones I’ve seen are the ones @Joe built on those two threads. I’ve been following the forum since before the middle layer opened up and given people’s excitement leading up to it and afterwards I was expecting there would be a flood of heads writing them. But I feel like that hasn’t happened for whatever reason.

Please don’t mistake my inquiry as a criticism of any sort, I’m just genuinely curious. Trust me, I’ve got plenty of depths to explore with the ER-301 as it is, there’s so much to play with Brian’s updates.


I’d be interested to know too.

I think there are two things making middle layer patching kind of tough right now.

The development environment is a bit unforgiving at this point. You have to write the code on a computer, transfer it to the SD card, load it on the ER-301 and see what happens. If anything goes kaboom, then back to the computer to debug from the crash report. It can potentially be a lot of round trips, especially if you’re trying to learn the syntax and the SDK.

Also, while there’s been a good bit of documentation provided, so far it’s mostly code annotations extracted from the classes themselves, and a couple of purposefully commented examples.

So basically, the middle layer seems like a tough place for inexperienced coder and/or the feint of heart at this point. I feel there’s lots of potential to be discovered and tapped here though!

I guess my follow on question would be if someone is interested in middle layer patching but not doing it now, what do they feel like they’d need to get started?


Just a few more hours in the day… :wink:


Same here… I could probably find time to develop, but not work out what is effectively a challenging puzzle at the moment - there are not enough hours in the day, or days in the year for that matter :wink:


I’ve highlighted some of the challenges of working with the middle layer at this point in time. One thing I thing my spark some interest is to highlight some of the advantages of working with the middle layer SDK. In other words, what can you do in the middle layer that you can’t do in the UI layer, but without yet having access to the DSP layer?

I’m not sure they are 100% clear in my mind at this point, but I’ll take a shot at what I think they are:

  • You can create your own custom controls. For example in a custom unit, the linear custom control has a hard-coded range of -5.0 to 5.0. You could, for example, create one that goes from 0.0 to 5.0 if a negative value is not applicable.

  • You have more freedom in routing. In the UI you are restricted to a left-to-right and subchain type routing setup. I think a lot of us have used the trick of either creating a linear control with a subchain or a sample recorder/player arrangement to make signals available at the places we want it inside of a custom unit. Whereas with the SDK, this could be done more directly, eliminating custom controls that are not meant for interaction, and probably also reducing CPU usage and latency in the case of the sample recorder/players.

  • You could create additional custom settings in the unit header menu (though I’m not sure how these might be applied yet).

  • Since you are working with DSP objects and not units, you don’t need to include all of the pieces of a unit if they aren’t needed (again, potential CPU savings).

  • Obviously with larger patches, at some times the UI can get a bit unwieldy, and code can be cleaner/easier to manage.

Do those sound accurate? What else have I missed?


Given this list, I think I need to climb the custom unit learning curve before attempting the middle layer learning curve. Because, it sounds mainly useful for taking a custom unit, and refactoring it for better UI and CPU usage.

So in other words, you won’t feel compelled to use it until you’re pretty deep in the weeds with custom units.


I think a good understanding of working with custom units would be a pretty strong advantage.

Given what I’ve been able to figure out about the SDK so far, if I wanted to build a middle layer unit [would these just be called a “Unit” or “3rd Party Unit” vs. "Custom Unit?], I would probably start it in the UI layer, with a Custom unit container, and get as far as I could.

The immediate visual and audible result vs. having to move it via SD card to test it out would be a huge time saver in designing it, I’d think. Then once it was working, or I’d hit the wall with what I could do in the UI layer, I’d move it to code, and would have the design either done or mostly done, and just be optimizing the processor cycles and user experience.

But these are just my impressions so far based on a very small amount of time spent with the SDK.


I like the term ‘bespoke’ units for third party units written in Lua.


Well, bumping this post inspired me to spend a little time with the SDK this eve, so thanks for that @iiii! :slight_smile:

This library contains the ring modulator I made the “how to” video about, and also a new bespoke unit, called the Bespoke BPF (named as such because I’m sure @odevices will create a better band pass filter in the future). If you copy the folder to your ER-301\libs folder, you should see both of these under the Experimental category.

The Bespoke BPF has controls for f0, V/Oct, Q, and bw (bandwidth). I do not recommend raising Q above 0.3 or you start to get some weird harmonics. Here’s a short video of white noise into the Bespoke BPF, and adjusting f0, bw, and Q (no sound in the video).

Would definitely be interested in thoughts on it.

Joe’s Bespoke ER-301 Units


Outside of the fact that they both use Lua the role of Lua in each device is fairly different. Here we have Lua being used to describe/configure signal processing chains which run independent of the Lua code which created the chains. In the case of norns Lua code is entirely responsible for all the control logic to for one of several different opaque DSP “engines” (which are defined in Supercollider’s sclang).


Digging that FM operator unit!


If I want to create a DSP object, say, a LPF, that has no controls showing, should something like this suffice to make it operational and set its frequency? Would “hardSet” be used here?

local lpf = self:createObject("StereoLadderFilter","filter")

Also, what is the last argument of line 1: “filter” for?

If I create 2 LPFs, should these be unique? E.g.:

local lpf1 = self:createObject("StereoLadderFilter","filter1")
local lpf2 = self:createObject("StereoLadderFilter","filter2")


The 2nd parameter is the (unique) name of the object under which it will be stored in the object table. Later you can get access to your objects outside of this routine via self.objects.filter1 and self.objects.filter2.

This name is also used to identify what data belongs to what object when saving/loading presets. So for example if you change the name of an object then presets made previously will not restore that particular object’s state anymore.


Thanks! Do all of the inlets on a DSP object have to be connected to something in order for the object to work properly? Again using the example of the LPF:

Inlet 	mVoltPerOctave { "V/Oct" }
Inlet 	mResonance { "Resonance" }
Inlet 	mFundamental { "Fundamental" }

Would all of these need to be connect() 'ed (for example to a GainBias) in order for the LPF to work? Or could some of them just be hardSet and left unconnected with no controls/subchain?


No. The default value (unless otherwise specified) for an inlet is zero.



Hehe, I love it when @Joe starts asking questions like this, it kinda feels like I am doing the asking… I am not sure how strange that is, but I mean it as a sincere compliment!


It also means that he is up to something.


Hehe yep - exactly :smiley:

All very exciting… the first signs of surface water disturbance caused by a monster rising from the deep!