From 83652270aa81b3bc67fbee1465360e2c22e0813c Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Thu, 17 May 2018 14:13:13 -0400 Subject: [PATCH] Generate MIDI with Gamepad driver, allow negative CC values in MIDI-CC --- include/gamepad.hpp | 5 ++- src/Core/MIDICCToCVInterface.cpp | 5 +-- src/gamepad.cpp | 60 +++++++++++++++++++++++++------- src/midi.cpp | 2 ++ 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/include/gamepad.hpp b/include/gamepad.hpp index 84cb5299..cd0f71ed 100644 --- a/include/gamepad.hpp +++ b/include/gamepad.hpp @@ -12,11 +12,14 @@ const int GAMEPAD_DRIVER = -10; struct GamepadInputDevice : MidiInputDevice { int deviceId; + std::vector ccs; + void step(); + void updateCc(int index, uint8_t cc); }; struct GamepadInputDriver : MidiInputDriver { - GamepadInputDevice gamepadInputDevices[16]; + GamepadInputDevice devices[16]; GamepadInputDriver(); std::vector getDeviceIds() override; diff --git a/src/Core/MIDICCToCVInterface.cpp b/src/Core/MIDICCToCVInterface.cpp index 20dba917..ba43d335 100644 --- a/src/Core/MIDICCToCVInterface.cpp +++ b/src/Core/MIDICCToCVInterface.cpp @@ -19,7 +19,7 @@ struct MIDICCToCVInterface : Module { }; MidiInputQueue midiInput; - uint8_t cvs[16]; + int8_t cvs[16]; ExponentialFilter ccFilters[16]; int learningId = -1; @@ -64,7 +64,8 @@ struct MIDICCToCVInterface : Module { // Set CV for (int i = 0; i < 16; i++) { if (learnedCcs[i] == cc) { - cvs[i] = msg.value(); + // Allow CC to be negative if the 8th bit is set + cvs[i] = msg.data2; } } } break; diff --git a/src/gamepad.cpp b/src/gamepad.cpp index a52c75a4..dfacc53e 100644 --- a/src/gamepad.cpp +++ b/src/gamepad.cpp @@ -6,9 +6,46 @@ namespace rack { +void GamepadInputDevice::step() { + if (!glfwJoystickPresent(deviceId)) + return; + // Get gamepad state + int numAxes; + const float *axes = glfwGetJoystickAxes(deviceId, &numAxes); + int numButtons; + const unsigned char *buttons = glfwGetJoystickButtons(deviceId, &numButtons); + // Update state + ccs.resize(numAxes + numButtons); + for (int i = 0; i < numAxes; i++) { + // Allow CC value to go negative, but clamp at -127 instead of -128 for symmetry + updateCc(i, clamp((int) (axes[i] * 127), -127, 127)); + } + for (int i = 0; i < numButtons; i++) { + updateCc(numAxes + i, buttons[i] ? 127 : 0); + } +} + +void GamepadInputDevice::updateCc(int index, uint8_t cc) { + if ((int) ccs.size() < index) + return; + + if (cc != ccs[index]) { + ccs[index] = cc; + + // Send MIDI message + MidiMessage msg; + // MIDI channel 1 + msg.cmd = (0xb << 4) | 0; + msg.data1 = index; + msg.data2 = ccs[index]; + onMessage(msg); + } +} + + GamepadInputDriver::GamepadInputDriver() { for (int i = 0; i < 16; i++) { - gamepadInputDevices[i].deviceId = i; + devices[i].deviceId = i; } } @@ -37,31 +74,30 @@ MidiInputDevice *GamepadInputDriver::getDevice(int deviceId) { if (!(0 <= deviceId && deviceId < 16)) return NULL; - return &gamepadInputDevices[deviceId]; + return &devices[deviceId]; } -static GamepadInputDriver *gamepadInputDriver = NULL; +static GamepadInputDriver *driver = NULL; void gamepadStep() { + // Check if the driver has been instantiated + if (!driver) + return; + for (int i = 0; i < 16; i++) { if (glfwJoystickPresent(i)) { - const char *name = glfwGetJoystickName(i); - int numButtons; - const unsigned char *buttons = glfwGetJoystickButtons(i, &numButtons); - int numAxes; - const float *axes = glfwGetJoystickAxes(i, &numAxes); - debug("%d %s", i, name); + driver->devices[i].step(); } } } MidiInputDriver *gamepadGetInputDriver() { - if (!gamepadInputDriver) { - gamepadInputDriver = new GamepadInputDriver(); + if (!driver) { + driver = new GamepadInputDriver(); } - return gamepadInputDriver; + return driver; } diff --git a/src/midi.cpp b/src/midi.cpp index 0c479956..cf333b8b 100644 --- a/src/midi.cpp +++ b/src/midi.cpp @@ -50,6 +50,7 @@ std::vector MidiIO::getDriverIds() { std::string MidiIO::getDriverName(int driverId) { switch (driverId) { + case -1: return "None"; case RtMidi::UNSPECIFIED: return "Unspecified"; case RtMidi::MACOSX_CORE: return "Core MIDI"; case RtMidi::LINUX_ALSA: return "ALSA"; @@ -179,6 +180,7 @@ void MidiInputQueue::onMessage(MidiMessage message) { return; } + // Push to queue if ((int) queue.size() < queueSize) queue.push(message); }