libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmMidi.c 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmMidi.h"
  4. enum
  5. {
  6. mdStatusDescLabelCharCnt = 5
  7. };
  8. typedef struct
  9. {
  10. cmMidiByte_t status;
  11. cmMidiByte_t byteCnt;
  12. char label[ mdStatusDescLabelCharCnt+1 ];
  13. } cmMidiStatusDesc;
  14. cmMidiStatusDesc _cmMidiStatusDescArray[] =
  15. {
  16. // channel messages
  17. { kNoteOffMdId, 2, "nof" },
  18. { kNoteOnMdId, 2, "non" },
  19. { kPolyPresMdId,2, "ppr" },
  20. { kCtlMdId, 2, "ctl" },
  21. { kPgmMdId, 1, "pgm" },
  22. { kChPresMdId, 1, "cpr" },
  23. { kPbendMdId, 2, "pb" },
  24. { kSysExMdId, kInvalidMidiByte,"sex" },
  25. // system common
  26. { kSysComMtcMdId, 1, "mtc" },
  27. { kSysComSppMdId, 2, "spp" },
  28. { kSysComSelMdId, 1, "sel" },
  29. { kSysComUndef0MdId, 0, "cu0" },
  30. { kSysComUndef1MdId, 0, "cu1" },
  31. { kSysComTuneMdId, 0, "tun" },
  32. { kSysComEoxMdId, 0, "eox" },
  33. // system real-time
  34. { kSysRtClockMdId, 0, "clk" },
  35. { kSysRtUndef0MdId,0, "ud0" },
  36. { kSysRtStartMdId, 0, "beg" },
  37. { kSysRtContMdId, 0, "cnt" },
  38. { kSysRtStopMdId, 0, "end" },
  39. { kSysRtUndef1MdId,0, "ud1" },
  40. { kSysRtSenseMdId, 0, "sns" },
  41. { kSysRtResetMdId, 0, "rst" },
  42. { kInvalidStatusMdId, kInvalidMidiByte, "ERR" }
  43. };
  44. cmMidiStatusDesc _cmMidiMetaStatusDescArray[] =
  45. {
  46. { kSeqNumbMdId, 2, "seqn" },
  47. { kTextMdId, -1, "text" },
  48. { kCopyMdId, -1, "copy" },
  49. { kTrkNameMdId, -1, "name" },
  50. { kInstrNameMdId, -1, "instr" },
  51. { kLyricsMdId, -1, "lyric" },
  52. { kMarkerMdId, -1, "mark" },
  53. { kCuePointMdId, -1, "cue" },
  54. { kMidiChMdId, 1, "chan" },
  55. { kEndOfTrkMdId, 0, "eot" },
  56. { kTempoMdId, 3, "tempo" },
  57. { kSmpteMdId, 5, "smpte" },
  58. { kTimeSigMdId, 4, "tsig" },
  59. { kKeySigMdId, 2, "ksig" },
  60. { kSeqSpecMdId, -1, "seqs" },
  61. { kInvalidMetaMdId, kInvalidMidiByte, "ERROR"}
  62. };
  63. //====================================================================================================
  64. const char* cmMidiStatusToLabel( cmMidiByte_t status )
  65. {
  66. unsigned i;
  67. if( !cmMidiIsStatus(status) )
  68. return NULL;
  69. // remove the channel value from ch msg status bytes
  70. if( cmMidiIsChStatus(status) )
  71. status &= 0xf0;
  72. for(i=0; _cmMidiStatusDescArray[i].status != kInvalidStatusMdId; ++i)
  73. if( _cmMidiStatusDescArray[i].status == status )
  74. return _cmMidiStatusDescArray[i].label;
  75. return _cmMidiStatusDescArray[i].label;
  76. }
  77. const char* cmMidiMetaStatusToLabel( cmMidiByte_t metaStatus )
  78. {
  79. int i;
  80. for(i=0; _cmMidiMetaStatusDescArray[i].status != kInvalidMetaMdId; ++i)
  81. if( _cmMidiMetaStatusDescArray[i].status == metaStatus )
  82. break;
  83. return _cmMidiMetaStatusDescArray[i].label;
  84. }
  85. cmMidiByte_t cmMidiStatusToByteCount( cmMidiByte_t status )
  86. {
  87. unsigned i;
  88. if( !cmMidiIsStatus(status) )
  89. return kInvalidMidiByte;
  90. // remove the channel value from ch msg status bytes
  91. if( cmMidiIsChStatus(status) )
  92. status &= 0xf0;
  93. for(i=0; _cmMidiStatusDescArray[i].status != kInvalidStatusMdId; ++i)
  94. if( _cmMidiStatusDescArray[i].status == status )
  95. return _cmMidiStatusDescArray[i].byteCnt;
  96. assert(0);
  97. return 0;
  98. }
  99. //====================================================================================================
  100. const char* cmMidiToSciPitch( cmMidiByte_t pitch, char* label, unsigned labelCharCnt )
  101. {
  102. static char buf[ kMidiSciPitchCharCnt ];
  103. if( label == NULL || labelCharCnt == 0 )
  104. {
  105. label = buf;
  106. labelCharCnt = kMidiSciPitchCharCnt;
  107. }
  108. assert( labelCharCnt >= kMidiSciPitchCharCnt );
  109. if( /*pitch < 0 ||*/ pitch > 127 )
  110. {
  111. label[0] = 0;
  112. return label;
  113. }
  114. assert( labelCharCnt >= 5 && /*pitch >= 0 &&*/ pitch <= 127 );
  115. char noteV[] = { 'C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B' };
  116. char shrpV[] = { ' ', '#', ' ', '#', ' ', ' ', '#', ' ', '#', ' ', '#', ' ' };
  117. int octave = (pitch / 12)-1;
  118. unsigned noteIdx = pitch % 12;
  119. char noteCh = noteV[ noteIdx ];
  120. char sharpCh = shrpV[ noteIdx ];
  121. unsigned idx = 1;
  122. label[labelCharCnt-1] = 0;
  123. label[0] = noteCh;
  124. if( sharpCh != ' ' )
  125. {
  126. label[1] = sharpCh;
  127. idx = 2;
  128. }
  129. assert( -1 <= octave && octave <= 9);
  130. snprintf(label+idx,kMidiSciPitchCharCnt-idx-1,"%i",octave);
  131. return label;
  132. }
  133. cmMidiByte_t cmSciPitchToMidi( const char* sciPitchStr )
  134. {
  135. const char* cp = sciPitchStr;
  136. bool sharpFl = false;
  137. bool flatFl = false;
  138. int octave;
  139. int idx = -1;
  140. if( sciPitchStr==NULL || strlen(sciPitchStr) > 5 )
  141. return kInvalidMidiPitch;
  142. switch(tolower(*cp))
  143. {
  144. case 'a': idx = 9; break;
  145. case 'b': idx = 11; break;
  146. case 'c': idx = 0; break;
  147. case 'd': idx = 2; break;
  148. case 'e': idx = 4; break;
  149. case 'f': idx = 5; break;
  150. case 'g': idx = 7; break;
  151. default:
  152. return kInvalidMidiPitch;
  153. }
  154. ++cp;
  155. if( !(*cp) )
  156. return kInvalidMidiPitch;
  157. if((sharpFl = *cp=='#') == true )
  158. ++idx;
  159. else
  160. if((flatFl = *cp=='b') == true )
  161. --idx;
  162. if( sharpFl || flatFl )
  163. {
  164. ++cp;
  165. if( !(*cp) )
  166. return kInvalidMidiPitch;
  167. }
  168. if( isdigit(*cp) == false && *cp!='-' )
  169. return kInvalidMidiPitch;
  170. octave = atoi(cp);
  171. unsigned rv = (octave*12) + idx + 12;
  172. if( 0 <= rv && rv <= 127 )
  173. return rv;
  174. return kInvalidMidiPitch;
  175. }