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 MRPMapping.h: mapping class for magnetic resonator piano using continuous
|
andrewm@0
|
21 key position.
|
andrewm@0
|
22 */
|
andrewm@0
|
23
|
andrewm@0
|
24 #ifndef __touchkeys__MRPMapping__
|
andrewm@0
|
25 #define __touchkeys__MRPMapping__
|
andrewm@0
|
26
|
andrewm@0
|
27 #include <map>
|
andrewm@0
|
28 #include <boost/bind.hpp>
|
andrewm@0
|
29 #include "../TouchKeys/KeyTouchFrame.h"
|
andrewm@0
|
30 #include "../TouchKeys/KeyPositionTracker.h"
|
andrewm@0
|
31 #include "../TouchKeys/PianoKeyboard.h"
|
andrewm@0
|
32 #include "Mapping.h"
|
andrewm@0
|
33 #include "../Utility/IIRFilter.h"
|
andrewm@0
|
34
|
andrewm@0
|
35 // How many velocity samples to save in the buffer. Make sure this is
|
andrewm@0
|
36 // enough to cover the frequency of updates.
|
andrewm@0
|
37 const int kMRPMappingVelocityBufferLength = 30;
|
andrewm@0
|
38
|
andrewm@0
|
39 // This class handles the mapping from key position and, optionally,
|
andrewm@0
|
40 // touch information to OSC messages which control the magnetic resonator
|
andrewm@0
|
41 // piano. One copy of the object is created for each active note, and
|
andrewm@0
|
42 // all objects use the PianoKeyboard Scheduler facility to request timed
|
andrewm@0
|
43 // updates.
|
andrewm@0
|
44
|
andrewm@0
|
45 class MRPMapping : public Mapping {
|
andrewm@0
|
46 private:
|
andrewm@0
|
47 /*// Useful constants for mapping MRP messages
|
andrewm@0
|
48 const int kMIDINoteOnMessage = 0x90;
|
andrewm@0
|
49 const int kDefaultMIDIChannel = 15;
|
andrewm@0
|
50 const float kDefaultAftertouchScaler = 100.0;
|
andrewm@0
|
51
|
andrewm@0
|
52 // Parameters for vibrato detection and mapping
|
andrewm@0
|
53 const key_velocity kVibratoVelocityThreshold = scale_key_velocity(2.0);
|
andrewm@0
|
54 const timestamp_diff_type kVibratoMinimumPeakSpacing = microseconds_to_timestamp(60000);
|
andrewm@0
|
55 const timestamp_diff_type kVibratoTimeout = microseconds_to_timestamp(500000);
|
andrewm@0
|
56 const int kVibratoMinimumOscillations = 4;
|
andrewm@0
|
57 const float kVibratoRateScaler = 0.005;*/
|
andrewm@0
|
58 // Useful constants for mapping MRP messages
|
andrewm@0
|
59 static const int kMIDINoteOnMessage;
|
andrewm@0
|
60 static const int kDefaultMIDIChannel;
|
andrewm@0
|
61 static const float kDefaultAftertouchScaler;
|
andrewm@0
|
62
|
andrewm@0
|
63 // Parameters for vibrato detection and mapping
|
andrewm@0
|
64 static const key_velocity kVibratoVelocityThreshold;
|
andrewm@0
|
65 static const timestamp_diff_type kVibratoMinimumPeakSpacing;
|
andrewm@0
|
66 static const timestamp_diff_type kVibratoTimeout;
|
andrewm@0
|
67 static const int kVibratoMinimumOscillations;
|
andrewm@0
|
68 static const float kVibratoRateScaler;
|
andrewm@0
|
69
|
andrewm@0
|
70 struct PitchBend {
|
andrewm@0
|
71 int note; // Note number of the bending key
|
andrewm@0
|
72 bool isControllingBend; // True if the note in this structure
|
andrewm@0
|
73 // is the one controlling bend (false if it's us)
|
andrewm@0
|
74 bool isFinished; // True if the bend should finish after this cycle
|
andrewm@0
|
75 Node<key_position>* positionBuffer; // Key position for bending key
|
andrewm@0
|
76 KeyPositionTracker* positionTracker; // Key states for bending key
|
andrewm@0
|
77 };
|
andrewm@0
|
78
|
andrewm@0
|
79 public:
|
andrewm@0
|
80 // ***** Constructors *****
|
andrewm@0
|
81
|
andrewm@0
|
82 // Default constructor, passing the buffer on which to trigger
|
andrewm@0
|
83 MRPMapping(PianoKeyboard &keyboard, MappingFactory *factory, int noteNumber, Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
84 Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker);
|
andrewm@0
|
85
|
andrewm@0
|
86 // Copy constructor
|
andrewm@0
|
87 //MRPMapping(MRPMapping const& obj);
|
andrewm@0
|
88
|
andrewm@0
|
89 // ***** Destructor *****
|
andrewm@0
|
90
|
andrewm@0
|
91 ~MRPMapping();
|
andrewm@0
|
92
|
andrewm@0
|
93 // ***** Modifiers *****
|
andrewm@0
|
94
|
andrewm@0
|
95 // Disable mappings from being sent
|
andrewm@0
|
96 void disengage();
|
andrewm@0
|
97
|
andrewm@0
|
98 // Reset the state back initial values
|
andrewm@0
|
99 void reset();
|
andrewm@0
|
100
|
andrewm@0
|
101 // Set the aftertouch sensitivity on continuous key position
|
andrewm@0
|
102 // 0 means no aftertouch, 1 means default sensitivity, upward
|
andrewm@0
|
103 // from there
|
andrewm@0
|
104 void setAftertouchSensitivity(float sensitivity);
|
andrewm@0
|
105
|
andrewm@0
|
106 // Engage a pitch bend from a different key, based on its position and state
|
andrewm@0
|
107 void enablePitchBend(int toNote, Node<key_position>* toPositionBuffer,
|
andrewm@0
|
108 KeyPositionTracker *toPositionTracker);
|
andrewm@0
|
109
|
andrewm@0
|
110 // ***** Evaluators *****
|
andrewm@0
|
111
|
andrewm@0
|
112 // This method receives triggers whenever events occur in the touch data or the
|
andrewm@0
|
113 // continuous key position (state changes only). It alters the behavior and scheduling
|
andrewm@0
|
114 // of the mapping but does not itself send OSC messages
|
andrewm@0
|
115 void triggerReceived(TriggerSource* who, timestamp_type timestamp);
|
andrewm@0
|
116
|
andrewm@0
|
117 // This method handles the OSC message transmission. It should be run in the Scheduler
|
andrewm@0
|
118 // thread provided by PianoKeyboard.
|
andrewm@0
|
119 timestamp_type performMapping();
|
andrewm@0
|
120
|
andrewm@0
|
121 private:
|
andrewm@0
|
122 // ***** Private Methods *****
|
andrewm@0
|
123
|
andrewm@0
|
124 // Bring velocity calculations up to date
|
andrewm@0
|
125 key_velocity updateVelocityMeasurements();
|
andrewm@0
|
126
|
andrewm@0
|
127 // Find the timestamp of the first transition into a PartialPress state
|
andrewm@0
|
128 timestamp_type findTimestampOfPartialPress();
|
andrewm@0
|
129
|
andrewm@0
|
130 // ***** Member Variables *****
|
andrewm@0
|
131
|
andrewm@0
|
132 bool noteIsOn_; // Whether the MIDI note is active or not
|
andrewm@0
|
133 float aftertouchScaler_; // Scaler which affects aftertouch sensitivity
|
andrewm@0
|
134 float lastIntensity_, lastBrightness_; // Cached values for mapping qualities
|
andrewm@0
|
135 float lastPitch_, lastHarmonic_;
|
andrewm@0
|
136
|
andrewm@0
|
137 bool shouldLookForPitchBends_; // Whether to search for adjacent keys to start a pitch bend
|
andrewm@0
|
138 std::vector<PitchBend> activePitchBends_; // Which keys are involved in a pitch bend
|
andrewm@0
|
139
|
andrewm@0
|
140 Node<key_velocity> rawVelocity_; // History of key velocity measurements
|
andrewm@0
|
141 IIRFilterNode<key_velocity> filteredVelocity_; // Filtered key velocity information
|
andrewm@0
|
142 Node<key_position>::size_type lastCalculatedVelocityIndex_; // Keep track of how many velocity samples we've calculated
|
andrewm@0
|
143
|
andrewm@0
|
144 bool vibratoActive_; // Whether a vibrato gesture is currently detected
|
andrewm@0
|
145 int vibratoVelocityPeakCount_; // Counter for tracking velocity oscillations
|
andrewm@0
|
146 timestamp_type vibratoLastPeakTimestamp_; // When the last velocity peak took place
|
andrewm@0
|
147
|
andrewm@0
|
148 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MRPMapping)
|
andrewm@0
|
149 };
|
andrewm@0
|
150
|
andrewm@0
|
151 #endif /* defined(__touchkeys__MRPMapping__) */
|