tttapa / Control-Surface

Arduino library for creating MIDI controllers and other MIDI devices.
GNU General Public License v3.0
1.25k stars 140 forks source link

Rotary Encoder - Directional Note On/Off Triggers #363

Closed Ginjah6205 closed 3 years ago

Ginjah6205 commented 3 years ago

Is your feature request related to a problem? Please describe. Hi! I am not sure if this is the correct way to ask for help so please tell me if need be! :)

I have rotary encoders and what I am trying to do is configure them in such a way that when I turn the encoder in one direction (lets say CW) it sends a MIDI note On and then immediately after Note Off, then when it is turned another step in that same direction (CW) the same thing happens. The same would also be the case with a CCW rotation - I turn counter clock wise, a different note turns on then back off.

I am not even sure the library has this capability for this but I'd love to see it.

Thank you in advance. :)

#include <Encoder.h> // Include the Encoder library.
// This must be done before the Control Surface library.
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

using namespace MIDI_Notes;

// Instantiate a CCAbsoluteEncoder object
CCAbsoluteEncoder enc = {
  {2, 3},       // pins
  MIDI_CC::Pan, // MIDI address (CC number + optional channel)
  1,            // optional multiplier if the control isn't fast enough
};

 //Encoder PushButton
NoteButton button = {
  9,                       // Push button on pin 5
  {note(C, 4), CHANNEL_1}, // Note C4 on MIDI channel 1
};

void setup() {

  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}
tttapa commented 3 years ago

This can be done by creating your own MIDI Sender and then inheriting from the MIDIRotaryEncoder class template with your sender as the template argument.

#include <Encoder.h>
#include <Control_Surface.h>

struct CustomRelativeNoteSender {
  void send(long delta, MIDIAddress address) {
    while (delta > 0) {
      Control_Surface.sendNoteOn(address, 127);
      Control_Surface.sendNoteOff(address, 127);
      --delta;
    }
    while (delta < 0) {
      Control_Surface.sendNoteOn(address + 1, 127);
      Control_Surface.sendNoteOff(address + 1, 127);
      ++delta;
    }
  }
};

class NoteRotaryEncoder : public MIDIRotaryEncoder<CustomRelativeNoteSender> {
  public:
    NoteRotaryEncoder(EncoderPinList pins, MIDIAddress address,
                      int8_t speedMultiply = 1, uint8_t pulsesPerStep = 4)
      : MIDIRotaryEncoder(pins, address, speedMultiply, pulsesPerStep, {}) {}
};

// Instantiate a MIDI over USB interface.
USBMIDI_Interface midi;

using namespace MIDI_Notes;

NoteRotaryEncoder enc = {
  {2, 3},       // pins
  note(C, 4),   // MIDI address (note number + optional channel)
};

void setup() {
  Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
}
Ginjah6205 commented 3 years ago

Thank you very much - this was extremely helpful and the exact solution I needed! Thanks for all of your help with this! :)