Hi everyone!
Is there a tutorial or a simple example to check out for module expanders?
I have one module that could use an expander with some extra knobs only, so nothing too fancy.
Thanks!
Hi everyone!
Is there a tutorial or a simple example to check out for module expanders?
I have one module that could use an expander with some extra knobs only, so nothing too fancy.
Thanks!
Stoermelder Strip is probably a good example to go on as it manipulates all modules connected to it.
Impromptu, Squinky-Labs and Frozen Wasteland also have expanderâs
This is also a compact example, which had been updated by Andrew as the code evolved when he was designing expanders:
Yes, thatâs the source of truth, and much easier to understand than looking in our mixer-expander code! Thanks @marc_boule
Definitely! My expander code is horrible to look at in particular, brain cramps are guaranteed
Nice, thanks for the info!
Clocked looks like a nice example too Marc
Btw. Any thoughts about:
std::numeric_limits<float>::quiet_NaN()
. Using another float to indicate a boolean state would be possible also. How are others doing this?Couldnât you pass a pointer to the port and work directly with its member functions?
Yes, but then when you want to also have lights, or switches, or other stuff on the same expander, then the types would not work. Perhaps casting it all to void pointers would work, but doesnât seem really elegant. Float, covers pretty much all (except for a current project Iâm working on where I have to cast 4 chars per float since Iâm mixing signals and text to an expander, ouch!).
You may be right on that, I havenât enough experience with development in C++ to know whatâs elegant and what isnât. I suggested it because of this comment in Module.hpp
:
If you intend to receive messages from an expander, allocate both message buffers with identical blocks of memory (arrays, structs, etc). Remember to free the buffer in the Module destructor. Example:
rightExpander.producerMessage = new MyExpanderMessage; rightExpander.consumerMessage = new MyExpanderMessage;
You must check the expander moduleâs
model
before attempting to write its message buffer. Once the module is checked, you can reinterpret_cast its producerMessage at no performance cost.
After writing my own expander I have to say this was a bad suggestion: You shouldnât access members directly from other modules because youâll get threading-issues sooner or later. At least when the engine uses more than one thread.
I just ended up implementing a thread-safe message bus - technically still true to the eurorack format, since the 16 pin connector carries 2 buses.
Our modular mixers send data in both directions. Audio always goes left to right, but solo information travels in both directions. You can totally do whatever you want. And hope that people find the resulting thing useful.
So can you just randomly mess with another module? That seems like it might be a bad thing if an expander has undocumented functionality. On the other hand the potential to randomly mess up an otherwise boring patch might be interesting.
I donât have the programming skills to do this but could someone make a quantussy cell that was an expander? So that i could have a quantussy ring that doesnât take ages to connect up? I love the Frozen Wasteland Quantussy cell, if you havenât tried it you should.
Well, yes and no. You can âseeâ the modules on both sides, but you can really only mess with them if you know what is inside, which in practice means that you made them and they are in the same plugin. You could try to reach into âotherâ modules and mess with them, but it would be very fragile and difficult.
Also, the âotherâ module probably wonât talk to you if it doesnât recognize you.
The expander protocol proper really wants you to send/receive data, not do arbitrary munging.
So, without getting too crazy, arbitrary modules canât do crazy things to other modules.
Also, anything you do with the Module
pointer is not thread-safe unless you write to its producerMessage
or read from its consumerMessage
and then set messageFlipRequested = true
. This is important when using >1 thread.
Iâd be interested to know more about the thread-safe bus you mention, if ever you have it in your github or can post more info here, I might need to do something like that in my current project, since I may need to daisy chain a dozen (or two) small expanders that will carry audio, and want to avoid a signal having to ripple through an expander chain when communicating with the mother module. Cheers!
I just went ahead and pushed some of the work Iâve been doing:
I hadnât pushed it previously as Iâm not ready for release of this module yet, but this should give you a good idea of what Iâm doing.
a module registers itself:
with a message being sent as so:
my plan is to expand it before actual release, to include message tags, but it works fairly well as-is.
it uses a mutex guard around the vector that stores the data, leaving only the most recent message from each publisher. any subscriber can get a copy of the most recent messages.