diff 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
line wrap: on
line diff
--- a/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.cpp	Mon Apr 13 20:51:17 2015 -0700
+++ b/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.cpp	Wed Apr 22 21:37:51 2015 +0100
@@ -23,89 +23,17 @@
 */
 
 #include "TouchkeyKeyDivisionMappingFactory.h"
+#include "TouchkeyKeyDivisionMappingShortEditor.h"
 #include "../../Display/KeyboardDisplay.h"
 
-// Yarman-24 Turkish microtonal tuning:
-/*      1/1	RAST		C
- 84.360	Nim Zengule	C#/Db
- 145.112	Zengule		Cᵻ/Dƀ
- 192.180	Dik Zengule	Dd
- 9/8	DUGAH		D
- 292.180	Kurdi		D#/Eb
- 60/49	Dik Kurdi	Dᵻ/Eƀ
- 364.735	Nerm Segah	Ed
- 5/4	SEGAH		E
- 415.677	Buselik		E‡
- 4/3	CHARGAH		F
- 584.359	Nim Hijaz	F#/Gb
- 635.300	Hijaz/Saba	Fᵻ/Gƀ
- 696.090	Dik Hijaz/Saba	Gd
- 3/2	NEVA		G
- 788.270	Nim Hisar	G#/Ab
- 854.924	Hisar		Gᵻ/Aƀ
- 888.270	Dik Hisar	Ad
- 27/16	HUSEYNI		A	440hz
- 16/9	Ajem		A#/Bb
- 11/6	Dik Ajem	Aᵻ/Bƀ
- 1074.547	Nerm Evdj	Bd
- 15/8	EVDJ		B
- 1125.488	Mahur		B‡
- 2/1	GERDANIYE	C */
-/*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
-    0, 84.36, 145.112, 192.18, 203.9, 292.18, 350.62, 364.74, 386.31, 415.677, 498.04, 584.359,
-    635.3, 696.09, 701.95, 788.27, 854.92, 888.27, 905.87, 996.1, 1049.36, 1074.55, 1088.27, 1125.488
-};*/
-
-// Yarman-24c Turkish microtonal tuning:
-/*   0:          1/1           C    Dbb   unison, perfect prime    RAST ♥
- 1:         83.059 cents   C#   Db    				nim zengule
- 2:        143.623 cents					zengule
- 3:        191.771 cents   C##  Dd				dik zengule
- 4:          9/8           D    Ebb   major whole tone		DÜGAH ♥
- 5:        292.413 cents   D#   Eb				kürdi
- 6:        348.343 cents   D#|  Eb-				dik kürdi
- 7:        362.503 cents					nerm segah
- 8:        156/125 cents   E					SEGAH ♥
- 9:        415.305 cents   E| 					Buselik
- 10:          4/3           F    Gbb   perfect fourth		ÇARGAH ♥
- 11:        581.382 cents   F#   Gb				nim hicaz
- 12:        634.184 cents					hicaz
- 13:        695.885 cents   F##  Gd				dik hicaz
- 14:          3/2           G    Abb   perfect fifth		NEVA ♥
- 15:        788.736 cents   G#   Ab				nim hisar
- 16:        853.063 cents					hisar
- 17:        887.656 cents   G##  Ad				dik hisar
- 18:         27/16          A    Bbb   Pyth. major sixth	HÜSEYNİ ♥
- 19:         16/9           A#   Bb    Pyth. minor seventh	acem
- 20:       1043.623 cents   A#|  Bb-				dik acem
- 21:       1071.942 cents					nerm eviç
- 22:        234/125 cents   B					EVİÇ ♥
- 23:       1124.744 cents   B|					mahur
- 24:          2/1           C    Dbb   octave			GERDANİYE ♥
-*/
-
-/*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
-    0, 83.059, 143.623, 191.771, 203.9, 292.413, 348.343, 362.503, 383.54, 415.305, 498.04, 581.382,
-    634.184, 695.885, 701.95, 788.736, 853.063, 887.656, 905.87, 996.1, 1043.623, 1071.942, 1085.49, 1124.744
-};*/
-
-/* Yarman-24c as above but arranged for performance */
-const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
+/* Yarman-24c microtonal tuning */
+const float TouchkeyKeyDivisionMappingFactory::kTuningsYarman24c[24] = {
     0, (1124.744 - 1200.0), 83.059, 143.623, 203.9, 191.771, 292.413, 348.343,
     383.54, 362.503, 498.04, 415.305, 581.382, 634.184, 695.885, 648.682,
     788.736, 853.063, 905.87, 887.656, 996.1, 1043.623, 1085.49, 1071.942,
 };
 
