cs-midi/MIDI_Senders/RelativeCCSender.hpp

60 lines
1.8 KiB
C++

#pragma once
#include <Control_Surface/Control_Surface_Class.hpp>
#include <AH/Arduino-Wrapper.h>
BEGIN_CS_NAMESPACE
enum relativeCCmode {
TWOS_COMPLEMENT,
BINARY_OFFSET,
SIGN_MAGNITUDE,
NEXT_ADDRESS = 4,
REAPER_RELATIVE_1 = TWOS_COMPLEMENT,
REAPER_RELATIVE_2 = BINARY_OFFSET,
REAPER_RELATIVE_3 = SIGN_MAGNITUDE,
TRACKTION_RELATIVE = TWOS_COMPLEMENT,
MACKIE_CONTROL_RELATIVE = SIGN_MAGNITUDE,
KORG_KONTROL_INC_DEC_1 = NEXT_ADDRESS,
};
class RelativeCCSender {
public:
static uint8_t toTwosComplement7bit(int8_t value) { return value & 0x7F; }
static uint8_t toBinaryOffset7bit(int8_t value) { return value + 64; }
static uint8_t toSignedMagnitude7bit(int8_t value) {
uint8_t mask = value >> 7;
uint8_t abs = (value + mask) ^ mask;
uint8_t sign = mask & 0b01000000;
return (abs & 0b00111111) | sign;
}
static uint8_t mapRelativeCC(int8_t value) {
switch (mode) {
case TWOS_COMPLEMENT: return toTwosComplement7bit(value);
case BINARY_OFFSET: return toBinaryOffset7bit(value);
case SIGN_MAGNITUDE: return toSignedMagnitude7bit(value);
case NEXT_ADDRESS: return value < 0 ? -value : value;
default: return 0;
}
}
static void send(long delta, MIDIAddress address) {
if (delta < 0 && mode == NEXT_ADDRESS)
address = address + 1;
while (delta != 0) {
long thisDelta = constrain(delta, -15, 15);
uint8_t msgVal = mapRelativeCC(thisDelta);
Control_Surface.sendControlChange(address, msgVal);
delta -= thisDelta;
}
}
static void setMode(relativeCCmode mode) { RelativeCCSender::mode = mode; }
private:
static relativeCCmode mode;
};
END_CS_NAMESPACE