andrewm@0: /* andrewm@0: TouchKeys: multi-touch musical keyboard control software andrewm@0: Copyright (c) 2013 Andrew McPherson andrewm@0: andrewm@0: This program is free software: you can redistribute it and/or modify andrewm@0: it under the terms of the GNU General Public License as published by andrewm@0: the Free Software Foundation, either version 3 of the License, or andrewm@0: (at your option) any later version. andrewm@0: andrewm@0: This program is distributed in the hope that it will be useful, andrewm@0: but WITHOUT ANY WARRANTY; without even the implied warranty of andrewm@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the andrewm@0: GNU General Public License for more details. andrewm@0: andrewm@0: You should have received a copy of the GNU General Public License andrewm@0: along with this program. If not, see . andrewm@0: andrewm@0: ===================================================================== andrewm@0: andrewm@0: MIDIKeyPositionMapping.h: handles generating MIDI data out of continuous andrewm@0: key position. andrewm@0: */ andrewm@0: andrewm@0: #ifndef __touchkeys__MIDIKeyPositionMapping__ andrewm@0: #define __touchkeys__MIDIKeyPositionMapping__ andrewm@0: andrewm@0: #include andrewm@0: #include andrewm@0: #include "../TouchKeys/KeyTouchFrame.h" andrewm@0: #include "../TouchKeys/KeyPositionTracker.h" andrewm@0: #include "../TouchKeys/PianoKeyboard.h" andrewm@0: #include "Mapping.h" andrewm@0: andrewm@0: // This class handles the mapping from continuous key position to andrewm@0: // MIDI messages: note on, note off, aftertouch. andrewm@0: andrewm@0: class MIDIKeyPositionMapping : public Mapping { andrewm@0: private: andrewm@0: /*const int kDefaultMIDIChannel = 0; andrewm@0: const float kDefaultAftertouchScaler = 127.0 / 0.03; // Default aftertouch sensitivity: MIDI 127 = 0.03 andrewm@0: const float kMinimumAftertouchPosition = 0.99; // Position at which aftertouch messages start andrewm@0: const float kDefaultPercussivenessScaler = 1.0 / 300.0; // Default scaler from percussiveness feature to MIDI andrewm@0: const key_velocity kPianoKeyVelocityForMaxMIDI = scale_key_velocity(40.0); // Press velocity for MIDI 127 andrewm@0: const key_velocity kPianoKeyReleaseVelocityForMaxMIDI = scale_key_velocity(-50.0); // Release velocity for MIDI 127*/ andrewm@0: static const int kDefaultMIDIChannel; andrewm@0: static const float kDefaultAftertouchScaler; // Default aftertouch sensitivity: MIDI 127 = 0.03 andrewm@0: static const float kMinimumAftertouchPosition; // Position at which aftertouch messages start andrewm@0: static const float kDefaultPercussivenessScaler; // Default scaler from percussiveness feature to MIDI andrewm@0: static const key_velocity kPianoKeyVelocityForMaxMIDI; // Press velocity for MIDI 127 andrewm@0: static const key_velocity kPianoKeyReleaseVelocityForMaxMIDI; // Release velocity for MIDI 127 andrewm@0: andrewm@0: public: andrewm@0: // ***** Constructors ***** andrewm@0: andrewm@0: // Default constructor, passing the buffer on which to trigger andrewm@0: MIDIKeyPositionMapping(PianoKeyboard &keyboard, MappingFactory *factory, int noteNumber, Node* touchBuffer, andrewm@0: Node* positionBuffer, KeyPositionTracker* positionTracker); andrewm@0: andrewm@0: // Copy constructor andrewm@0: MIDIKeyPositionMapping(MIDIKeyPositionMapping const& obj); andrewm@0: andrewm@0: // ***** Destructor ***** andrewm@0: andrewm@0: ~MIDIKeyPositionMapping(); andrewm@0: andrewm@0: // ***** Modifiers ***** andrewm@0: andrewm@0: // Disable mappings from being sent andrewm@0: void disengage(); andrewm@0: andrewm@0: // Reset the state back initial values andrewm@0: void reset(); andrewm@0: andrewm@0: // Set the aftertouch sensitivity on continuous key position andrewm@0: // 0 means no aftertouch, 1 means default sensitivity, upward andrewm@0: // from there andrewm@0: void setAftertouchSensitivity(float sensitivity); andrewm@0: andrewm@0: // Get or set the MIDI channel (0-15) andrewm@0: int midiChannel() { return midiChannel_; } andrewm@0: void setMIDIChannel(int ch) { andrewm@0: if(ch >= 0 && ch < 16) andrewm@0: midiChannel_ = ch; andrewm@0: } andrewm@0: andrewm@0: // Get or set the MIDI channel for percussiveness messages andrewm@0: int percussivenessMIDIChannel() { return midiPercussivenessChannel_; } andrewm@0: void setPercussivenessMIDIChannel(int ch) { andrewm@0: if(ch >= 0 && ch < 16) andrewm@0: midiPercussivenessChannel_ = ch; andrewm@0: else andrewm@0: midiPercussivenessChannel_ = -1; andrewm@0: } andrewm@0: void disableMIDIPercussiveness() { midiPercussivenessChannel_ = -1; } andrewm@0: andrewm@0: // ***** Evaluators ***** andrewm@0: andrewm@0: // This method receives triggers whenever events occur in the touch data or the andrewm@0: // continuous key position (state changes only). It alters the behavior and scheduling andrewm@0: // of the mapping but does not itself send OSC messages andrewm@0: void triggerReceived(TriggerSource* who, timestamp_type timestamp); andrewm@0: andrewm@0: // This method handles the OSC message transmission. It should be run in the Scheduler andrewm@0: // thread provided by PianoKeyboard. andrewm@0: timestamp_type performMapping(); andrewm@0: andrewm@0: private: andrewm@0: // ***** Private Methods ***** andrewm@0: andrewm@0: void generateMidiNoteOn(); andrewm@0: void generateMidiNoteOff(); andrewm@0: void generateMidiPercussivenessNoteOn(); andrewm@0: andrewm@0: // ***** Member Variables ***** andrewm@0: andrewm@0: bool noteIsOn_; // Whether the MIDI note is active or not andrewm@0: float aftertouchScaler_; // Scaler which affects aftertouch sensitivity andrewm@0: int midiChannel_; // Channel on which to transmit MIDI messages andrewm@0: int lastAftertouchValue_; // Value of the last aftertouch message andrewm@0: int midiPercussivenessChannel_; // Whether and where to transmit percussiveness messages andrewm@0: }; andrewm@0: andrewm@0: andrewm@0: #endif /* defined(__touchkeys__MIDIKeyPositionMapping__) */