Simple Expander example / tutorial?

I am planning to create my first expander module and am having some trouble finding clear documentation/example for how to go about it.

For my module, communication will be in one direction - the expander will send data to the master module, but there’s no need for the master to send data to the expander.

I’ve seen Module expanders tutorial?, but it mostly seems to be focussed on a specific need to send data bidirectionally and only discusses that aspect of the implementation. (frustratingly there’s a broken link on that thread to a tutorial that @Vortico wrote which was perhaps the basic doc I’m looking for, but it’s gone: https://github.com/VCVRack/Rack/issues/1204#issuecomment-469797678). Archive.org doesn’t have a copy.

I’m looking for a more general (and gentle) introduction to the basics. I’ve tried some code diving looking at Bogaudio, Stoermelder and Squinky expanders, but everything I’ve reviewed so far is a lot more complicated than “just the basics” of expander-ness due to the other complexities of each of those modules.

Things I’m looking for:

  • Clear explanation of timing. If an expander writes to its producerMessage, will the master module get that data on the same sample frame? What, if any, latency needs to be considered?
  • How are expanders “connected”? What is the master expected to do to initialize the rightExpander or leftExpander variables. Similarly, what does the expander need to do. I see example code checking module pointers and moduleId values - not clear how that is expected to be managed.
  • If I want to have multiple expanders all feeding into the same master module, do I need to send data from expander1 to expander2 to … then finally to the master? Or can I send data directly to the master from each expander?

I’m sure I’ll have more questions once I get something in a debugger. Can anyone suggest specific modules that are good examples of the basics (or better yet, a purpose built expanders tutorial?)

2 Likes

yeah, it’s too bad andrew took all that good stuff down.

4 Likes

Did this post not help you?

1 Like

That tutorial thread has most of the bases covered but you may want to read the Rack implementation of expanders (sometimes at least for me the simplest thing is to go to the source code).

It’s mostly here; start with Engine_stepFrame and see that messages are swapped right after cables are processed (so that’s your timing question) as well as exactly how they’re swapped (not much going on). Engine::stepBlock checks for new expander pointers by calling Engine_updateExpander_NoLock on the left (side == false) and right (side == true), and Engine::removeModule_NoLock removes expander pointers during module removal. I’m sure I’m missing something but that’s a lot of it right there.

2 Likes

Slaps head. I spent so much time diving into third party module code trying to intuit how they work, I ran out of steam before jumping into the Engine sources. Yes - this helps a lot. Between this and @CountModula and @clone45 's examples on that original thread, I think I have enough to get started.

Thanks!

1 Like

Nice! Looking forward to seeing what you come up with! :slight_smile:

Here’s what I’m up to - an expander for my MIDI Recorder module: Chinenual Development Thread - #36 by Chinenual

1 Like