annotate Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.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 TouchkeyVibratoMappingFactory.cpp: factory for the vibrato mapping class,
andrewm@0 21 which creates vibrato through side-to-side motion of the finger on the
andrewm@0 22 key surface.
andrewm@0 23 */
andrewm@0 24
andrewm@0 25 #include "TouchkeyVibratoMappingFactory.h"
andrewm@0 26 #include "TouchkeyVibratoMappingShortEditor.h"
andrewm@0 27
andrewm@0 28 // Class constants
andrewm@0 29 const int TouchkeyVibratoMappingFactory::kDefaultVibratoControl = MidiKeyboardSegment::kControlPitchWheel;
andrewm@0 30
andrewm@0 31 // Default constructor, containing a reference to the PianoKeyboard class.
andrewm@0 32
andrewm@0 33 TouchkeyVibratoMappingFactory::TouchkeyVibratoMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) :
andrewm@7 34 TouchkeyBaseMappingFactory<TouchkeyVibratoMapping>(keyboard, segment),
andrewm@0 35 vibratoControl_(kDefaultVibratoControl),
andrewm@0 36 vibratoRange_(TouchkeyVibratoMapping::kDefaultVibratoRangeSemitones),
andrewm@0 37 vibratoPrescaler_(TouchkeyVibratoMapping::kDefaultVibratoPrescaler),
andrewm@0 38 vibratoTimeout_(TouchkeyVibratoMapping::kDefaultVibratoTimeout),
andrewm@0 39 vibratoOnsetThresholdX_(TouchkeyVibratoMapping::kDefaultVibratoThresholdX),
andrewm@0 40 vibratoOnsetThresholdY_(TouchkeyVibratoMapping::kDefaultVibratoThresholdY),
andrewm@0 41 vibratoOnsetRatioX_(TouchkeyVibratoMapping::kDefaultVibratoRatioX),
andrewm@0 42 vibratoOnsetRatioY_(TouchkeyVibratoMapping::kDefaultVibratoRatioY)
andrewm@0 43 {
andrewm@0 44 // Set up the MIDI converter to use pitch wheel
andrewm@0 45 configurePitchWheelVibrato();
andrewm@0 46 }
andrewm@0 47
andrewm@0 48 // ***** Destructor *****
andrewm@0 49
andrewm@0 50 TouchkeyVibratoMappingFactory::~TouchkeyVibratoMappingFactory() {
andrewm@0 51
andrewm@0 52 }
andrewm@0 53
andrewm@0 54 // ***** Accessors / Modifiers *****
andrewm@0 55
andrewm@0 56 void TouchkeyVibratoMappingFactory::setName(const string& name) {
andrewm@0 57 TouchkeyBaseMappingFactory<TouchkeyVibratoMapping>::setName(name);
andrewm@0 58 setVibratoControl(vibratoControl_);
andrewm@0 59 }
andrewm@0 60
andrewm@0 61 // ***** Vibrato Methods *****
andrewm@0 62
andrewm@0 63 void TouchkeyVibratoMappingFactory::setVibratoControl(int vibratoControl) {
andrewm@0 64 if(vibratoControl < 0 || vibratoControl >= MidiKeyboardSegment::kControlMax)
andrewm@0 65 return;
andrewm@0 66
andrewm@0 67 // Update the variable which affects future mappings
andrewm@0 68 vibratoControl_ = vibratoControl;
andrewm@0 69
andrewm@0 70 if(vibratoControl_ == MidiKeyboardSegment::kControlPitchWheel)
andrewm@0 71 configurePitchWheelVibrato();
andrewm@0 72 else
andrewm@0 73 configureControlChangeVibrato();
andrewm@0 74 }
andrewm@0 75
andrewm@0 76 void TouchkeyVibratoMappingFactory::setVibratoRange(float range, bool updateCurrent) {
andrewm@0 77 /*if(updateCurrent) {
andrewm@0 78 // Send new range to all active mappings
andrewm@0 79 // TODO: mutex protect
andrewm@0 80 std::map<int, mapping_pair>::iterator it = mappings_.begin();
andrewm@0 81 while(it != mappings_.end()) {
andrewm@0 82 // Tell this mapping to update its range
andrewm@0 83 TouchkeyVibratoMapping *mapping = it->second.first;
andrewm@0 84 mapping->setRange(rangeSemitones);
andrewm@0 85 it++;
andrewm@0 86 }
andrewm@0 87 }*/
andrewm@0 88
andrewm@0 89 // Update the variable which affects future mappings
andrewm@0 90 vibratoRange_ = range;
andrewm@0 91 if(vibratoRange_ < 0.01)
andrewm@0 92 vibratoRange_ = 0.01;
andrewm@0 93 if(vibratoRange_ > 127.0)
andrewm@0 94 vibratoRange_ = 127.0;
andrewm@0 95 }
andrewm@0 96
andrewm@0 97 void TouchkeyVibratoMappingFactory::setVibratoPrescaler(float prescaler, bool updateCurrent) {
andrewm@0 98 /*if(updateCurrent) {
andrewm@0 99 // Send new range to all active mappings
andrewm@0 100 // TODO: mutex protect
andrewm@0 101 std::map<int, mapping_pair>::iterator it = mappings_.begin();
andrewm@0 102 while(it != mappings_.end()) {
andrewm@0 103 // Tell this mapping to update its range
andrewm@0 104 TouchkeyVibratoMapping *mapping = it->second.first;
andrewm@0 105 mapping->setPrescaler(prescaler);
andrewm@0 106 it++;
andrewm@0 107 }
andrewm@0 108 }*/
andrewm@0 109
andrewm@0 110 // Update the variable which affects future mappings
andrewm@0 111 vibratoPrescaler_ = prescaler;
andrewm@0 112 }
andrewm@0 113
andrewm@0 114 void TouchkeyVibratoMappingFactory::setVibratoThreshold(float threshold, bool updateCurrent) {
andrewm@0 115 vibratoOnsetThresholdX_ = threshold;
andrewm@0 116 if(vibratoOnsetThresholdX_ < 0)
andrewm@0 117 vibratoOnsetThresholdX_ = 0;
andrewm@0 118 if(vibratoOnsetThresholdX_ > 1.0)
andrewm@0 119 vibratoOnsetThresholdX_ = 1.0;
andrewm@0 120 }
andrewm@0 121
andrewm@0 122 void TouchkeyVibratoMappingFactory::setVibratoThresholds(float thresholdX, float thresholdY, float ratioX, float ratioY, bool updateCurrent) {
andrewm@0 123 /*if(updateCurrent) {
andrewm@0 124 // Send new range to all active mappings
andrewm@0 125 // TODO: mutex protect
andrewm@0 126 std::map<int, mapping_pair>::iterator it = mappings_.begin();
andrewm@0 127 while(it != mappings_.end()) {
andrewm@0 128 // Tell this mapping to update its range
andrewm@0 129 TouchkeyVibratoMapping *mapping = it->second.first;
andrewm@0 130 mapping->setThresholds(thresholdX, thresholdY, ratioX, ratioY);
andrewm@0 131 it++;
andrewm@0 132 }
andrewm@0 133 }*/
andrewm@0 134
andrewm@0 135 // Update the variables which affect future mappings
andrewm@0 136 vibratoOnsetThresholdX_ = thresholdX;
andrewm@0 137 vibratoOnsetThresholdY_ = thresholdY;
andrewm@0 138 vibratoOnsetRatioX_ = ratioX;
andrewm@0 139 vibratoOnsetRatioY_ = ratioY;
andrewm@0 140 }
andrewm@0 141
andrewm@0 142 void TouchkeyVibratoMappingFactory::setVibratoTimeout(timestamp_diff_type timeout, bool updateCurrent) {
andrewm@0 143 /*if(updateCurrent) {
andrewm@0 144 // Send new range to all active mappings
andrewm@0 145 // TODO: mutex protect
andrewm@0 146 std::map<int, mapping_pair>::iterator it = mappings_.begin();
andrewm@0 147 while(it != mappings_.end()) {
andrewm@0 148 // Tell this mapping to update its range
andrewm@0 149 TouchkeyVibratoMapping *mapping = it->second.first;
andrewm@0 150 mapping->setTimeout(timeout);
andrewm@0 151 it++;
andrewm@0 152 }
andrewm@0 153 }*/
andrewm@0 154
andrewm@0 155 // Update the variable which affects future mappings
andrewm@0 156 vibratoTimeout_ = timeout;
andrewm@0 157 }
andrewm@0 158
andrewm@49 159 #ifndef TOUCHKEYS_NO_GUI
andrewm@0 160 // ***** GUI Support *****
andrewm@0 161 MappingEditorComponent* TouchkeyVibratoMappingFactory::createBasicEditor() {
andrewm@0 162 return new TouchkeyVibratoMappingShortEditor(*this);
andrewm@0 163 }
andrewm@49 164 #endif
andrewm@49 165
andrewm@49 166 // ****** OSC Control Support ******
andrewm@49 167 OscMessage* TouchkeyVibratoMappingFactory::oscControlMethod(const char *path, const char *types,
andrewm@49 168 int numValues, lo_arg **values, void *data) {
andrewm@49 169 if(!strcmp(path, "/set-vibrato-control")) {
andrewm@49 170 // Change the vibrato control
andrewm@49 171 if(numValues > 0) {
andrewm@49 172 if(types[0] == 'i') {
andrewm@49 173 setVibratoControl(values[0]->i);
andrewm@49 174 return OscTransmitter::createSuccessMessage();
andrewm@49 175 }
andrewm@49 176 }
andrewm@49 177 }
andrewm@49 178 else if(!strcmp(path, "/set-vibrato-range")) {
andrewm@49 179 // Change the vibrato range in semitones
andrewm@49 180 if(numValues > 0) {
andrewm@49 181 if(types[0] == 'f') {
andrewm@49 182 setVibratoRange(values[0]->f);
andrewm@49 183 return OscTransmitter::createSuccessMessage();
andrewm@49 184 }
andrewm@49 185 }
andrewm@49 186 }
andrewm@49 187 else if(!strcmp(path, "/set-vibrato-prescaler")) {
andrewm@49 188 // Change the vibrato prescaler
andrewm@49 189 if(numValues > 0) {
andrewm@49 190 if(types[0] == 'f') {
andrewm@49 191 setVibratoPrescaler(values[0]->f);
andrewm@49 192 return OscTransmitter::createSuccessMessage();
andrewm@49 193 }
andrewm@49 194 }
andrewm@49 195 }
andrewm@49 196 else if(!strcmp(path, "/set-vibrato-timeout")) {
andrewm@49 197 // Change the vibrato timeout
andrewm@49 198 if(numValues > 0) {
andrewm@49 199 if(types[0] == 'f') {
andrewm@49 200 setVibratoTimeout(values[0]->f);
andrewm@49 201 return OscTransmitter::createSuccessMessage();
andrewm@49 202 }
andrewm@49 203 }
andrewm@49 204 }
andrewm@49 205 else if(!strcmp(path, "/set-vibrato-threshold")) {
andrewm@49 206 // Change the vibrato threshold
andrewm@49 207 if(numValues > 0) {
andrewm@49 208 if(types[0] == 'f') {
andrewm@49 209 setVibratoThreshold(values[0]->f);
andrewm@49 210 return OscTransmitter::createSuccessMessage();
andrewm@49 211 }
andrewm@49 212 }
andrewm@49 213 }
andrewm@49 214
andrewm@49 215 // If no match, check the base class
andrewm@49 216 return TouchkeyBaseMappingFactory<TouchkeyVibratoMapping>::oscControlMethod(path, types, numValues, values, data);
andrewm@49 217 }
andrewm@0 218
andrewm@35 219
andrewm@35 220 // ****** Preset Save/Load ******
andrewm@35 221 XmlElement* TouchkeyVibratoMappingFactory::getPreset() {
andrewm@35 222 PropertySet properties;
andrewm@35 223
andrewm@35 224 storeCommonProperties(properties);
andrewm@35 225 properties.setValue("vibratoControl", vibratoControl_);
andrewm@35 226 properties.setValue("vibratoRange", vibratoRange_);
andrewm@35 227 properties.setValue("vibratoPrescaler", vibratoPrescaler_);
andrewm@35 228 properties.setValue("vibratoTimeout", vibratoTimeout_);
andrewm@35 229 properties.setValue("vibratoOnsetThresholdX", vibratoOnsetThresholdX_);
andrewm@35 230 properties.setValue("vibratoOnsetThresholdY", vibratoOnsetThresholdY_);
andrewm@35 231 properties.setValue("vibratoOnsetRatioX", vibratoOnsetRatioX_);
andrewm@35 232 properties.setValue("vibratoOnsetRatioY", vibratoOnsetRatioY_);
andrewm@35 233
andrewm@35 234 XmlElement* preset = properties.createXml("MappingFactory");
andrewm@35 235 preset->setAttribute("type", "Vibrato");
andrewm@35 236
andrewm@35 237 return preset;
andrewm@35 238 }
andrewm@35 239
andrewm@35 240 bool TouchkeyVibratoMappingFactory::loadPreset(XmlElement const* preset) {
andrewm@35 241 if(preset == 0)
andrewm@35 242 return false;
andrewm@35 243
andrewm@35 244 PropertySet properties;
andrewm@35 245 properties.restoreFromXml(*preset);
andrewm@35 246
andrewm@35 247 if(!loadCommonProperties(properties))
andrewm@35 248 return false;
andrewm@35 249 if(!properties.containsKey("vibratoControl") ||
andrewm@35 250 !properties.containsKey("vibratoRange") ||
andrewm@35 251 !properties.containsKey("vibratoPrescaler") ||
andrewm@35 252 !properties.containsKey("vibratoTimeout") ||
andrewm@35 253 !properties.containsKey("vibratoOnsetThresholdX") ||
andrewm@35 254 !properties.containsKey("vibratoOnsetThresholdY") ||
andrewm@35 255 !properties.containsKey("vibratoOnsetRatioX") ||
andrewm@35 256 !properties.containsKey("vibratoOnsetRatioY"))
andrewm@35 257 return false;
andrewm@35 258
andrewm@35 259 vibratoControl_ = properties.getDoubleValue("vibratoControl");
andrewm@35 260 vibratoRange_ = properties.getDoubleValue("vibratoRange");
andrewm@35 261 vibratoPrescaler_ = properties.getDoubleValue("vibratoPrescaler");
andrewm@35 262 vibratoTimeout_ = properties.getDoubleValue("vibratoTimeout");
andrewm@35 263 vibratoOnsetThresholdX_ = properties.getDoubleValue("vibratoOnsetThresholdX");
andrewm@35 264 vibratoOnsetThresholdY_ = properties.getDoubleValue("vibratoOnsetThresholdY");
andrewm@35 265 vibratoOnsetRatioX_ = properties.getDoubleValue("vibratoOnsetRatioX");
andrewm@35 266 vibratoOnsetRatioY_ = properties.getDoubleValue("vibratoOnsetRatioY");
andrewm@35 267
andrewm@35 268 // Update MIDI information; this doesn't actually change the controller
andrewm@35 269 // (which is already set) but it adds a listener and updates the ranges
andrewm@35 270 setVibratoControl(vibratoControl_);
andrewm@35 271
andrewm@35 272 return true;
andrewm@35 273 }
andrewm@35 274
andrewm@35 275
andrewm@0 276 // ***** Private Methods *****
andrewm@0 277
andrewm@0 278 // Set the initial parameters for a new mapping
andrewm@0 279 void TouchkeyVibratoMappingFactory::initializeMappingParameters(int noteNumber, TouchkeyVibratoMapping *mapping) {
andrewm@0 280 mapping->setRange(vibratoRange_);
andrewm@0 281 mapping->setPrescaler(vibratoPrescaler_);
andrewm@0 282 mapping->setThresholds(vibratoOnsetThresholdX_, vibratoOnsetThresholdY_, vibratoOnsetRatioX_, vibratoOnsetRatioY_);
andrewm@0 283 mapping->setTimeout(vibratoTimeout_);
andrewm@0 284 }
andrewm@0 285
andrewm@0 286 // Configure the OSC-MIDI converter to handle pitchwheel vibrato
andrewm@0 287 void TouchkeyVibratoMappingFactory::configurePitchWheelVibrato() {
andrewm@7 288 // Range of 0 indicates special case of using global pitch wheel range
andrewm@7 289 setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, 0.0, 0.0, 0.0);
andrewm@0 290
andrewm@0 291 if(midiConverter_ != 0) {
andrewm@0 292 midiConverter_->listenToIncomingControl(MidiKeyboardSegment::kControlPitchWheel);
andrewm@0 293 }
andrewm@0 294 }
andrewm@0 295
andrewm@0 296 // Configure the OSC-MIDI converter to handle vibrato based on a CC
andrewm@0 297 void TouchkeyVibratoMappingFactory::configureControlChangeVibrato() {
andrewm@0 298 setMidiParameters(vibratoControl_, 0.0, 127.0, 0.0, 0, 0, 127, 0, false, OscMidiConverter::kOutOfRangeExtrapolate);
andrewm@0 299
andrewm@0 300 if(midiConverter_ != 0) {
andrewm@0 301 midiConverter_->listenToIncomingControl(vibratoControl_);
andrewm@0 302 }
andrewm@0 303 }
andrewm@0 304
andrewm@0 305