Mercurial > hg > touchkeys
comparison Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.cpp @ 51:003236a1e29b
Added GUI for key division mapping, plus more tuning options
author | Andrew McPherson <andrewm@eecs.qmul.ac.uk> |
---|---|
date | Wed, 22 Apr 2015 21:37:51 +0100 |
parents | 73576f49ad1c |
children |
comparison
equal
deleted
inserted
replaced
50:114427cb39f0 | 51:003236a1e29b |
---|---|
21 which triggers different actions or pitches depending on where the key | 21 which triggers different actions or pitches depending on where the key |
22 was struck. | 22 was struck. |
23 */ | 23 */ |
24 | 24 |
25 #include "TouchkeyKeyDivisionMappingFactory.h" | 25 #include "TouchkeyKeyDivisionMappingFactory.h" |
26 #include "TouchkeyKeyDivisionMappingShortEditor.h" | |
26 #include "../../Display/KeyboardDisplay.h" | 27 #include "../../Display/KeyboardDisplay.h" |
27 | 28 |
28 // Yarman-24 Turkish microtonal tuning: | 29 /* Yarman-24c microtonal tuning */ |
29 /* 1/1 RAST C | 30 const float TouchkeyKeyDivisionMappingFactory::kTuningsYarman24c[24] = { |
30 84.360 Nim Zengule C#/Db | |
31 145.112 Zengule Cᵻ/Dƀ | |
32 192.180 Dik Zengule Dd | |
33 9/8 DUGAH D | |
34 292.180 Kurdi D#/Eb | |
35 60/49 Dik Kurdi Dᵻ/Eƀ | |
36 364.735 Nerm Segah Ed | |
37 5/4 SEGAH E | |
38 415.677 Buselik E‡ | |
39 4/3 CHARGAH F | |
40 584.359 Nim Hijaz F#/Gb | |
41 635.300 Hijaz/Saba Fᵻ/Gƀ | |
42 696.090 Dik Hijaz/Saba Gd | |
43 3/2 NEVA G | |
44 788.270 Nim Hisar G#/Ab | |
45 854.924 Hisar Gᵻ/Aƀ | |
46 888.270 Dik Hisar Ad | |
47 27/16 HUSEYNI A 440hz | |
48 16/9 Ajem A#/Bb | |
49 11/6 Dik Ajem Aᵻ/Bƀ | |
50 1074.547 Nerm Evdj Bd | |
51 15/8 EVDJ B | |
52 1125.488 Mahur B‡ | |
53 2/1 GERDANIYE C */ | |
54 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = { | |
55 0, 84.36, 145.112, 192.18, 203.9, 292.18, 350.62, 364.74, 386.31, 415.677, 498.04, 584.359, | |
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 | |
57 };*/ | |
58 | |
59 // Yarman-24c Turkish microtonal tuning: | |
60 /* 0: 1/1 C Dbb unison, perfect prime RAST ♥ | |
61 1: 83.059 cents C# Db nim zengule | |
62 2: 143.623 cents zengule | |
63 3: 191.771 cents C## Dd dik zengule | |
64 4: 9/8 D Ebb major whole tone DÜGAH ♥ | |
65 5: 292.413 cents D# Eb kürdi | |
66 6: 348.343 cents D#| Eb- dik kürdi | |
67 7: 362.503 cents nerm segah | |
68 8: 156/125 cents E SEGAH ♥ | |
69 9: 415.305 cents E| Buselik | |
70 10: 4/3 F Gbb perfect fourth ÇARGAH ♥ | |
71 11: 581.382 cents F# Gb nim hicaz | |
72 12: 634.184 cents hicaz | |
73 13: 695.885 cents F## Gd dik hicaz | |
74 14: 3/2 G Abb perfect fifth NEVA ♥ | |
75 15: 788.736 cents G# Ab nim hisar | |
76 16: 853.063 cents hisar | |
77 17: 887.656 cents G## Ad dik hisar | |
78 18: 27/16 A Bbb Pyth. major sixth HÜSEYNİ ♥ | |
79 19: 16/9 A# Bb Pyth. minor seventh acem | |
80 20: 1043.623 cents A#| Bb- dik acem | |
81 21: 1071.942 cents nerm eviç | |
82 22: 234/125 cents B EVİÇ ♥ | |
83 23: 1124.744 cents B| mahur | |
84 24: 2/1 C Dbb octave GERDANİYE ♥ | |
85 */ | |
86 | |
87 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = { | |
88 0, 83.059, 143.623, 191.771, 203.9, 292.413, 348.343, 362.503, 383.54, 415.305, 498.04, 581.382, | |
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 | |
90 };*/ | |
91 | |
92 /* Yarman-24c as above but arranged for performance */ | |
93 const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = { | |
94 0, (1124.744 - 1200.0), 83.059, 143.623, 203.9, 191.771, 292.413, 348.343, | 31 0, (1124.744 - 1200.0), 83.059, 143.623, 203.9, 191.771, 292.413, 348.343, |
95 383.54, 362.503, 498.04, 415.305, 581.382, 634.184, 695.885, 648.682, | 32 383.54, 362.503, 498.04, 415.305, 581.382, 634.184, 695.885, 648.682, |
96 788.736, 853.063, 905.87, 887.656, 996.1, 1043.623, 1085.49, 1071.942, | 33 788.736, 853.063, 905.87, 887.656, 996.1, 1043.623, 1085.49, 1071.942, |
97 }; | 34 }; |
98 | 35 |
99 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = { | 36 const int TouchkeyKeyDivisionMappingFactory::kMaxSegmentsPerKey = 3; |
100 0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, | |
101 750, 800, 850, 900, 950, 1000, 1050, 1100, 1150 | |
102 };*/ | |
103 | |
104 /*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[36] = { | |
105 0, 33.3, 66.6, 100, 133.3, 166.6, 200, 233.3, 266.6, 300, 333.3, 366.6, | |
106 400, 433.3, 466.6, 500, 533.3, 566.6, 600, 633.3, 666.6, 700, 733.3, 766.6, | |
107 800, 833.3, 866.6, 900, 933.3, 966.6, 1000, 1033.3, 1066.6, 1100, 1133.3, 1166.6 | |
108 };*/ | |
109 | 37 |
110 /* As arranged: | 38 /* As arranged: |
111 * | 39 * |
112 * B| Db/ Dd Eb/ Ed E| Gb/ Gd Ab/ Ad Bb/ Bd | 40 * B| Db/ Dd Eb/ Ed E| Gb/ Gd Ab/ Ad Bb/ Bd |
113 * C C# D D# E F F# G G# A A# B | 41 * C C# D D# E F F# G G# A A# B |
114 */ | 42 */ |
115 | 43 |
116 TouchkeyKeyDivisionMappingFactory::TouchkeyKeyDivisionMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) | 44 TouchkeyKeyDivisionMappingFactory::TouchkeyKeyDivisionMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) |
117 : TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>(keyboard, segment), | 45 : TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>(keyboard, segment), |
46 tuningPreset_(-1), tunings_(0), | |
118 numSegmentsPerKey_(TouchkeyKeyDivisionMapping::kDefaultNumberOfSegments), | 47 numSegmentsPerKey_(TouchkeyKeyDivisionMapping::kDefaultNumberOfSegments), |
119 timeout_(TouchkeyKeyDivisionMapping::kDefaultDetectionTimeout), | 48 timeout_(TouchkeyKeyDivisionMapping::kDefaultDetectionTimeout), |
120 detectionParameter_(TouchkeyKeyDivisionMapping::kDefaultDetectionParameter), | 49 detectionParameter_(TouchkeyKeyDivisionMapping::kDefaultDetectionParameter), |
121 retriggerable_(false), | 50 retriggerable_(false), |
122 retriggerNumFrames_(TouchkeyKeyDivisionMapping::kDefaultRetriggerNumFrames), | 51 retriggerNumFrames_(TouchkeyKeyDivisionMapping::kDefaultRetriggerNumFrames), |
123 retriggerKeepsVelocity_(true), | 52 retriggerKeepsVelocity_(true), |
124 referenceNote_(0), globalOffsetCents_(0) | 53 referenceNote_(0), globalOffsetCents_(0) |
125 { | 54 { |
126 //setName("/touchkeys/segmentpitch"); | 55 //setName("/touchkeys/segmentpitch"); |
127 setBendParameters(); | 56 setBendParameters(); |
57 setTuningPreset(kTuningPreset24TET); | |
128 | 58 |
129 KeyboardDisplay *display = keyboard_.gui(); | 59 KeyboardDisplay *display = keyboard_.gui(); |
130 if(display != 0) { | 60 if(display != 0) { |
131 display->addKeyDivision(this, segment.noteRange().first, segment.noteRange().second, numSegmentsPerKey_); | 61 display->addKeyDivision(this, segment.noteRange().first, segment.noteRange().second, numSegmentsPerKey_); |
132 } | 62 } |
135 TouchkeyKeyDivisionMappingFactory::~TouchkeyKeyDivisionMappingFactory() { | 65 TouchkeyKeyDivisionMappingFactory::~TouchkeyKeyDivisionMappingFactory() { |
136 // Remove the divisions from the keys, if this mapping has added them | 66 // Remove the divisions from the keys, if this mapping has added them |
137 KeyboardDisplay *display = keyboard_.gui(); | 67 KeyboardDisplay *display = keyboard_.gui(); |
138 if(display != 0) | 68 if(display != 0) |
139 display->removeKeyDivision(this); | 69 display->removeKeyDivision(this); |
70 if(tunings_ != 0) { | |
71 delete tunings_; | |
72 tunings_ = 0; | |
73 } | |
140 } | 74 } |
141 | 75 |
142 void TouchkeyKeyDivisionMappingFactory::setName(const string& name) { | 76 void TouchkeyKeyDivisionMappingFactory::setName(const string& name) { |
143 TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>::setName(name); | 77 TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>::setName(name); |
144 setBendParameters(); | 78 setBendParameters(); |
145 } | 79 } |
146 | 80 |
81 void TouchkeyKeyDivisionMappingFactory::setTuningPreset(int preset) { | |
82 if(preset < 0 || preset >= kTuningPresetMaxValue) | |
83 return; | |
84 | |
85 ScopedLock sl(tuningMutex_); | |
86 | |
87 tuningPreset_ = preset; | |
88 if(tunings_ != 0) { | |
89 delete tunings_; | |
90 tunings_ = 0; | |
91 } | |
92 | |
93 if(tuningPreset_ == kTuningPreset19TET) { | |
94 numSegmentsPerKey_ = 2; | |
95 tunings_ = new float[24]; | |
96 for(int i = 0; i < 24; i++) { | |
97 // Start with fraction of an octave, round to the nearest 19th of an octave | |
98 float original = (float)i / 24.0; | |
99 float rounded = floorf(original * 19.0 + 0.5); | |
100 | |
101 // Now convert the 19-tone index back to a fractional number of semitones | |
102 tunings_[i] = rounded * 1200.0 / 19.0; | |
103 } | |
104 } | |
105 else if(tuningPreset_ == kTuningPreset24TET) { | |
106 numSegmentsPerKey_ = 2; | |
107 tunings_ = new float[24]; | |
108 for(int i = 0; i < 24; i++) { | |
109 tunings_[i] = (float)i * 50.0; | |
110 } | |
111 } | |
112 else if(tuningPreset_ == kTuningPreset31TET) { | |
113 numSegmentsPerKey_ = 3; | |
114 tunings_ = new float[36]; | |
115 for(int i = 0; i < 36; i++) { | |
116 // Start with fraction of an octave, round to the nearest 31st of an octave | |
117 float original = (float)i / 36.0; | |
118 float rounded = floorf(original * 31.0 + 0.5); | |
119 | |
120 // Now convert the 31-tone index back to a fractional number of semitones | |
121 tunings_[i] = rounded * 1200.0 / 31.0; | |
122 } | |
123 } | |
124 else if(tuningPreset_ == kTuningPreset36TET) { | |
125 numSegmentsPerKey_ = 3; | |
126 tunings_ = new float[36]; | |
127 for(int i = 0; i < 24; i++) { | |
128 tunings_[i] = (float)i * 100.0 / 3.0; | |
129 } | |
130 } | |
131 else if(tuningPreset_ == kTuningPresetYarman24c) { | |
132 numSegmentsPerKey_ = 2; | |
133 tunings_ = new float[24]; | |
134 for(int i = 0; i < 24; i++) | |
135 tunings_[i] = kTuningsYarman24c[i]; | |
136 } | |
137 | |
138 KeyboardDisplay *display = keyboard_.gui(); | |
139 if(display != 0) { | |
140 display->removeKeyDivision(this); | |
141 display->addKeyDivision(this, keyboardSegment_.noteRange().first, keyboardSegment_.noteRange().second, numSegmentsPerKey_); | |
142 } | |
143 } | |
144 | |
145 #ifndef TOUCHKEYS_NO_GUI | |
146 // ***** GUI Support ***** | |
147 MappingEditorComponent* TouchkeyKeyDivisionMappingFactory::createBasicEditor() { | |
148 return new TouchkeyKeyDivisionMappingShortEditor(*this); | |
149 } | |
150 #endif | |
147 | 151 |
148 // ****** Preset Save/Load ****** | 152 // ****** Preset Save/Load ****** |
149 XmlElement* TouchkeyKeyDivisionMappingFactory::getPreset() { | 153 XmlElement* TouchkeyKeyDivisionMappingFactory::getPreset() { |
150 PropertySet properties; | 154 PropertySet properties; |
151 | 155 |
176 | 180 |
177 // ***** Private Methods ***** | 181 // ***** Private Methods ***** |
178 | 182 |
179 // Set the initial parameters for a new mapping | 183 // Set the initial parameters for a new mapping |
180 void TouchkeyKeyDivisionMappingFactory::initializeMappingParameters(int noteNumber, TouchkeyKeyDivisionMapping *mapping) { | 184 void TouchkeyKeyDivisionMappingFactory::initializeMappingParameters(int noteNumber, TouchkeyKeyDivisionMapping *mapping) { |
181 // KLUDGE: testing Maqam tunings. Go from absolute tunings in cents to pitch bends in semitones | 185 ScopedLock sl(tuningMutex_); |
182 float tunings[2]; | 186 |
187 // Convert absolute tunings into pitch bends in semitones | |
188 float tunings[kMaxSegmentsPerKey]; | |
189 | |
183 int index = (noteNumber + 12 - referenceNote_) % 12; | 190 int index = (noteNumber + 12 - referenceNote_) % 12; |
184 float standardTuning = (float)index * 100.0; | 191 float standardTuning = (float)index * 100.0; |
185 tunings[0] = (kDefaultTuningsCents[index*2] - standardTuning + globalOffsetCents_) * .01; | 192 |
186 tunings[1] = (kDefaultTuningsCents[index*2 + 1] - standardTuning + globalOffsetCents_) * .01; | 193 for(int i = 0; i < numSegmentsPerKey_; i++) { |
187 mapping->setSegmentPitchBends(tunings, 2); | 194 tunings[i] = (tunings_[index*numSegmentsPerKey_ + i] - standardTuning + globalOffsetCents_) * .01; |
188 /*float tunings[3]; | 195 } |
189 int index = (noteNumber + 12 - referenceNote_) % 12; | 196 mapping->setSegmentPitchBends(tunings, numSegmentsPerKey_); |
190 float standardTuning = (float)index * 100.0; | |
191 tunings[0] = (kDefaultTuningsCents[index*3] - standardTuning + globalOffsetCents_) * .01; | |
192 tunings[1] = (kDefaultTuningsCents[index*3 + 1] - standardTuning + globalOffsetCents_) * .01; | |
193 tunings[2] = (kDefaultTuningsCents[index*3 + 2] - standardTuning + globalOffsetCents_) * .01; | |
194 mapping->setSegmentPitchBends(tunings, 3);*/ | |
195 | |
196 | |
197 mapping->setNumberOfSegments(numSegmentsPerKey_); | 197 mapping->setNumberOfSegments(numSegmentsPerKey_); |
198 mapping->setTimeout(timeout_); | 198 mapping->setTimeout(timeout_); |
199 mapping->setDetectionParameter(detectionParameter_); | 199 mapping->setDetectionParameter(detectionParameter_); |
200 mapping->setRetriggerable(retriggerable_, retriggerNumFrames_, retriggerKeepsVelocity_); | 200 mapping->setRetriggerable(retriggerable_, retriggerNumFrames_, retriggerKeepsVelocity_); |
201 } | 201 } |