-/*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[24] = {
-    0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700,
-    750, 800, 850, 900, 950, 1000, 1050, 1100, 1150
-};*/
-
-/*const float TouchkeyKeyDivisionMappingFactory::kDefaultTuningsCents[36] = {
-    0, 33.3, 66.6, 100, 133.3, 166.6, 200, 233.3, 266.6, 300, 333.3, 366.6,
-    400, 433.3, 466.6, 500, 533.3, 566.6, 600, 633.3, 666.6, 700, 733.3, 766.6,
-    800, 833.3, 866.6, 900, 933.3, 966.6, 1000, 1033.3, 1066.6, 1100, 1133.3, 1166.6
-};*/
+const int TouchkeyKeyDivisionMappingFactory::kMaxSegmentsPerKey = 3;
 
 /* As arranged:
  *
@@ -115,6 +43,7 @@
 
 TouchkeyKeyDivisionMappingFactory::TouchkeyKeyDivisionMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment)
 : TouchkeyBaseMappingFactory<TouchkeyKeyDivisionMapping>(keyboard, segment),
+  tuningPreset_(-1), tunings_(0),
   numSegmentsPerKey_(TouchkeyKeyDivisionMapping::kDefaultNumberOfSegments),
   timeout_(TouchkeyKeyDivisionMapping::kDefaultDetectionTimeout),
   detectionParameter_(TouchkeyKeyDivisionMapping::kDefaultDetectionParameter),
@@ -125,6 +54,7 @@
 {
     //setName("/touchkeys/segmentpitch");
     setBendParameters();
+    setTuningPreset(kTuningPreset24TET);
     
     KeyboardDisplay *display = keyboard_.gui();
     if(display != 0) { 
@@ -137,6 +67,10 @@
     KeyboardDisplay *display = keyboard_.gui();
     if(display != 0)
         display->removeKeyDivision(this);
+    if(tunings_ != 0) {
+        delete tunings_;
+        tunings_ = 0;
+    }
 }
 
 void TouchkeyKeyDivisionMappingFactory::setName(const string& name) {
@@ -144,6 +78,76 @@
     setBendParameters();
 }
 
+void TouchkeyKeyDivisionMappingFactory::setTuningPreset(int preset) {
+    if(preset < 0 || preset >= kTuningPresetMaxValue)
+        return;
+    
+    ScopedLock sl(tuningMutex_);
+    
+    tuningPreset_ = preset;
+    if(tunings_ != 0) {
+        delete tunings_;
+        tunings_ = 0;
+    }
+    
+    if(tuningPreset_ == kTuningPreset19TET) {
+        numSegmentsPerKey_ = 2;
+        tunings_ = new float[24];
+        for(int i = 0; i < 24; i++) {
+            // Start with fraction of an octave, round to the nearest 19th of an octave
+            float original = (float)i / 24.0;
+            float rounded = floorf(original * 19.0 + 0.5);
+            
+            // Now convert the 19-tone index back to a fractional number of semitones
+            tunings_[i] = rounded * 1200.0 / 19.0;
+        }
+    }
+    else if(tuningPreset_ == kTuningPreset24TET) {
+        numSegmentsPerKey_ = 2;
+        tunings_ = new float[24];
+        for(int i = 0; i < 24; i++) {
+            tunings_[i] = (float)i * 50.0;
+        }
+    }
+    else if(tuningPreset_ == kTuningPreset31TET) {
+        numSegmentsPerKey_ = 3;
+        tunings_ = new float[36];
+        for(int i = 0; i < 36; i++) {
+            // Start with fraction of an octave, round to the nearest 31st of an octave
+            float original = (float)i / 36.0;
+            float rounded = floorf(original * 31.0 + 0.5);
+            
+            // Now convert the 31-tone index back to a fractional number of semitones
+            tunings_[i] = rounded * 1200.0 / 31.0;
+        }
+    }
+    else if(tuningPreset_ == kTuningPreset36TET) {
+        numSegmentsPerKey_ = 3;
+        tunings_ = new float[36];
+        for(int i = 0; i < 24; i++) {
+            tunings_[i] = (float)i * 100.0 / 3.0;
+        }
+    }
+    else if(tuningPreset_ == kTuningPresetYarman24c) {
+        numSegmentsPerKey_ = 2;
+        tunings_ = new float[24];
+        for(int i = 0; i < 24; i++)
+            tunings_[i] = kTuningsYarman24c[i];
+    }
+    
+    KeyboardDisplay *display = keyboard_.gui();
+    if(display != 0) {
+        display->removeKeyDivision(this);
+        display->addKeyDivision(this, keyboardSegment_.noteRange().first, keyboardSegment_.noteRange().second, numSegmentsPerKey_);
+    }
+}
+
+#ifndef TOUCHKEYS_NO_GUI
+// ***** GUI Support *****
+MappingEditorComponent* TouchkeyKeyDivisionMappingFactory::createBasicEditor() {
+    return new TouchkeyKeyDivisionMappingShortEditor(*this);
+}
+#endif
 
 // ****** Preset Save/Load ******
 XmlElement* TouchkeyKeyDivisionMappingFactory::getPreset() {
@@ -178,22 +182,18 @@
 
 // Set the initial parameters for a new mapping
 void TouchkeyKeyDivisionMappingFactory::initializeMappingParameters(int noteNumber, TouchkeyKeyDivisionMapping *mapping) {
-    // KLUDGE: testing Maqam tunings. Go from absolute tunings in cents to pitch bends in semitones
-    float tunings[2];
+    ScopedLock sl(tuningMutex_);
+    
+    // Convert absolute tunings into pitch bends in semitones
+    float tunings[kMaxSegmentsPerKey];
+    
     int index = (noteNumber + 12 - referenceNote_) % 12;
     float standardTuning = (float)index * 100.0;
-    tunings[0] = (kDefaultTuningsCents[index*2] - standardTuning + globalOffsetCents_) * .01;
-    tunings[1] = (kDefaultTuningsCents[index*2 + 1] - standardTuning + globalOffsetCents_) * .01;
-    mapping->setSegmentPitchBends(tunings, 2);
-    /*float tunings[3];
-    int index = (noteNumber + 12 - referenceNote_) % 12;
-    float standardTuning = (float)index * 100.0;
-    tunings[0] = (kDefaultTuningsCents[index*3] - standardTuning + globalOffsetCents_) * .01;
-    tunings[1] = (kDefaultTuningsCents[index*3 + 1] - standardTuning + globalOffsetCents_) * .01;
-    tunings[2] = (kDefaultTuningsCents[index*3 + 2] - standardTuning + globalOffsetCents_) * .01;
-    mapping->setSegmentPitchBends(tunings, 3);*/
-
     
+    for(int i = 0; i < numSegmentsPerKey_; i++) {
+        tunings[i] = (tunings_[index*numSegmentsPerKey_ + i] - standardTuning + globalOffsetCents_) * .01;
+    }
+    mapping->setSegmentPitchBends(tunings, numSegmentsPerKey_);
     mapping->setNumberOfSegments(numSegmentsPerKey_);
     mapping->setTimeout(timeout_);
     mapping->setDetectionParameter(detectionParameter_);