You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
4.5KB

  1. #include "rack.hpp"
  2. using namespace rack;
  3. #include <stdio.h>
  4. #include <string>
  5. #include <vector>
  6. #include <iostream>
  7. namespace rack_plugin_Alikins {
  8. // using namespace rack;
  9. std::vector<std::string> note_name_vec = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
  10. enum NoteName {
  11. C_NATURAL,
  12. C_SHARP,
  13. D_NATURAL,
  14. D_SHARP,
  15. E_NATURAL,
  16. F_NATURAL,
  17. F_SHARP,
  18. G_NATURAL,
  19. G_SHARP,
  20. A_NATURAL,
  21. A_SHARP,
  22. B_NATURAL
  23. };
  24. // add a NoteValue obj based on volts, with
  25. // methods for voltToText, voltToNote, etc
  26. struct NoteOct {
  27. std::string name;
  28. std::string octave;
  29. std::string flag;
  30. int rank;
  31. NoteOct() {
  32. // if no octave number, assume it is octave 4
  33. name = "C";
  34. octave = "4";
  35. flag = "";
  36. rank = 0;
  37. }
  38. };
  39. // Build a map of note_name ('C4', 'Ab3', etc) to it's CV voltage
  40. std::map<std::string, float> gen_note_name_map() {
  41. double volt = -10.0;
  42. std::string note_name;
  43. std::map<std::string, float> note_name_map;
  44. std::vector<std::string>::iterator it;
  45. double semi = 1.0/12.0;
  46. // FIXME: add a map of note name (including enharmonic) to voltage offset from C
  47. // then just iterate over it for each octave
  48. for (int i = -6; i <= 14; i++)
  49. {
  50. for (int j = 0; j < 12; j++)
  51. {
  52. // debug("oct=%d note=%s volt=%f ", i, note_name_vec[j].c_str(), volt);
  53. note_name_map[stringf("%s%d",
  54. note_name_vec[j].c_str(), i)] = volt;
  55. volt += semi;
  56. }
  57. }
  58. return note_name_map;
  59. }
  60. std::map<std::string, std::string> gen_enharmonic_name_map() {
  61. std::map<std::string, std::string> enharmonic_map;
  62. enharmonic_map["c"] = "C";
  63. enharmonic_map["C"] = "C";
  64. enharmonic_map["C#"] = "C#";
  65. enharmonic_map["c#"] = "C#";
  66. enharmonic_map["Db"] = "C#";
  67. enharmonic_map["db"] = "C#";
  68. enharmonic_map["d"] = "D";
  69. enharmonic_map["D"] = "D";
  70. enharmonic_map["D#"] = "D#";
  71. enharmonic_map["d#"] = "D#";
  72. enharmonic_map["Eb"] = "D#";
  73. enharmonic_map["eb"] = "D#";
  74. enharmonic_map["E"] = "E";
  75. enharmonic_map["e"] = "E";
  76. enharmonic_map["Fb"] = "E";
  77. enharmonic_map["fb"] = "E";
  78. enharmonic_map["E#"] = "F";
  79. enharmonic_map["e#"] = "F";
  80. enharmonic_map["F"] = "F";
  81. enharmonic_map["f"] = "F";
  82. enharmonic_map["F#"] = "F#";
  83. enharmonic_map["f#"] = "F#";
  84. enharmonic_map["Gb"] = "F#";
  85. enharmonic_map["Gb"] = "F#";
  86. enharmonic_map["G"] = "G";
  87. enharmonic_map["g"] = "G";
  88. enharmonic_map["G#"] = "G#";
  89. enharmonic_map["g#"] = "G#";
  90. enharmonic_map["Ab"] = "G#";
  91. enharmonic_map["ab"] = "G#";
  92. enharmonic_map["A"] = "A";
  93. enharmonic_map["a"] = "A";
  94. enharmonic_map["A#"] = "A#";
  95. enharmonic_map["a#"] = "A#";
  96. enharmonic_map["Bb"] = "A#";
  97. enharmonic_map["bb"] = "A#";
  98. enharmonic_map["B"] = "B";
  99. enharmonic_map["b"] = "B";
  100. enharmonic_map["Cb"] = "B";
  101. enharmonic_map["cb"] = "B";
  102. enharmonic_map["B#"] = "C";
  103. enharmonic_map["b#"] = "C";
  104. return enharmonic_map;
  105. }
  106. std::map<std::string, std::string> enharmonic_name_map = gen_enharmonic_name_map();
  107. std::map<std::string, float> note_name_to_volts_map = gen_note_name_map();
  108. NoteOct* parseNote(std::string text) {
  109. // split into 'stuff before any int or -' and a number like string
  110. // ie C#11 -> C# 11, A-4 -> A 4
  111. std::size_t note_flag_found_loc = text.find_last_of("#♯b♭");
  112. std::string note_flag = "";
  113. if(note_flag_found_loc!=std::string::npos){
  114. note_flag = text[note_flag_found_loc];
  115. }
  116. std::size_t found = text.find_first_of("-0123456789");
  117. // if no octave number, assume it is octave 4
  118. std::string note_name = text;
  119. std::string note_oct = "4";
  120. if(found != std::string::npos){
  121. note_name = text.substr(0, found);
  122. note_oct = text.substr(found, text.length());
  123. }
  124. // debug("parseNote note_name: %s, note_oct: %s", note_name.c_str(), note_oct.c_str());
  125. std::string can_note_name = enharmonic_name_map[note_name];
  126. // debug("parseNote can_not_name: %s", can_note_name.c_str());
  127. NoteOct *noteOct = new NoteOct();
  128. noteOct->name = can_note_name;
  129. noteOct->octave = note_oct;
  130. noteOct->flag = note_flag;
  131. return noteOct;
  132. }
  133. std::string getCanNoteId(NoteOct *noteOct) {
  134. std::string can_note_name = enharmonic_name_map[noteOct->name];
  135. std::string can_note_id = stringf("%s%s", can_note_name.c_str(), noteOct->octave.c_str());
  136. return can_note_id;
  137. }
  138. } // namespace rack_plugin_Alikins