Using Control Surface for embedded instrument #1157
-
|
Hello and thanks for reading, I'm working on an embedded synthesizer project, and would like to use Control Surface to handle the onboard controls, as well as reading MIDI in from Serial and USB. The project seems fully geared towards getting all of this data and then piping it to an external midi interface, but I'm wondering the best way to have all (Serial, USB, potentiometers, etc) route to the instrument on the device (Teensy 4.0. For what it's worth, I'm only partially using the Teensy Audio Library). My current thought is to build a custom class that inherits from MIDI_Interface, then route to my instrument through callbacks on that interface, but wanted to reach out and see if anyone had experience or any ideas. Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
|
To give a code example, here is what I've attempted so far: custom_interface.h #include <Control_Surface.h>
class CustomMidiInterface : public MIDI_Interface {
void update() {};
void sendChannelMessageImpl(ChannelMessage a) {};
void sendSysCommonImpl(SysCommonMessage a) {};
void sendSysExImpl(SysExMessage a) {};
void sendRealTimeImpl(RealTimeMessage a) {};
void sendNowImpl() {};
void handleStall() override {};
};main.cpp #include "custom_interface.h"
#include <Control_Surface.h>
#include "synth_controller.h"
USBMIDI_Interface usb_midi;
CustomMidiInterface custom_midi;
MIDI_PipeFactory<8> pipes;
CCPotentiometer controls{A8, {MIDI_CC::Sound_Controller_5, Channel_1}};
SynthController synthController;
struct MyMIDI_Callbacks : FineGrainedMIDI_Callbacks<MyMIDI_Callbacks> {
void onNoteOff(Channel channel, uint8_t note, uint8_t velocity, Cable cable) {
synthController.stopNote(channel.getRaw(), note, velocity);
}
void onNoteOn(Channel channel, uint8_t note, uint8_t velocity, Cable cable) {
synthController.startNote(channel.getRaw(), note, velocity);
}
void onControlChange(Channel channel, uint8_t control, uint8_t value,
Cable cable) {
synthController.onParamChange(control, value);
}
} callback;
void setup() {
custom_midi << pipes << usb_midi;
custom_midi << pipes << Control_Surface;
custom_midi.setCallbacks(callback);
Control_Surface.begin();
}
void loop() {
Control_Surface.loop();
}So attempting to have notes and CCs come in via external midi and route to |
Beta Was this translation helpful? Give feedback.
-
|
What you describe should work fine, let me know if you run into trouble. If all you need to do is accept MIDI messages from a pipe, then inheriting from #include <Control_Surface.h>
struct MySynthController : TrueMIDI_Sink {
// Called when we receive a message over a pipe.
void sinkMIDIfromPipe(ChannelMessage msg) override {
switch (msg.getMessageType()) {
case MIDIMessageType::NoteOff:
Serial << "stop note #" << msg.getData1() << " on " << msg.getChannel() << endl;
break;
case MIDIMessageType::NoteOn:
Serial << "start note #" << msg.getData1() << " on " << msg.getChannel() << endl;
break;
case MIDIMessageType::ControlChange:
Serial << "controller #" << msg.getData1() << " " << msg.getData2() << " on " << msg.getChannel()<< endl;
break;
}
}
// Similar handlers for the other message types.
void sinkMIDIfromPipe(SysExMessage) override {}
void sinkMIDIfromPipe(SysCommonMessage) override {}
void sinkMIDIfromPipe(RealTimeMessage) override {}
};
MySynthController synth;
USBMIDI_Interface usb_midi;
MIDI_PipeFactory<3> pipes;
NoteButton btn{2, MIDI_Notes::C[4]};
void setup() {
usb_midi >> pipes >> synth;
Control_Surface >> pipes >> synth;
usb_midi >> pipes >> Control_Surface;
Serial.begin(115200);
Control_Surface.begin();
}
void loop() { Control_Surface.loop(); }When the Arduino receives a note message over MIDI USB, or if you press the button on pin 2, you should see the messages being printed by the |
Beta Was this translation helpful? Give feedback.
What you describe should work fine, let me know if you run into trouble.
If all you need to do is accept MIDI messages from a pipe, then inheriting from
MIDI_Interfaceand usingMIDI_Callbackswould be overkill, though. To interact with pipes, you just need to implement theTrueMIDI_Sinkand/orTrueMIDI_Sourceinterfaces (depending on whether you want to send or receive). Here's a minimal example: