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: TouchkeyKeyDivisionMappingFactory.h: factory for the split-key mapping
andrewm@0: which triggers different actions or pitches depending on where the key
andrewm@0: was struck.
andrewm@0: */
andrewm@0:
andrewm@0: #ifndef __TouchKeys__TouchkeyKeyDivisionMappingFactory__
andrewm@0: #define __TouchKeys__TouchkeyKeyDivisionMappingFactory__
andrewm@0:
andrewm@0: #include "../TouchkeyBaseMappingFactory.h"
andrewm@0: #include "TouchkeyKeyDivisionMapping.h"
andrewm@0:
andrewm@0: class TouchkeyKeyDivisionMappingFactory : public TouchkeyBaseMappingFactory {
andrewm@0: private:
andrewm@51: static const float kTuningsYarman24c[];
andrewm@51: static const int kMaxSegmentsPerKey;
andrewm@0:
andrewm@0: public:
andrewm@51: enum {
andrewm@51: kTuningPreset19TET = 0,
andrewm@51: kTuningPreset24TET,
andrewm@51: kTuningPreset31TET,
andrewm@51: kTuningPreset36TET,
andrewm@51: kTuningPresetYarman24c,
andrewm@51: kTuningPresetMaxValue
andrewm@51: };
andrewm@51:
andrewm@0: // ***** Constructor *****
andrewm@0:
andrewm@0: // Default constructor, containing a reference to the PianoKeyboard class.
andrewm@0: TouchkeyKeyDivisionMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment);
andrewm@0:
andrewm@0: // ***** Destructor *****
andrewm@0:
andrewm@44: ~TouchkeyKeyDivisionMappingFactory();
andrewm@0:
andrewm@0: // ***** Accessors / Modifiers *****
andrewm@0:
andrewm@0: virtual const std::string factoryTypeName() { return "Split\nKeys"; }
andrewm@0:
andrewm@0: void setName(const string& name);
andrewm@0:
andrewm@51: // ***** Split-Key Specific Methods *****
andrewm@51:
andrewm@51: int getNumberOfSegments() { return numSegmentsPerKey_; }
andrewm@51: timestamp_diff_type getTimeout() { return timeout_; }
andrewm@51: int getDetectionParameter() { return detectionParameter_; }
andrewm@51: bool getRetriggerable() { return retriggerable_; }
andrewm@51: int getRetriggerNumFrames() { return retriggerNumFrames_; }
andrewm@51: bool getRetriggerKeepsVelocity() { return retriggerKeepsVelocity_; }
andrewm@51: int getReferenceNote() { return referenceNote_; }
andrewm@51: float getGlobalOffset() { return globalOffsetCents_; }
andrewm@51: int getTuningPreset() { return tuningPreset_; }
andrewm@0:
andrewm@0: void setNumberOfSegments(int segments) {
andrewm@51: if(segments > 0 && segments <= kMaxSegmentsPerKey)
andrewm@0: numSegmentsPerKey_ = segments;
andrewm@0: }
andrewm@0:
andrewm@0: // Set the detection timeout value (how long from MIDI note on to touch)
andrewm@0: void setTimeout(timestamp_diff_type timeout) {
andrewm@0: timeout_ = timeout;
andrewm@0: }
andrewm@0:
andrewm@0: // Set the detection parameter for choosing a segment
andrewm@0: void setDetectionParameter(int detectionParameter) {
andrewm@51: if(detectionParameter >= 1 && detectionParameter < TouchkeyKeyDivisionMapping::kDetectionParameterMaxValue)
andrewm@51: detectionParameter_ = detectionParameter;
andrewm@0: }
andrewm@0:
andrewm@0: // Set whether placing a second finger in the other segment triggers a
andrewm@51: // new note with that segment. Two forms of this...
andrewm@0: void setRetriggerable(bool retrigger, int numFrames, bool keepOriginalVelocity) {
andrewm@0: retriggerable_ = retrigger;
andrewm@0: retriggerNumFrames_ = numFrames;
andrewm@0: retriggerKeepsVelocity_ = keepOriginalVelocity;
andrewm@0: }
andrewm@0:
andrewm@51: void setRetriggerable(bool retrigger) {
andrewm@51: retriggerable_ = retrigger;
andrewm@51: }
andrewm@51:
andrewm@0: // Set the note that acts as the reference point in a microtonal scale
andrewm@0: void setReferenceNote(int note) {
andrewm@0: if(note >= 0)
andrewm@0: referenceNote_ = note % 12;
andrewm@0: }
andrewm@0:
andrewm@0: void setGlobalOffset(float offsetCents) {
andrewm@0: globalOffsetCents_ = offsetCents;
andrewm@0: }
andrewm@0:
andrewm@51: void setTuningPreset(int preset);
andrewm@51:
andrewm@51: #ifndef TOUCHKEYS_NO_GUI
andrewm@51: // ***** GUI Support *****
andrewm@51: bool hasBasicEditor() { return true; }
andrewm@51: MappingEditorComponent* createBasicEditor();
andrewm@51: bool hasExtendedEditor() { return false; }
andrewm@51: MappingEditorComponent* createExtendedEditor() { return nullptr; }
andrewm@51: #endif
andrewm@51:
andrewm@36: // ****** Preset Save/Load ******
andrewm@36: XmlElement* getPreset();
andrewm@36: bool loadPreset(XmlElement const* preset);
andrewm@36:
andrewm@0: private:
andrewm@0: // ***** Private Methods *****
andrewm@0: void initializeMappingParameters(int noteNumber, TouchkeyKeyDivisionMapping *mapping);
andrewm@0: void setBendParameters();
andrewm@0:
andrewm@51: int tuningPreset_; // Number of the preset tuning, if active
andrewm@51: float *tunings_; // Array of tuning values, set by preset
andrewm@0: int numSegmentsPerKey_; // How many segments per key
andrewm@0: timestamp_diff_type timeout_; // How long before timeout activates default segment
andrewm@0: int detectionParameter_; // Which parameter separates it into segments
andrewm@0: bool retriggerable_; // Whether a second touch can retrigger this note
andrewm@0: int retriggerNumFrames_; // How many frames a new touch must be present to retrigger
andrewm@0: bool retriggerKeepsVelocity_; // Whether a retriggered note keeps the original velocity or a default
andrewm@0: int referenceNote_; // Which note acts as the reference point
andrewm@0: float globalOffsetCents_; // Offset of every note in cents
andrewm@51:
andrewm@51: CriticalSection tuningMutex_; // Mutex to avoid triggers during tuning changes
andrewm@0: };
andrewm@0:
andrewm@0: #endif /* defined(__TouchKeys__TouchkeyKeyDivisionMappingFactory__) */