annotate Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.cpp @ 44:73576f49ad1c

Trying out a new method for parsing OSC emulation strings which may be more Windows-friendly. Also added basic support for keyboard divisions on the display.
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Sat, 23 Aug 2014 23:46:38 +0100
parents 0deac2806a7b
children 003236a1e29b
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 TouchkeyKeyDivisionMappingFactory.cpp: factory for the split-key mapping
andrewm@0 21 which triggers different actions or pitches depending on where the key
andrewm@0 22 was struck.
andrewm@0 23 */
andrewm@0 24
andrewm@0 25 #include "TouchkeyKeyDivisionMappingFactory.h"
andrewm@44 26 #include "../../Display/KeyboardDisplay.h"
andrewm@0 27
andrewm@0 28 // Yarman-24 Turkish microtonal tuning:
andrewm@0 29 /* 1/1 RAST C
andrewm@0 30 84.360 Nim Zengule C#/Db
andrewm@0 31 145.112 Zengule Cᵻ/Dƀ
andrewm@0 32 192.180 Dik Zengule Dd
andrewm@0 33 9/8 DUGAH D
andrewm@0 34 292.180 Kurdi D#/Eb
andrewm@0 35 60/49 Dik Kurdi Dᵻ/Eƀ
andrewm@0 36 364.735 Nerm Segah Ed
andrewm@0 37 5/4 SEGAH E
andrewm@0 38 415.677 Buselik E‡
andrewm@0 39 4/3 CHARGAH F
andrewm@0 40 584.359 Nim Hijaz F#/Gb
andrewm@0 41 635.300 Hijaz/Saba Fᵻ/Gƀ
andrewm@0 42 696.090 Dik Hijaz/Saba Gd
andrewm@0 43 3/2 NEVA G
andrewm@0 44 788.270 Nim Hisar G#/Ab
andrewm@0 45 854.924 Hisar Gᵻ/Aƀ
andrewm@0 46 888.270 Dik Hisar Ad
andrewm@0 47 27/16 HUSEYNI A 440hz
andrewm@0 48 16/9 Ajem A#/Bb
andrewm@0 49 11/6 Dik Ajem Aᵻ/Bƀ
andrewm@0 50 1074.547 Nerm Evdj Bd
andrewm@0 51 15/8 EVDJ B
andrewm@0 52 1125.488 Mahur B‡
andrewm@0 53 2/1 GERDANIYE C */
andrewm@0 54 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
andrewm@0 55 0, 84.36, 145.112, 192.18, 203.9, 292.18, 350.62, 364.74, 386.31, 415.677, 498.04, 584.359,
andrewm@0 56 635.3, 696.09, 701.95, 788.27, 854.92, 888.27, 905.87, 996.1, 1049.36, 1074.55, 1088.27, 1125.488
andrewm@0 57 };*/
andrewm@0 58
andrewm@0 59 // Yarman-24c Turkish microtonal tuning:
andrewm@0 60 /* 0: 1/1 C Dbb unison, perfect prime RAST ♥
andrewm@0 61 1: 83.059 cents C# Db nim zengule
andrewm@0 62 2: 143.623 cents zengule
andrewm@0 63 3: 191.771 cents C## Dd dik zengule
andrewm@0 64 4: 9/8 D Ebb major whole tone DÜGAH ♥
andrewm@0 65 5: 292.413 cents D# Eb kürdi
andrewm@0 66 6: 348.343 cents D#| Eb- dik kürdi
andrewm@0 67 7: 362.503 cents nerm segah
andrewm@0 68 8: 156/125 cents E SEGAH ♥
andrewm@0 69 9: 415.305 cents E| Buselik
andrewm@0 70 10: 4/3 F Gbb perfect fourth ÇARGAH ♥
andrewm@0 71 11: 581.382 cents F# Gb nim hicaz
andrewm@0 72 12: 634.184 cents hicaz
andrewm@0 73 13: 695.885 cents F## Gd dik hicaz
andrewm@0 74 14: 3/2 G Abb perfect fifth NEVA ♥
andrewm@0 75 15: 788.736 cents G# Ab nim hisar
andrewm@0 76 16: 853.063 cents hisar
andrewm@0 77 17: 887.656 cents G## Ad dik hisar
andrewm@0 78 18: 27/16 A Bbb Pyth. major sixth HÜSEYNİ ♥
andrewm@0 79 19: 16/9 A# Bb Pyth. minor seventh acem
andrewm@0 80 20: 1043.623 cents A#| Bb- dik acem
andrewm@0 81 21: 1071.942 cents nerm eviç
andrewm@0 82 22: 234/125 cents B EVİÇ ♥
andrewm@0 83 23: 1124.744 cents B| mahur
andrewm@0 84 24: 2/1 C Dbb octave GERDANİYE ♥
andrewm@0 85 */
andrewm@0 86
andrewm@0 87 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
andrewm@0 88 0, 83.059, 143.623, 191.771, 203.9, 292.413, 348.343, 362.503, 383.54, 415.305, 498.04, 581.382,
andrewm@0 89 634.184, 695.885, 701.95, 788.736, 853.063, 887.656, 905.87, 996.1, 1043.623, 1071.942, 1085.49, 1124.744
andrewm@0 90 };*/
andrewm@0 91
andrewm@0 92 /* Yarman-24c as above but arranged for performance */
andrewm@0 93 const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
andrewm@0 94 0, (1124.744 - 1200.0), 83.059, 143.623, 203.9, 191.771, 292.413, 348.343,
andrewm@0 95 383.54, 362.503, 498.04, 415.305, 581.382, 634.184, 695.885, 648.682,
andrewm@0 96 788.736, 853.063, 905.87, 887.656, 996.1, 1043.623, 1085.49, 1071.942,
andrewm@0 97 };
andrewm@0 98
andrewm@0 99 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
andrewm@0 100 0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700,
andrewm@0 101 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150
andrewm@0 102 };*/
andrewm@0 103
andrewm@0 104 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[36] = {
andrewm@0 105 0, 33.3, 66.6, 100, 133.3, 166.6, 200, 233.3, 266.6, 300, 333.3, 366.6,
andrewm@0 106 400, 433.3, 466.6, 500, 533.3, 566.6, 600, 633.3, 666.6, 700, 733.3, 766.6,
andrewm@0 107 800, 833.3, 866.6, 900, 933.3, 966.6, 1000, 1033.3, 1066.6, 1100, 1133.3, 1166.6
andrewm@0 108 };*/
andrewm@0 109
andrewm@0 110 /* As arranged:
andrewm@0 111 *
andrewm@0 112 * B| Db/ Dd Eb/ Ed E| Gb/ Gd Ab/ Ad Bb/ Bd
andrewm@0 113 * C C# D D# E F F# G G# A A# B
andrewm@0 114 */
andrewm@0 115
andrewm@0 116 TouchkeyKeyDivisionMappingFactory::TouchkeyKeyDivisionMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment)
andrewm@0 117 : TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>(keyboard, segment),
andrewm@0 118 numSegmentsPerKey_(TouchkeyKeyDivisionMapping::kDefaultNumberOfSegments),
andrewm@0 119 timeout_(TouchkeyKeyDivisionMapping::kDefaultDetectionTimeout),
andrewm@0 120 detectionParameter_(TouchkeyKeyDivisionMapping::kDefaultDetectionParameter),
andrewm@0 121 retriggerable_(false),
andrewm@0 122 retriggerNumFrames_(TouchkeyKeyDivisionMapping::kDefaultRetriggerNumFrames),
andrewm@0 123 retriggerKeepsVelocity_(true),
andrewm@0 124 referenceNote_(0), globalOffsetCents_(0)
andrewm@0 125 {
andrewm@0 126 //setName("/touchkeys/segmentpitch");
andrewm@0 127 setBendParameters();
andrewm@44 128
andrewm@44 129 KeyboardDisplay *display = keyboard_.gui();
andrewm@44 130 if(display != 0) {
andrewm@44 131 display->addKeyDivision(this, segment.noteRange().first, segment.noteRange().second, numSegmentsPerKey_);
andrewm@44 132 }
andrewm@44 133 }
andrewm@44 134
andrewm@44 135 TouchkeyKeyDivisionMappingFactory::~TouchkeyKeyDivisionMappingFactory() {
andrewm@44 136 // Remove the divisions from the keys, if this mapping has added them
andrewm@44 137 KeyboardDisplay *display = keyboard_.gui();
andrewm@44 138 if(display != 0)
andrewm@44 139 display->removeKeyDivision(this);
andrewm@0 140 }
andrewm@0 141
andrewm@0 142 void TouchkeyKeyDivisionMappingFactory::setName(const string& name) {
andrewm@0 143 TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>::setName(name);
andrewm@0 144 setBendParameters();
andrewm@0 145 }
andrewm@0 146
andrewm@36 147
andrewm@36 148 // ****** Preset Save/Load ******
andrewm@36 149 XmlElement* TouchkeyKeyDivisionMappingFactory::getPreset() {
andrewm@36 150 PropertySet properties;
andrewm@36 151
andrewm@36 152 storeCommonProperties(properties);
andrewm@36 153
andrewm@36 154 // No properties for now
andrewm@36 155
andrewm@36 156 XmlElement* preset = properties.createXml("MappingFactory");
andrewm@36 157 preset->setAttribute("type", "KeyDivision");
andrewm@36 158
andrewm@36 159 return preset;
andrewm@36 160 }
andrewm@36 161
andrewm@36 162 bool TouchkeyKeyDivisionMappingFactory::loadPreset(XmlElement const* preset) {
andrewm@36 163 if(preset == 0)
andrewm@36 164 return false;
andrewm@36 165
andrewm@36 166 PropertySet properties;
andrewm@36 167 properties.restoreFromXml(*preset);
andrewm@36 168
andrewm@36 169 if(!loadCommonProperties(properties))
andrewm@36 170 return false;
andrewm@36 171
andrewm@36 172 // Nothing specific to do for now
andrewm@36 173
andrewm@36 174 return true;
andrewm@36 175 }
andrewm@36 176
andrewm@36 177 // ***** Private Methods *****
andrewm@36 178
andrewm@0 179 // Set the initial parameters for a new mapping
andrewm@0 180 void TouchkeyKeyDivisionMappingFactory::initializeMappingParameters(int noteNumber, TouchkeyKeyDivisionMapping *mapping) {
andrewm@0 181 // KLUDGE: testing Maqam tunings. Go from absolute tunings in cents to pitch bends in semitones
andrewm@0 182 float tunings[2];
andrewm@0 183 int index = (noteNumber + 12 - referenceNote_) % 12;
andrewm@0 184 float standardTuning = (float)index * 100.0;
andrewm@0 185 tunings[0] = (kDefaultTuningsCents[index*2] - standardTuning + globalOffsetCents_) * .01;
andrewm@0 186 tunings[1] = (kDefaultTuningsCents[index*2 + 1] - standardTuning + globalOffsetCents_) * .01;
andrewm@0 187 mapping->setSegmentPitchBends(tunings, 2);
andrewm@0 188 /*float tunings[3];
andrewm@0 189 int index = (noteNumber + 12 - referenceNote_) % 12;
andrewm@0 190 float standardTuning = (float)index * 100.0;
andrewm@0 191 tunings[0] = (kDefaultTuningsCents[index*3] - standardTuning + globalOffsetCents_) * .01;
andrewm@0 192 tunings[1] = (kDefaultTuningsCents[index*3 + 1] - standardTuning + globalOffsetCents_) * .01;
andrewm@0 193 tunings[2] = (kDefaultTuningsCents[index*3 + 2] - standardTuning + globalOffsetCents_) * .01;
andrewm@0 194 mapping->setSegmentPitchBends(tunings, 3);*/
andrewm@0 195
andrewm@0 196
andrewm@0 197 mapping->setNumberOfSegments(numSegmentsPerKey_);
andrewm@0 198 mapping->setTimeout(timeout_);
andrewm@0 199 mapping->setDetectionParameter(detectionParameter_);
andrewm@0 200 mapping->setRetriggerable(retriggerable_, retriggerNumFrames_, retriggerKeepsVelocity_);
andrewm@0 201 }
andrewm@0 202
andrewm@0 203 void TouchkeyKeyDivisionMappingFactory::setBendParameters() {
andrewm@7 204 // Range of 0 indicates special case of using global pitch wheel range
andrewm@7 205 setMidiParameters(MidiKeyboardSegment::kControlPitchWheel, 0.0, 0.0, 0.0);
andrewm@0 206
andrewm@0 207 if(midiConverter_ != 0) {
andrewm@0 208 midiConverter_->listenToIncomingControl(MidiKeyboardSegment::kControlPitchWheel);
andrewm@0 209 }
andrewm@0 210 }