C++ encoderChanged() Question, re: updating from knobs only when needed

Starting to really get into Lich programming now.
but have a question

if i put:

adsr.SetAttackTime(getParameterValue(PARAMETER_A));

in processAudio it updates my parameter correctly.
(I implemented a class for adsr, this all works right, and I can change attack time on my envelope which is on CV out2)

so that’s basically “Lich can do it”, but I looked into the API and thought I could take this out of the audio thread, where it doesn’t want to be.

the following is from Martin’s Midi Modular patch, I didn’t test but presume it works.

void buttonChanged(PatchButtonId bid, uint16_t value, uint16_t samples){
switch(bid){
case BUTTON_A:
out.velocity = value ? 80 : 0;
sendMidi(MidiMessage::note(out.channel, out.note, out.velocity));
break;
case BUTTON_B:
break;
}
}

however I expected the following to do similar for the knobs, and it doesn’t.

void 	encoderChanged (PatchParameterId pid, int16_t delta, uint16_t samples){
  switch(pid){
	case PARAMETER_A:
	  adsr.SetAttackTime(getParameterValue(PARAMETER_A));
	  break;
  case PARAMETER_B:
	  adsr.SetDecayTime(getParameterValue(PARAMETER_B));
	  break;
  case PARAMETER_C:
	  adsr.SetSustainLevel(getParameterValue(PARAMETER_C));
	  break;
  case PARAMETER_D:
	  adsr.SetReleaseTime(getParameterValue(PARAMETER_D));
	  break;
  }
}

So what did I miss? (it’s bound to be valuable info ).

There is no such thing as “encoderChanged” among methods of Patch abstract base class from which you inherit, see full list of them here.

Also, there isn’t really an audio thread as such as this runs on baremetal microcontroller hardware without desktop OS, obviously. Instead of that we have a callback from audio codec’s DMA transfer completion. Both audio processing function and various other callbacks are called from the same function, effectively. So if you wanted to run something on lower priority, that’s not gonna happen by moving anything out of processAudio.

If you wanted to avoid having minor changes to your data (i.e. due to ADC noise), you might have some luck with variables with hysteresis.

Thanks for response. This is really helpful.
“encoderChanged” is third on list that you linked (hence, it compiles), that’s the place I found it. I guess it’s to pick up the actual encoder rather than the knobs . Anyway, safe to ignore :wink:

I’d assumed buttonChanged( was on a different thread because it was called when a button was pressed and I remembered being told that interrupts were used to pick stuff up.
So looked on the API to find something similar for the knobs.

Anyway, got my ADSR coming out of CV OUT2 and it’s working perfectly.
1V/oct tracking is spot on.
Lich reconnects to my crappy midi keyboard when the usb goes down since firmware update.
Audio Interface just appeared unexpectedly and could come in handy.
…and I have a pretty good idea about handling the inputs and outputs.

good times :slight_smile:

Well not noticing that this thing exist was a bit embarrassing for me. However, it looks like that callback is never called from current firmware version. My guess would be that it was intended for handling encoders on that control parameters on certain hardware (Magus, Genius and some earlier prototypes), but eventually phased out. Maybe such reactive programming didn’t feel right. Anyway, the firmware resets pointer to that callback to NULL and never does anything with it, that’s why I didn’t even know that such thing is out there.

You’re right that interrupts for GPIO events are used when possible to avoid polling for button state, but this is just an implementation detail for checking for button presses. The callback is still called by patch itself before processing next block of audio.