annotate Source/Mappings/Vibrato/TouchkeyVibratoMapping.h @ 56:b4a2d2ae43cf tip

merge
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Fri, 23 Nov 2018 15:48:14 +0000
parents 3580ffe87dc8
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 TouchkeyVibratoMapping.h: per-note mapping 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 #ifndef __touchkeys__TouchkeyVibratoMapping__
andrewm@0 26 #define __touchkeys__TouchkeyVibratoMapping__
andrewm@0 27
andrewm@0 28
andrewm@0 29 #include <map>
andrewm@0 30 #include <boost/bind.hpp>
andrewm@0 31 #include "../../TouchKeys/KeyTouchFrame.h"
andrewm@0 32 #include "../../TouchKeys/KeyPositionTracker.h"
andrewm@0 33 #include "../../TouchKeys/PianoKeyboard.h"
andrewm@0 34 #include "../TouchkeyBaseMapping.h"
andrewm@0 35 #include "../../Utility/IIRFilter.h"
andrewm@0 36
andrewm@0 37 // This class handles the detection and mapping of vibrato gestures
andrewm@0 38 // based on Touchkey data. It outputs MIDI or OSC messages that
andrewm@0 39 // can be used to affect the pitch of the active note.
andrewm@0 40
andrewm@0 41 class TouchkeyVibratoMapping : public TouchkeyBaseMapping {
andrewm@0 42 friend class TouchkeyVibratoMappingFactory;
andrewm@0 43
andrewm@0 44 private:
andrewm@0 45 // Useful constants for mapping MRP messages
andrewm@0 46 /*constexpr static const int kDefaultMIDIChannel = 0;
andrewm@0 47 constexpr static const int kDefaultFilterBufferLength = 30;
andrewm@0 48
andrewm@0 49 constexpr static const float kDefaultVibratoThresholdX = 0.05;
andrewm@0 50 constexpr static const float kDefaultVibratoRatioX = 0.3;
andrewm@0 51 constexpr static const float kDefaultVibratoThresholdY = 0.02;
andrewm@0 52 constexpr static const float kDefaultVibratoRatioY = 0.8;
andrewm@0 53 constexpr static const timestamp_diff_type kDefaultVibratoTimeout = microseconds_to_timestamp(400000); // 0.4s
andrewm@0 54 constexpr static const float kDefaultVibratoPrescaler = 2.0;
andrewm@0 55 constexpr static const float kDefaultVibratoRangeSemitones = 1.25;
andrewm@0 56
andrewm@0 57 constexpr static const timestamp_diff_type kZeroCrossingMinimumTime = microseconds_to_timestamp(50000); // 50ms
andrewm@0 58 constexpr static const timestamp_diff_type kMinimumOnsetTime = microseconds_to_timestamp(30000); // 30ms
andrewm@0 59 constexpr static const timestamp_diff_type kMaximumOnsetTime = microseconds_to_timestamp(300000); // 300ms
andrewm@0 60 constexpr static const timestamp_diff_type kMinimumReleaseTime = microseconds_to_timestamp(30000); // 30ms
andrewm@0 61 constexpr static const timestamp_diff_type kMaximumReleaseTime = microseconds_to_timestamp(300000); // 300ms*/
andrewm@0 62
andrewm@0 63 static const int kDefaultMIDIChannel;
andrewm@0 64 static const int kDefaultFilterBufferLength;
andrewm@0 65
andrewm@0 66 static const float kDefaultVibratoThresholdX;
andrewm@0 67 static const float kDefaultVibratoRatioX;
andrewm@0 68 static const float kDefaultVibratoThresholdY;
andrewm@0 69 static const float kDefaultVibratoRatioY;
andrewm@0 70 static const timestamp_diff_type kDefaultVibratoTimeout;
andrewm@0 71 static const float kDefaultVibratoPrescaler;
andrewm@0 72 static const float kDefaultVibratoRangeSemitones;
andrewm@0 73
andrewm@0 74 static const timestamp_diff_type kZeroCrossingMinimumTime;
andrewm@0 75 static const timestamp_diff_type kMinimumOnsetTime;
andrewm@0 76 static const timestamp_diff_type kMaximumOnsetTime;
andrewm@0 77 static const timestamp_diff_type kMinimumReleaseTime;
andrewm@0 78 static const timestamp_diff_type kMaximumReleaseTime;
andrewm@0 79
andrewm@0 80 static const float kWhiteKeySingleAxisThreshold;
andrewm@0 81
andrewm@0 82 enum {
andrewm@0 83 kStateInactive = 0,
andrewm@0 84 kStateSwitchingOn,
andrewm@0 85 kStateActive,
andrewm@0 86 kStateSwitchingOff
andrewm@0 87 };
andrewm@0 88
andrewm@0 89 public:
andrewm@0 90 // ***** Constructors *****
andrewm@0 91
andrewm@0 92 // Default constructor, passing the buffer on which to trigger
andrewm@0 93 TouchkeyVibratoMapping(PianoKeyboard &keyboard, MappingFactory *factory, int noteNumber, Node<KeyTouchFrame>* touchBuffer,
andrewm@0 94 Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker);
andrewm@0 95
andrewm@0 96 // ***** Destructor *****
andrewm@0 97
andrewm@0 98 ~TouchkeyVibratoMapping();
andrewm@0 99
andrewm@0 100 // ***** Modifiers *****
andrewm@0 101
andrewm@0 102 // Disable mappings from being sent
andrewm@0 103 void disengage(bool shouldDelete = false);
andrewm@0 104
andrewm@0 105 // Reset the state back initial values
andrewm@0 106 void reset();
andrewm@0 107
andrewm@0 108 // Resend the current state of all parameters
andrewm@0 109 void resend();
andrewm@0 110
andrewm@0 111 // Parameters for vibrato algorithm
andrewm@0 112 //void setType(int vibratoType);
andrewm@0 113 void setRange(float rangeSemitones);
andrewm@0 114 void setPrescaler(float prescaler);
andrewm@0 115 void setThresholds(float thresholdX, float thresholdY, float ratioX, float ratioY);
andrewm@0 116 void setTimeout(timestamp_diff_type timeout);
andrewm@0 117
andrewm@0 118 // ***** Evaluators *****
andrewm@0 119
andrewm@0 120 // This method receives triggers whenever events occur in the touch data or the
andrewm@0 121 // continuous key position (state changes only). It alters the behavior and scheduling
andrewm@0 122 // of the mapping but does not itself send OSC messages
andrewm@0 123 void triggerReceived(TriggerSource* who, timestamp_type timestamp);
andrewm@0 124
andrewm@0 125 // This method handles the OSC message transmission. It should be run in the Scheduler
andrewm@0 126 // thread provided by PianoKeyboard.
andrewm@0 127 timestamp_type performMapping();
andrewm@0 128
andrewm@0 129 private:
andrewm@0 130 // ***** Private Methods *****
andrewm@0 131 void midiNoteOnReceived(int channel, int velocity);
andrewm@0 132 void midiNoteOffReceived(int channel);
andrewm@0 133
andrewm@0 134 void changeStateSwitchingOn(timestamp_type timestamp);
andrewm@0 135 void changeStateActive(timestamp_type timestamp);
andrewm@0 136 void changeStateSwitchingOff(timestamp_type timestamp);
andrewm@0 137 void changeStateInactive(timestamp_type timestamp);
andrewm@0 138
andrewm@0 139 void resetDetectionState();
andrewm@0 140 void clearBuffers();
andrewm@0 141
andrewm@0 142 bool keyIsWhite();
andrewm@0 143
andrewm@0 144 void sendVibratoMessage(float pitchBendSemitones, bool force = false);
andrewm@0 145
andrewm@0 146 // ***** Member Variables *****
andrewm@0 147
andrewm@0 148 int vibratoState_; // Whether a vibrato gesture is currently detected
andrewm@0 149
andrewm@0 150 timestamp_type rampBeginTime_; // If in a switching state, when does the transition begin?
andrewm@0 151 float rampScaleValue_; // If in a switching state, what is the end point of the ramp?
andrewm@0 152 timestamp_diff_type rampLength_; // If in a switching state, how long is the transition?
andrewm@0 153 float lastCalculatedRampValue_; // Value of the ramp that was last calculated
andrewm@0 154
andrewm@0 155 float onsetThresholdX_, onsetThresholdY_; // Thresholds for detecting vibrato (first extremum)
andrewm@0 156 float onsetRatioX_, onsetRatioY_; // Thresholds for detection vibrato (second extremum)
andrewm@0 157 timestamp_diff_type onsetTimeout_; // Timeout between first and second extrema
andrewm@0 158
andrewm@0 159 float onsetLocationX_, onsetLocationY_; // Where the touch began at MIDI note on
andrewm@0 160 float lastX_, lastY_; // Where the touch was at the last frame we received
andrewm@0 161 int idOfCurrentTouch_; // Which touch ID we're currently following
andrewm@0 162 timestamp_type lastTimestamp_; // When the last data point arrived
andrewm@0 163 Node<float>::size_type lastProcessedIndex_; // Index of the last filtered position sample we've handled
andrewm@0 164
andrewm@0 165 timestamp_type lastZeroCrossingTimestamp_; // Timestamp of the last zero crossing
andrewm@0 166 timestamp_diff_type lastZeroCrossingInterval_; // Interval between the last two zero-crossings of filtered distance
andrewm@0 167 bool lastSampleWasPositive_; // Whether the last sample was > 0
andrewm@0 168
andrewm@0 169 bool foundFirstExtremum_; // Whether the first extremum has occurred
andrewm@0 170 float firstExtremumX_, firstExtremumY_; // Where the first extremum occurred
andrewm@0 171 timestamp_type firstExtremumTimestamp_; // Where the first extremum occurred
andrewm@0 172 timestamp_type lastExtremumTimestamp_; // When the most recent extremum occurred
andrewm@0 173
andrewm@0 174 float vibratoPrescaler_; // Parameter controlling prescaler before nonlinear scaling
andrewm@0 175 float vibratoRangeSemitones_; // Amount of pitch bend in one direction at maximum
andrewm@0 176
andrewm@0 177 float lastPitchBendSemitones_; // The last pitch bend value we sent out
andrewm@0 178
andrewm@0 179 Node<float> rawDistance_; // Distance from onset location
andrewm@0 180 IIRFilterNode<float> filteredDistance_; // Bandpass filtered finger motion
andrewm@0 181 CriticalSection distanceAccessMutex_; // Mutex that protects the access buffer from changes
andrewm@0 182 };
andrewm@0 183
andrewm@0 184 #endif /* defined(__touchkeys__TouchkeyVibratoMapping__) */