How do the Mute buttons work on the Fundamental/Mutes module?


I’m a beginner at module development. I’ve successfully taken the PLAY module by Clément Foulc and added some new inputs and added some functionality. The PLAY module uses Next and Previous buttons to select the active sample slot. I’d like to change how that works. I’d like to have the following:

  1. Three LEDBezelLights (green), similar to the Fundamental/Mute module. Clicking on one of the three lights selects the corresponding sample slot (0,1, or 2). They’ll act like radio buttons in HTML.

What I’ve got done so far looks like this:

enum ParamIds {

enum LightIds {

// Later in the code...

// You might notice that I haven't created my 3 lights yet.  I started with just one light, and since it's not responding to mouse clicks, I'm trying to get that working before adding the additional two lights.

addParam(createParam<LEDBezel>(Vec(52, 69), module, Bsampler::SAMPLE_SELECT_PARAM));
addChild(createLight<LEDBezelLight<GreenLight>>(Vec(53, 70), module, Bsampler::SAMPLE_SELECT_LIGHT));

This is very similar to what the Mutes module does. That’s where I start getting confused. In the Mutes module, these lines of code appear to be responsible for handling the mouse-click event on the mute buttons:

if (muteTrigger[i].process(params[MUTE_PARAM + i].getValue() > 0.f))
	state[i] ^= true;

In English, this appears to be saying, “Hey muteTrigger input, please check the value of the mute parameter and if it’s ON, then toggle the mute status.”

This is really strange to me and I’m pretty confused. What is the muteTrigger[i].process(…) doing? Where is the code that looks for a mouse click? What if I don’t have a CV input that corresponds to the parameter?

Let me rephrase my question, just in case my description above is confusing. I’d like to have a radio button group with three buttons that respond to mouse clicks. That’s basically it!

Thanks! Bret

There are many ways to make radio buttons. Ours is terrible, but you can see it in our EV3 module.

What the trigger line means is, hey trigger check this value and return true only when the value changes from 0 to 1.

This is in fact the code that is handling the mouse click. The state of the buttons is stored in the params array. When a button is pressed down, the corresponding param value is 1.f (1 volt), and when it is not pressed down its value is 0.f (0 volts). The min and max values are set on line 28 of Fundamental’s Mutes.cpp:

configParam(MUTE_PARAM + i, 0.0, 1.0, 0.0, string::f("Ch %d mute", i+1));

The muteTrigger.process(...) piece of code is checking to see if the param has gone from “off” (0.f) to “on” (1.f).

This is how I’ve always seen button presses handled in VCV Rack plugins.

You can take a look at the code for my Boly Puttons module on GitHub for an example of how I implemented radio buttons. It’s not the prettiest implementation, but it works :slight_smile: Look at the checkForParamChanges and switchOffAllButtonsButOne methods. Good luck!

1 Like

Oooohhh! Thanks for explaining this. I think that I finally now understand. Just to reiterate,

params[MUTE_PARAM + i].getValue()

^-- This code will get the value of the button, which will be either 0 or 1.

However, we’re not so interested in the immediate value of the button, but whether is has changed from 0 to 1. That’s where the muteTrigger.process(...) part comes into play. muteTrigger is of type dsp::BooleanTrigger, which handles to annoying task of having to keep track of the state changes of the mute button (aka mute parameter) to determine if it has gone from 0 to 1.

Awesome! It all makes sense now!

1 Like