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 TouchkeyPitchBendMapping.h: per-note mapping for the pitch-bend mapping,
|
andrewm@0
|
21 which handles changing pitch based on relative finger motion.
|
andrewm@0
|
22 */
|
andrewm@0
|
23
|
andrewm@0
|
24 #ifndef __touchkeys__TouchkeyPitchBendMapping__
|
andrewm@0
|
25 #define __touchkeys__TouchkeyPitchBendMapping__
|
andrewm@0
|
26
|
andrewm@0
|
27
|
andrewm@0
|
28
|
andrewm@0
|
29 #include <map>
|
andrewm@0
|
30 #include <boost/bind.hpp>
|
andrewm@0
|
31 #include "../TouchkeyBaseMapping.h"
|
andrewm@0
|
32 #include "../../Utility/IIRFilter.h"
|
andrewm@0
|
33
|
andrewm@0
|
34 // This class handles the detection and mapping of vibrato gestures
|
andrewm@0
|
35 // based on Touchkey data. It outputs MIDI or OSC messages that
|
andrewm@0
|
36 // can be used to affect the pitch of the active note.
|
andrewm@0
|
37
|
andrewm@0
|
38 class TouchkeyPitchBendMapping : public TouchkeyBaseMapping {
|
andrewm@0
|
39 friend class TouchkeyVibratoMappingFactory;
|
andrewm@0
|
40 friend class TouchkeyPitchBendMappingFactory;
|
andrewm@0
|
41
|
andrewm@0
|
42
|
andrewm@0
|
43 public:
|
andrewm@0
|
44 enum {
|
andrewm@0
|
45 kPitchBendModeVariableEndpoints = 1,
|
andrewm@0
|
46 kPitchBendModeFixedEndpoints
|
andrewm@0
|
47 };
|
andrewm@0
|
48
|
andrewm@0
|
49 private:
|
andrewm@0
|
50 // Useful constants for mapping MRP messages
|
andrewm@0
|
51
|
andrewm@0
|
52 static const int kDefaultMIDIChannel;
|
andrewm@0
|
53 static const int kDefaultFilterBufferLength;
|
andrewm@0
|
54
|
andrewm@0
|
55 static const float kDefaultBendRangeSemitones;
|
andrewm@0
|
56 static const float kDefaultBendThresholdSemitones;
|
andrewm@0
|
57 static const float kDefaultBendThresholdKeyLength;
|
andrewm@0
|
58 static const float kDefaultSnapZoneSemitones;
|
andrewm@0
|
59 static const int kDefaultPitchBendMode;
|
andrewm@0
|
60 static const float kDefaultFixedModeEnableDistance;
|
andrewm@0
|
61 static const float kDefaultFixedModeBufferDistance;
|
andrewm@0
|
62
|
andrewm@0
|
63 static const bool kDefaultIgnoresTwoFingers;
|
andrewm@0
|
64 static const bool kDefaultIgnoresThreeFingers;
|
andrewm@0
|
65
|
andrewm@0
|
66
|
andrewm@0
|
67 public:
|
andrewm@0
|
68 // ***** Constructors *****
|
andrewm@0
|
69
|
andrewm@0
|
70 // Default constructor, passing the buffer on which to trigger
|
andrewm@0
|
71 TouchkeyPitchBendMapping(PianoKeyboard &keyboard, MappingFactory *factory, int noteNumber, Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
72 Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker);
|
andrewm@0
|
73
|
andrewm@0
|
74 // Copy constructor
|
andrewm@0
|
75 //TouchkeyPitchBendMapping(TouchkeyPitchBendMapping const& obj);
|
andrewm@0
|
76
|
andrewm@0
|
77 // ***** Destructor *****
|
andrewm@0
|
78
|
andrewm@0
|
79 ~TouchkeyPitchBendMapping();
|
andrewm@0
|
80
|
andrewm@0
|
81 // ***** Modifiers *****
|
andrewm@0
|
82
|
andrewm@0
|
83 // Reset the state back initial values
|
andrewm@0
|
84 void reset();
|
andrewm@0
|
85
|
andrewm@0
|
86 // Resend the current state of all parameters
|
andrewm@0
|
87 void resend();
|
andrewm@0
|
88
|
andrewm@0
|
89 // Parameters for pitch bend algorithm
|
andrewm@0
|
90 void setRange(float rangeSemitones);
|
andrewm@0
|
91 void setThresholds(float thresholdSemitones, float thresholdKeyLength);
|
andrewm@0
|
92 void setFixedEndpoints(float minimumDistanceToEnable, float bufferAtEnd);
|
andrewm@0
|
93 void setVariableEndpoints();
|
andrewm@0
|
94
|
andrewm@0
|
95 // Whether we ignore two or three finger touches for calculating pitch bends
|
andrewm@0
|
96 void setIgnoresMultipleFingers(bool ignoresTwo, bool ignoresThree);
|
andrewm@0
|
97
|
andrewm@0
|
98 // ***** Evaluators *****
|
andrewm@0
|
99
|
andrewm@0
|
100 // This method receives triggers whenever events occur in the touch data or the
|
andrewm@0
|
101 // continuous key position (state changes only). It alters the behavior and scheduling
|
andrewm@0
|
102 // of the mapping but does not itself send OSC messages
|
andrewm@0
|
103 void triggerReceived(TriggerSource* who, timestamp_type timestamp);
|
andrewm@0
|
104
|
andrewm@0
|
105 // This method handles the OSC message transmission. It should be run in the Scheduler
|
andrewm@0
|
106 // thread provided by PianoKeyboard.
|
andrewm@0
|
107 timestamp_type performMapping();
|
andrewm@0
|
108
|
andrewm@0
|
109 private:
|
andrewm@0
|
110 // ***** Private Methods *****
|
andrewm@0
|
111 void midiNoteOnReceived(int channel, int velocity);
|
andrewm@0
|
112 void midiNoteOffReceived(int channel);
|
andrewm@0
|
113
|
andrewm@0
|
114 void resetDetectionState();
|
andrewm@0
|
115 void clearBuffers();
|
andrewm@0
|
116
|
andrewm@0
|
117 void engageSnapping();
|
andrewm@0
|
118 void disengageSnapping();
|
andrewm@0
|
119
|
andrewm@0
|
120 void updateCombinedThreshold();
|
andrewm@0
|
121 void sendPitchBendMessage(float pitchBendSemitones, bool force = false);
|
andrewm@0
|
122
|
andrewm@0
|
123 // ***** Member Variables *****
|
andrewm@0
|
124
|
andrewm@0
|
125 bool bendIsEngaged_; // Whether the pitch bend is currently engaged
|
andrewm@0
|
126 bool snapIsEngaged_; // Whether the note is currently being snapped to nearest semitone
|
andrewm@0
|
127
|
andrewm@0
|
128 float thresholdSemitones_; // Minimum motion in semitones before bend engages
|
andrewm@0
|
129 float thresholdKeyLength_; // Minimum motion as a function of key length
|
andrewm@0
|
130 float thresholdCombinedMax_; // Whichever is greater of the above two
|
andrewm@0
|
131 float snapZoneSemitones_; // How wide the snap area is around each semitone
|
andrewm@0
|
132 int bendMode_; // What mode the bend works in (fixed, variable, etc.)
|
andrewm@0
|
133 float fixedModeMinEnableDistance_; // Minimum distance to engage in fixed mode
|
andrewm@0
|
134 float fixedModeBufferDistance_; // Extra distance at end beyond which no bend happens
|
andrewm@0
|
135 bool ignoresTwoFingers_; // Whether this mapping supresses all messages when two
|
andrewm@0
|
136 bool ignoresThreeFingers_; // or three fingers are present
|
andrewm@0
|
137
|
andrewm@0
|
138 float onsetLocationX_, onsetLocationY_; // Where the touch began at MIDI note on
|
andrewm@0
|
139 float lastX_, lastY_; // Where the touch was at the last frame we received
|
andrewm@0
|
140 int idOfCurrentTouch_; // Which touch ID we're currently following
|
andrewm@0
|
141 timestamp_type lastTimestamp_; // When the last data point arrived
|
andrewm@0
|
142 Node<float>::size_type lastProcessedIndex_; // Index of the last filtered position sample we've handled
|
andrewm@0
|
143
|
andrewm@0
|
144 float bendScalerPositive_, bendScalerNegative_; // Translation between position and semitones for upward and downward motions
|
andrewm@0
|
145
|
andrewm@0
|
146 float currentSnapDestinationSemitones_; // Where the pitch would snap to if snapping was engaged
|
andrewm@0
|
147
|
andrewm@0
|
148 float bendRangeSemitones_; // Amount of pitch bend in one direction at maximum
|
andrewm@0
|
149 float lastPitchBendSemitones_; // The last pitch bend value we sent out
|
andrewm@0
|
150
|
andrewm@0
|
151 Node<float> rawDistance_; // Distance from onset location
|
andrewm@0
|
152 CriticalSection distanceAccessMutex_; // Mutex protecting access to the distance buffer
|
andrewm@0
|
153 };
|
andrewm@0
|
154
|
andrewm@0
|
155
|
andrewm@0
|
156 #endif /* defined(__touchkeys__TouchkeyPitchBendMapping__) */
|