Small utility library for MIDI functions.
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.

117 lines
2.7 KiB

  1. #include "midi-utils.h"
  2. #if !defined _WIN32
  3. /**
  4. * Converts a string to lowercase.
  5. * @param dest - The string to convert.
  6. */
  7. void _strlwr(char* dest) {
  8. for (unsigned int i = 0; i < strlen(dest); i += 1) {
  9. if ('A' <= dest[i] && dest[i] <= 'Z') {
  10. dest[i] += 0x20;
  11. }
  12. }
  13. }
  14. #endif
  15. /**
  16. * Gets the name of a MIDI note value.
  17. * @param midi_note - The MIDI note value.
  18. * @note Valid values are from 0-127.
  19. * @return The MIDI note name.
  20. * @see MIDI_GetNoteFromName()
  21. */
  22. char* MIDI_GetNoteName(unsigned char midi_note) {
  23. static const char* pitch_names[] = {
  24. "C",
  25. "C#",
  26. "D",
  27. "D#",
  28. "E",
  29. "F",
  30. "F#",
  31. "G",
  32. "G#",
  33. "A",
  34. "A#",
  35. "B"
  36. };
  37. const unsigned char pitch_class = midi_note % 12;
  38. const unsigned char octave = midi_note / 12;
  39. static char note_name[8];
  40. sprintf(note_name, "%s%u", pitch_names[pitch_class], octave);
  41. return note_name;
  42. }
  43. /**
  44. * Gets the note value from a MIDI note name
  45. * @param name - The MIDI note name.
  46. * @return The MIDI note value, or 255 if an invalid name is passed.
  47. * @see MIDI_GetNoteName()
  48. */
  49. unsigned char MIDI_GetNoteFromName(const char* name) {
  50. if (!name) {
  51. return 255u;
  52. }
  53. char name_copy[8];
  54. strcpy(name_copy, name);
  55. _strlwr(name_copy);
  56. unsigned char octave = 0;
  57. unsigned char has_accidental = name_copy[1] == '#' || name_copy[1] == 'b';
  58. unsigned char octave_start = has_accidental ? 2 : 1;
  59. unsigned char pitch_class;
  60. char octave_offset = 0;
  61. for (unsigned char i = octave_start; '0' <= name_copy[i] && name_copy[i] <= '9'; i += 1) {
  62. octave *= 10;
  63. octave += name_copy[i] - '0';
  64. }
  65. if (strstr(name_copy, "c#") || strstr(name_copy, "db")) {
  66. pitch_class = 1;
  67. } else if (strstr(name_copy, "d#") || strstr(name_copy, "eb")) {
  68. pitch_class = 3;
  69. } else if (strstr(name_copy, "fb")) {
  70. pitch_class = 4;
  71. } else if (strstr(name_copy, "e#")) {
  72. pitch_class = 5;
  73. } else if (strstr(name_copy, "f#") || strstr(name_copy, "gb")) {
  74. pitch_class = 6;
  75. } else if (strstr(name_copy, "g#") || strstr(name_copy, "ab")) {
  76. pitch_class = 8;
  77. } else if (strstr(name_copy, "a#") || strstr(name_copy, "bb")) {
  78. pitch_class = 10;
  79. } else if (strstr(name_copy, "cb")) {
  80. pitch_class = 11;
  81. octave_offset = -1;
  82. } else if (strstr(name_copy, "b#")) {
  83. pitch_class = 0;
  84. octave_offset = 1;
  85. } else if (strstr(name_copy, "c")) {
  86. pitch_class = 0;
  87. } else if (strstr(name_copy, "d")) {
  88. pitch_class = 2;
  89. } else if (strstr(name_copy, "e")) {
  90. pitch_class = 4;
  91. } else if (strstr(name_copy, "f")) {
  92. pitch_class = 5;
  93. } else if (strstr(name_copy, "g")) {
  94. pitch_class = 7;
  95. } else if (strstr(name_copy, "a")) {
  96. pitch_class = 9;
  97. } else if (strstr(name_copy, "b")) {
  98. pitch_class = 11;
  99. } else {
  100. return 255u;
  101. }
  102. if (octave == 0 && octave_offset < 0) {
  103. return 255u;
  104. }
  105. return ((octave * 12) + octave_offset) + pitch_class;
  106. }