So I have been working on an Arduino program that sends MIDI data over USB, and I can't seem to figure out how to pass the function that handles sending of midi data to my main class. It worked at some point but for some reason, it doesn't, and I feel like I have tried every combination of things.
Here is my main file, simplified down to just output the MIDI data over serial:
#include "XiaoPiezoDrum.h"
void sendNoteOn(int note, int velocity, int chan) {
Serial.printf("WORKS! %d %d %d\n", note, velocity, chan);
};
XiaoPiezoDrum drum(9, 2, 3, 4);
void setup() {
drum.setNoteComFunctions(sendNoteOn);
}
Here is what that setNoteComFunctions method looks like:
void XiaoPiezoDrum::setNoteComFunctions(const std::function<void(int, int, int)>& onFunc) {
sendNote = [onFunc](auto && PH1, auto && PH2, auto && PH3) { onFunc(PH1, PH2, PH3); };
}
And here is the relevant parts of the main class definition:
class XiaoPiezoDrum {
public:
XiaoPiezoDrum();
XiaoPiezoDrum(int piezoPin, int rPin, int gPin, int bPin);
void setNoteComFunctions(const function<void(int, int, int)>& onFunc);
void RunCycle();
private:
std::function<void(int, int, int)> sendNote;
}
So everything runs just fine until I call sendNote from within RunCycle , which is just called every loop, and then serial communication just stops suddenly. What am I doing wrong? I also tried using bind instead of a lambda, and the same thing happens. When I just copy the same print statement that is in sendNoteOn in the main file into the lambda in setNoteComFunctions , it prints just fine, so I know the issue is all about linking the function from the main file.
Things I have tried:
I have been banging my head against the keyboard for hours with this. If anybody knows what I'm doing wrong, I'd love an explanation!
EDIT Here is the full code of RunCycle . Many of these variables are instance variables that I left out of the provided class definition, but I know the issue is with the call of sendNote , because if I comment it out, things continue running normally. I have also tried replacing the velocity variable with a fixed integer, and the same thing happened.
void XiaoPiezoDrum::RunCycle() {
double val = sensor.read();
val = (val > 0) ? val : 0;
Serial.println(val);
unsigned long timeElapsed;
int velocity;
MaxVal = (val > MaxVal) ? val : MaxVal;
trigger = val > THRESHOLD && !triggering;
if (val > THRESHOLD && !triggering) trigger = true;
if (trigger) {
triggerTime = millis();
trigger = false;
triggering = true;
triggerBuffer.clear();
}
if (triggering) {
timeElapsed = millis() - triggerTime;
if (timeElapsed < SAMPLE_TIME) {
loopCounter++;
triggerBuffer.addValue(val);
Serial.println(val);
}
else {
velocity = map(round(triggerBuffer.getMax()), 0, 300, THRESHOLD, 127);
Serial.printf("Velocity: %d\n", velocity);
if (comFunctionsSet) sendNote(40, velocity, 1);
noteEndTime = millis();
triggerTime = 0;
triggerBuffer.clear();
triggering = false;
resting = true;
}
}
}
jignatius' answer did it! I should have known I could do that!! Thanks!
I just had to replace
void XiaoPiezoDrum::setNoteComFunctions(const std::function<void(int, int, int)>& onFunc) {
sendNote = [onFunc](auto && PH1, auto && PH2, auto && PH3) { onFunc(PH1, PH2, PH3); };
}
with:
void XiaoPiezoDrum::setNoteComFunctions(const std::function<void(int, int, int)>& onFunc) {
sendNote = onFunc;
}
So glad to have that solved! Thanks!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.