then I think you could have two classes, with the following public interfaces:
class MidiLearner{
public:
void setup(int numChannels);
void analogInput(float* analog, unsigned int numFrames);
void midiInput(int controllerNumber, int value);
int getChannel(int controllerNumber);
};
class Control {
public:
void setAnalog(float analogInputValue);
void setMidi(short midiInputValue);
void setOutputRange(float minOut, float maxOut);
float get();
};
and you would use them as follows:
#include <Bela.h>
#include <vector>
#include "Control.h"
#include "MidiLearner.h"
#include <Midi.h>
std::vector<Control> gControls;
MidiLearner gMidiLearner;
Midi gMidi;
bool gLearning;
bool setup(BelaContext* context,void*)
{
gMidiLearner.setup(context->analogInChannels);
for(unsigned int n = 0; n < context->analogInChannels; ++n){
gControls.emplace_back();
gControls[n].setOutputRange(0, 1);
}
gMidi.readFrom("hw:1,0,0");
gMidi.enableParser(true);
return true;
}
void render(BelaContext* context, void*)
{
if(gLearning)
gMidiLearner.analogInput(context->analogIn, context->analogFrames);
int num;
while((num = midi.getParser()->numAvailableMessages()) > 0){
MidiChannelMessage message;
message = midi.getParser()->getNextChannelMessage();
message.prettyPrint();
if(message.getType() == kmmControlChange){
int controllerNumber = message.getDataByte(0);
int controllerValue = message.getDataByte(1);
if(gLearning)
{
gMidiLearner.midiInput(controllerNumber, controllerValue);
} else {
int control = gMidiLearner.getChannel(controllerNumber);
if(control >= 0)
controls[control].setMidi(controllerValue);
}
}
}
for(unsigned int ch = 0; ch < context->analogInChannels; ++ch)
{
controls[channel].setAnalog(analogRead(context, 0, ch);
}
// in the rest of your code, use
controls[channel].get();
// instead of analogRead(context, frame, channel)
/// somehow turn gLearning into `true`
}
Then every time a new midi input comes in you call setMidi()
and, at least once per block you call setAnalog(analogRead(...))
.
I only provide the interface of the classes above, but the implementation is not done. Do you think you can do that?