annotate Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingFactory.cpp @ 56:b4a2d2ae43cf tip

merge
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Fri, 23 Nov 2018 15:48:14 +0000
parents 90ce403d0dc5
children
rev   line source
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 TouchkeyReleaseAngleMappingFactory.cpp: factory for the release angle
andrewm@0 21 mapping, which measures the speed of finger motion along the key at
andrewm@0 22 the time of MIDI note off.
andrewm@0 23 */
andrewm@0 24
andrewm@0 25 #include "TouchkeyReleaseAngleMappingFactory.h"
andrewm@46 26 #include "TouchkeyReleaseAngleMappingExtendedEditor.h"
andrewm@0 27
andrewm@0 28 // Class constants
andrewm@0 29 const timestamp_diff_type TouchkeyReleaseAngleMappingFactory::kDefaultMaxLookbackTime = milliseconds_to_timestamp(100);
andrewm@46 30 const int TouchkeyReleaseAngleMappingFactory::kNumConfigurations = 2;
andrewm@46 31 const std::string TouchkeyReleaseAngleMappingFactory::kConfigurationNames[] = {
andrewm@46 32 "Sample Modeling Trombone",
andrewm@46 33 "Sample Modeling Trumpet"
andrewm@46 34 };
andrewm@0 35
andrewm@0 36 TouchkeyReleaseAngleMappingFactory::TouchkeyReleaseAngleMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment)
andrewm@46 37 : TouchkeyBaseMappingFactory<TouchkeyReleaseAngleMapping>(keyboard, segment),
andrewm@46 38 currentConfiguration_(-1),
andrewm@46 39 upEnabled_(true), downEnabled_(true),
andrewm@46 40 upMinimumAngle_(TouchkeyReleaseAngleMapping::kDefaultUpMinimumAngle),
andrewm@46 41 downMinimumAngle_(TouchkeyReleaseAngleMapping::kDefaultDownMinimumAngle)
andrewm@46 42 {
andrewm@46 43 // Get default values from the first configuration
andrewm@46 44 setCurrentConfiguration(0);
andrewm@46 45 }
andrewm@46 46
andrewm@46 47 // Set a particular configuration; make sure the values here match the
andrewm@46 48 // defined names and indices above
andrewm@46 49 void TouchkeyReleaseAngleMappingFactory::setCurrentConfiguration(int index) {
andrewm@46 50 if(index == 0) {
andrewm@46 51 // Sample Modeling Trombone
andrewm@46 52 currentConfiguration_ = 0;
andrewm@46 53 upEnabled_ = downEnabled_ = true;
andrewm@46 54 upMinimumAngle_ = 1.0;
andrewm@46 55 downMinimumAngle_ = 1.5;
andrewm@46 56 windowSizeMilliseconds_ = 100.0;
andrewm@46 57
andrewm@46 58 clearNotes();
andrewm@46 59
andrewm@46 60 upNotes_[0] = 36;
andrewm@46 61 upVelocities_[0] = 64;
andrewm@46 62 upNotes_[1] = 31;
andrewm@46 63 upVelocities_[1] = 96;
andrewm@46 64
andrewm@46 65 downNotes_[0] = 36;
andrewm@46 66 downVelocities_[0] = 64;
andrewm@46 67 downNotes_[1] = 33;
andrewm@46 68 downVelocities_[1] = 80;
andrewm@46 69 }
andrewm@46 70 else if(index == 1) {
andrewm@46 71 // Sample Modeling Trumpet
andrewm@46 72 currentConfiguration_ = 1;
andrewm@46 73 upEnabled_ = downEnabled_ = true;
andrewm@46 74 upMinimumAngle_ = 1.0;
andrewm@46 75 downMinimumAngle_ = 1.5;
andrewm@46 76 windowSizeMilliseconds_ = 100.0;
andrewm@46 77
andrewm@46 78 clearNotes();
andrewm@46 79
andrewm@46 80 upNotes_[0] = 48;
andrewm@46 81 upVelocities_[0] = 64;
andrewm@46 82 upNotes_[1] = 42;
andrewm@46 83 upVelocities_[1] = 96;
andrewm@46 84
andrewm@46 85 downNotes_[0] = 48;
andrewm@46 86 downVelocities_[0] = 64;
andrewm@46 87 downNotes_[1] = 46;
andrewm@46 88 downVelocities_[1] = 96;
andrewm@46 89 }
andrewm@46 90 }
andrewm@46 91
andrewm@46 92 // Parameters for release angle algorithm
andrewm@46 93 int TouchkeyReleaseAngleMappingFactory::getUpNote(int sequence) {
andrewm@46 94 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 95 return 0;
andrewm@46 96 return upNotes_[sequence];
andrewm@46 97 }
andrewm@46 98
andrewm@46 99 int TouchkeyReleaseAngleMappingFactory::getUpVelocity(int sequence) {
andrewm@46 100 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 101 return 0;
andrewm@46 102 return upVelocities_[sequence];
andrewm@46 103 }
andrewm@46 104
andrewm@46 105 int TouchkeyReleaseAngleMappingFactory::getDownNote(int sequence) {
andrewm@46 106 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 107 return 0;
andrewm@46 108 return downNotes_[sequence];
andrewm@46 109 }
andrewm@46 110
andrewm@46 111 int TouchkeyReleaseAngleMappingFactory::getDownVelocity(int sequence) {
andrewm@46 112 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 113 return 0;
andrewm@46 114 return downVelocities_[sequence];
andrewm@46 115 }
andrewm@46 116
andrewm@46 117 void TouchkeyReleaseAngleMappingFactory::setWindowSize(float windowSize) {
andrewm@46 118 if(windowSizeMilliseconds_ != windowSize)
andrewm@46 119 currentConfiguration_ = -1;
andrewm@46 120 windowSizeMilliseconds_ = windowSize;
andrewm@46 121 }
andrewm@46 122
andrewm@46 123 void TouchkeyReleaseAngleMappingFactory::setUpMessagesEnabled(bool enable) {
andrewm@46 124 if(upEnabled_ != enable)
andrewm@46 125 currentConfiguration_ = -1;
andrewm@46 126 upEnabled_ = enable;
andrewm@46 127 }
andrewm@46 128
andrewm@46 129 void TouchkeyReleaseAngleMappingFactory::setDownMessagesEnabled(bool enable) {
andrewm@46 130 if(downEnabled_ != enable)
andrewm@46 131 currentConfiguration_ = -1;
andrewm@46 132 downEnabled_ = enable;
andrewm@46 133 }
andrewm@46 134
andrewm@46 135 void TouchkeyReleaseAngleMappingFactory::setUpMinimumAngle(float minAngle) {
andrewm@46 136 if(upMinimumAngle_ != minAngle)
andrewm@46 137 currentConfiguration_ = -1;
andrewm@46 138 upMinimumAngle_ = fabsf(minAngle);
andrewm@46 139 }
andrewm@46 140
andrewm@46 141 void TouchkeyReleaseAngleMappingFactory::setUpNote(int sequence, int note) {
andrewm@46 142 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 143 return;
andrewm@46 144 if(note < 0 || note > 127)
andrewm@46 145 upNotes_[sequence] = 0;
andrewm@46 146 else {
andrewm@46 147 if(upNotes_[sequence] != note)
andrewm@46 148 currentConfiguration_ = -1;
andrewm@46 149 upNotes_[sequence] = note;
andrewm@46 150 }
andrewm@46 151 }
andrewm@46 152
andrewm@46 153 void TouchkeyReleaseAngleMappingFactory::setUpVelocity(int sequence, int velocity) {
andrewm@46 154 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 155 return;
andrewm@46 156 if(velocity < 0 || velocity > 127)
andrewm@46 157 upVelocities_[sequence] = 0;
andrewm@46 158 else {
andrewm@46 159 if(upVelocities_[sequence] != velocity)
andrewm@46 160 currentConfiguration_ = -1;
andrewm@46 161 upVelocities_[sequence] = velocity;
andrewm@46 162 }
andrewm@46 163 }
andrewm@46 164
andrewm@46 165 void TouchkeyReleaseAngleMappingFactory::setDownMinimumAngle(float minAngle) {
andrewm@46 166 if(downMinimumAngle_ != minAngle)
andrewm@46 167 currentConfiguration_ = -1;
andrewm@46 168 downMinimumAngle_ = fabsf(minAngle);
andrewm@46 169 }
andrewm@46 170
andrewm@46 171 void TouchkeyReleaseAngleMappingFactory::setDownNote(int sequence, int note) {
andrewm@46 172 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 173 return;
andrewm@46 174 if(note < 0 || note > 127)
andrewm@46 175 downNotes_[sequence] = 0;
andrewm@46 176 else {
andrewm@46 177 if(downNotes_[sequence] != note)
andrewm@46 178 currentConfiguration_ = -1;
andrewm@46 179 downNotes_[sequence] = note;
andrewm@46 180 }
andrewm@46 181 }
andrewm@46 182
andrewm@46 183 void TouchkeyReleaseAngleMappingFactory::setDownVelocity(int sequence, int velocity) {
andrewm@46 184 if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH)
andrewm@46 185 return;
andrewm@46 186 if(velocity < 0 || velocity > 127)
andrewm@46 187 downVelocities_[sequence] = 0;
andrewm@46 188 else {
andrewm@46 189 if(downVelocities_[sequence] != velocity)
andrewm@46 190 currentConfiguration_ = -1;
andrewm@46 191 downVelocities_[sequence] = velocity;
andrewm@46 192 }
andrewm@46 193 }
andrewm@46 194
andrewm@49 195 #ifndef TOUCHKEYS_NO_GUI
andrewm@46 196 // ***** GUI Support *****
andrewm@46 197
andrewm@46 198 MappingEditorComponent* TouchkeyReleaseAngleMappingFactory::createExtendedEditor() {
andrewm@46 199 return new TouchkeyReleaseAngleMappingExtendedEditor(*this);
andrewm@46 200 }
andrewm@49 201 #endif
andrewm@49 202
andrewm@0 203
andrewm@36 204 // ****** Preset Save/Load ******
andrewm@36 205 XmlElement* TouchkeyReleaseAngleMappingFactory::getPreset() {
andrewm@36 206 PropertySet properties;
andrewm@36 207
andrewm@36 208 storeCommonProperties(properties);
andrewm@36 209
andrewm@46 210 properties.setValue("currentConfiguration", currentConfiguration_);
andrewm@46 211 properties.setValue("upEnabled", upEnabled_);
andrewm@46 212 properties.setValue("downEnabled", downEnabled_);
andrewm@46 213 properties.setValue("upMinimumAngle", upMinimumAngle_);
andrewm@46 214 properties.setValue("downMinimumAngle", downMinimumAngle_);
andrewm@46 215 properties.setValue("windowSizeMilliseconds", windowSizeMilliseconds_);
andrewm@46 216
andrewm@46 217 // TODO: set arrays of notes and velocities
andrewm@36 218
andrewm@36 219 XmlElement* preset = properties.createXml("MappingFactory");
andrewm@36 220 preset->setAttribute("type", "ReleaseAngle");
andrewm@36 221
andrewm@36 222 return preset;
andrewm@36 223 }
andrewm@36 224
andrewm@36 225 bool TouchkeyReleaseAngleMappingFactory::loadPreset(XmlElement const* preset) {
andrewm@36 226 if(preset == 0)
andrewm@36 227 return false;
andrewm@36 228
andrewm@36 229 PropertySet properties;
andrewm@36 230 properties.restoreFromXml(*preset);
andrewm@36 231
andrewm@36 232 if(!loadCommonProperties(properties))
andrewm@36 233 return false;
andrewm@36 234
andrewm@46 235 // First check if there's a default configuration in use
andrewm@46 236 // We can get all other parameters from that regardless of the
andrewm@46 237 // remaining contents
andrewm@46 238 if(properties.containsKey("currentConfiguration")) {
andrewm@46 239 int config = properties.getIntValue("currentConfiguration");
andrewm@46 240 if(config >= 0 && config < kNumConfigurations)
andrewm@46 241 setCurrentConfiguration(config);
andrewm@46 242 }
andrewm@46 243 else {
andrewm@46 244 if(!properties.containsKey("upEnabled") ||
andrewm@46 245 !properties.containsKey("downEnabled") ||
andrewm@46 246 !properties.containsKey("upMinimumAngle") ||
andrewm@46 247 !properties.containsKey("downMinimumAngle") ||
andrewm@46 248 !properties.containsKey("windowSizeMilliseconds"))
andrewm@46 249 return false;
andrewm@46 250
andrewm@46 251 currentConfiguration_ = -1;
andrewm@46 252 upEnabled_ = properties.getBoolValue("upEnabled");
andrewm@46 253 downEnabled_ = properties.getBoolValue("downEnabled");
andrewm@46 254 upMinimumAngle_ = properties.getDoubleValue("upMinimumAngle");
andrewm@46 255 downMinimumAngle_ = properties.getDoubleValue("downMinimumAngle");
andrewm@46 256 windowSizeMilliseconds_ = properties.getDoubleValue("windowSizeMilliseconds");
andrewm@46 257
andrewm@46 258 // TODO: load arrays of notes and velocities
andrewm@46 259 }
andrewm@36 260
andrewm@36 261 return true;
andrewm@36 262 }
andrewm@36 263
andrewm@0 264 // MIDI note ended: see whether the mapping was suspended and if not, execute the angle calculation
andrewm@46 265 /*void TouchkeyReleaseAngleMappingFactory::midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive,
andrewm@0 266 Node<KeyTouchFrame>* touchBuffer,
andrewm@0 267 Node<key_position>* positionBuffer,
andrewm@0 268 KeyPositionTracker* positionTracker) {
andrewm@0 269 if(mappings_.count(noteNumber) != 0) {
andrewm@0 270 mappings_[noteNumber]->processRelease(keyboard_.schedulerCurrentTimestamp());
andrewm@0 271 }
andrewm@0 272
andrewm@0 273 // Call base class method
andrewm@0 274 TouchkeyBaseMappingFactory<TouchkeyReleaseAngleMapping>::midiNoteOff(noteNumber, touchIsOn, keyMotionActive, touchBuffer, positionBuffer, positionTracker);
andrewm@46 275 }*/
andrewm@46 276
andrewm@46 277 void TouchkeyReleaseAngleMappingFactory::initializeMappingParameters(int noteNumber,
andrewm@46 278 TouchkeyReleaseAngleMapping *mapping) {
andrewm@46 279 mapping->setWindowSize(windowSizeMilliseconds_);
andrewm@46 280 mapping->setUpMessagesEnabled(upEnabled_);
andrewm@46 281 mapping->setDownMessagesEnabled(downEnabled_);
andrewm@46 282 mapping->setUpMinimumAngle(upMinimumAngle_);
andrewm@46 283 mapping->setDownMinimumAngle(downMinimumAngle_);
andrewm@46 284
andrewm@46 285 for(int i = 0; i < RELEASE_ANGLE_MAX_SEQUENCE_LENGTH; i++) {
andrewm@46 286 mapping->setUpNote(i, upNotes_[i]);
andrewm@46 287 mapping->setUpVelocity(i, upVelocities_[i]);
andrewm@46 288 mapping->setDownNote(i, downNotes_[i]);
andrewm@46 289 mapping->setDownVelocity(i, downVelocities_[i]);
andrewm@46 290 }
andrewm@0 291 }
andrewm@46 292
andrewm@46 293 // Reset notes and velocities to defaults
andrewm@46 294 void TouchkeyReleaseAngleMappingFactory::clearNotes() {
andrewm@46 295 for(int i = 0; i < RELEASE_ANGLE_MAX_SEQUENCE_LENGTH; i++)
andrewm@46 296 upNotes_[i] = downNotes_[i] = upVelocities_[i] = downVelocities_[i] = 0;
andrewm@46 297 }