andrewm@0
|
1 /*
|
andrewm@0
|
2 TouchKeys: multi-touch musical keyboard control software
|
andrewm@0
|
3 Copyright (c) 2013 Andrew McPherson
|
andrewm@0
|
4
|
andrewm@0
|
5 This program is free software: you can redistribute it and/or modify
|
andrewm@0
|
6 it under the terms of the GNU General Public License as published by
|
andrewm@0
|
7 the Free Software Foundation, either version 3 of the License, or
|
andrewm@0
|
8 (at your option) any later version.
|
andrewm@0
|
9
|
andrewm@0
|
10 This program is distributed in the hope that it will be useful,
|
andrewm@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
andrewm@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
andrewm@0
|
13 GNU General Public License for more details.
|
andrewm@0
|
14
|
andrewm@0
|
15 You should have received a copy of the GNU General Public License
|
andrewm@0
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
andrewm@0
|
17
|
andrewm@0
|
18 =====================================================================
|
andrewm@0
|
19
|
andrewm@0
|
20 OscMidiConverter.h: converts incoming OSC messages to outgoing MIDI
|
andrewm@0
|
21 messages with adjustable ranges and parameters.
|
andrewm@0
|
22 */
|
andrewm@0
|
23
|
andrewm@0
|
24 #ifndef __touchkeys__OscMidiConverter__
|
andrewm@0
|
25 #define __touchkeys__OscMidiConverter__
|
andrewm@0
|
26
|
andrewm@0
|
27 #include <vector>
|
andrewm@0
|
28 #include "Osc.h"
|
andrewm@0
|
29 #include "MidiOutputController.h"
|
andrewm@0
|
30 #include "PianoKeyboard.h"
|
andrewm@0
|
31 #include "MidiKeyboardSegment.h"
|
andrewm@0
|
32
|
andrewm@0
|
33 /* OscMidiConverter
|
andrewm@0
|
34 *
|
andrewm@0
|
35 * This class handles the sending of MIDI output messages of a particular type
|
andrewm@0
|
36 * (control change, aftertouch, pitch wheel) in response to incoming OSC messages.
|
andrewm@0
|
37 * Each object takes responsibility for one type of MIDI output but can take
|
andrewm@0
|
38 * several types of OSC message to control it.
|
andrewm@0
|
39 */
|
andrewm@0
|
40
|
andrewm@0
|
41 class OscMidiConverter : public OscHandler {
|
andrewm@0
|
42 public:
|
andrewm@0
|
43 // Behavior for out-of-range inputs.
|
andrewm@0
|
44 enum {
|
andrewm@41
|
45 kOutOfRangeIgnore = 1,
|
andrewm@0
|
46 kOutOfRangeClip,
|
andrewm@0
|
47 kOutOfRangeExtrapolate
|
andrewm@0
|
48 };
|
andrewm@0
|
49
|
andrewm@0
|
50 private:
|
andrewm@0
|
51 // Structure holding information about a given OSC source
|
andrewm@0
|
52 struct OscInput {
|
andrewm@0
|
53 int uniqueId; // ID to keep track of recent values
|
andrewm@0
|
54 int oscParamNumber; // Parameter number in the OSC message we map
|
andrewm@0
|
55 float oscMinValue; // Min and max of its input range
|
andrewm@0
|
56 float oscMaxValue;
|
andrewm@0
|
57 float oscScaledCenterValue; // Value of the input that should correspond to control center,
|
andrewm@0
|
58 // pre-normalized to 0-1 range
|
andrewm@0
|
59 int outOfRangeBehavior; // What happens at the edge of the range
|
andrewm@0
|
60 };
|
andrewm@0
|
61
|
andrewm@0
|
62 public:
|
andrewm@0
|
63 // Constructor
|
andrewm@0
|
64 OscMidiConverter(PianoKeyboard& keyboard, MidiKeyboardSegment& segment, int controllerId);
|
andrewm@0
|
65
|
andrewm@0
|
66 // ***** MIDI methods *****
|
andrewm@0
|
67
|
andrewm@0
|
68 // Provide a reference to the MidiOutputController which actually sends the messages
|
andrewm@0
|
69 void setMidiOutputController(MidiOutputController* m) { midiOutputController_ = m; }
|
andrewm@0
|
70
|
andrewm@0
|
71 // Set which control this object is handling. If minimum or maximum values are specified,
|
andrewm@0
|
72 // then the control will never exceed this range no matter what OSC messages come in.
|
andrewm@0
|
73 // use14BitControl specifies whether a 14-bit (paired) MIDI CC message should be used,
|
andrewm@0
|
74 // for relevant values of message.
|
andrewm@0
|
75 void setMidiMessageType(int defaultValue = -1, int minValue = -1,
|
andrewm@0
|
76 int maxValue = -1, int centerValue = -1, bool use14BitControl = false);
|
andrewm@0
|
77
|
andrewm@0
|
78 // Set whether this converter passes through incoming CC messages from the MIDI input,
|
andrewm@0
|
79 // and if so, which one. Doesn't need to be the same CC coming in as going out.
|
andrewm@0
|
80 void listenToIncomingControl(int controller, int centerValue = -1, bool use14BitControl = false);
|
andrewm@0
|
81
|
andrewm@0
|
82 // Force a resend of the current value
|
andrewm@0
|
83 void resend(int channel);
|
andrewm@0
|
84
|
andrewm@0
|
85 // Send the default controller value on the specified channel. Typically used
|
andrewm@0
|
86 // before note onset.
|
andrewm@0
|
87 void sendDefaultValue(int channel);
|
andrewm@0
|
88
|
andrewm@0
|
89 // Return the current value of the MIDI controller without sending it
|
andrewm@0
|
90 int currentControllerValue(int channel);
|
andrewm@0
|
91
|
andrewm@0
|
92 // ***** OSC methods *****
|
andrewm@0
|
93
|
andrewm@0
|
94 // This message specifies an OSC path to be mapped to MIDI, along with its input ranges which
|
andrewm@0
|
95 // correspond to the complete specified MIDI range.
|
andrewm@0
|
96 void addControl(const string& oscPath, int oscParamNumber, float oscMinValue, float oscMaxValue,
|
andrewm@0
|
97 float oscCenterValue, int outOfRangeBehavior);
|
andrewm@0
|
98 void removeControl(const string& oscPath);
|
andrewm@0
|
99 void removeAllControls();
|
andrewm@0
|
100
|
andrewm@0
|
101 // These methods update the range for an existing control
|
andrewm@0
|
102 void setControlMinValue(const string& oscPath, float newValue);
|
andrewm@0
|
103 void setControlMaxValue(const string& oscPath, float newValue);
|
andrewm@0
|
104 void setControlCenterValue(const string& oscPath, float newValue);
|
andrewm@0
|
105 void setControlOutOfRangeBehavior(const string& oscPath, int newBehavior);
|
andrewm@0
|
106
|
andrewm@0
|
107 // Reset any active previous values on the given channel
|
andrewm@0
|
108 void clearLastValues(int channel, bool send = true);
|
andrewm@0
|
109
|
andrewm@0
|
110 // OSC Handler Method: called by PianoKeyboard (or other OSC source)
|
andrewm@0
|
111 bool oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data);
|
andrewm@0
|
112
|
andrewm@0
|
113 // Destructor
|
andrewm@0
|
114 ~OscMidiConverter() {}
|
andrewm@0
|
115
|
andrewm@0
|
116 private:
|
andrewm@0
|
117 // ***** Private Methods *****
|
andrewm@0
|
118 int idWithChannel(int channel, int inputId) { return (inputId << 4) + channel; }
|
andrewm@0
|
119 void sendCurrentValue(int port, int channel, int note, bool force);
|
andrewm@0
|
120
|
andrewm@0
|
121 // ***** Member Variables *****
|
andrewm@0
|
122
|
andrewm@0
|
123 PianoKeyboard& keyboard_; // Main piano keyboard controller
|
andrewm@0
|
124 MidiKeyboardSegment& keyboardSegment_; // Which segment of the keyboard this mapping is using
|
andrewm@0
|
125 MidiOutputController* midiOutputController_; // Class handling MIDI output
|
andrewm@0
|
126
|
andrewm@0
|
127 int controller_; // Which MIDI control to use
|
andrewm@0
|
128 bool controllerIs14Bit_; // Whether to use a paired MIDI CC
|
andrewm@0
|
129 int controlMinValue_, controlMaxValue_; // Ranges control can take
|
andrewm@0
|
130 int controlCenterValue_; // The center value to use when all OSC inputs are 0
|
andrewm@0
|
131 int controlDefaultValue_; // Default value for the control on new notes
|
andrewm@0
|
132
|
andrewm@0
|
133 int lastUniqueId_; // Global unique ID for input messages
|
andrewm@0
|
134
|
andrewm@0
|
135 int incomingController_; // Which controller we listen to from the MIDI input
|
andrewm@0
|
136 bool incomingControllerIs14Bit_; // Whether the input controller is 14 bit
|
andrewm@0
|
137 int incomingControllerCenterValue_; // The center value to subtract from the incoming controller
|
andrewm@0
|
138
|
andrewm@0
|
139 std::map<std::string, OscInput> inputs_; // OSC sources for this MIDI output
|
andrewm@0
|
140 std::map<int, float> lastValues_; // Recently received values from each OSC input
|
andrewm@0
|
141
|
andrewm@0
|
142 float currentValue_[16]; // Current sum value of all inputs for each channel
|
andrewm@0
|
143 int lastOutputValue_[16]; // The last value we sent out; saved to avoid duplicate messages
|
andrewm@0
|
144 };
|
andrewm@0
|
145
|
andrewm@0
|
146 #endif /* defined(__touchkeys__OscMidiConverter__) */
|