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.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. unsigned cmMidiTo14Bits( cmMidiByte_t d0, cmMidiByte_t d1 )
  100. {
  101. unsigned val = d0;
  102. val <<= 7;
  103. val += d1;
  104. return val;
  105. }
  106. void cmMidiSplit14Bits( unsigned v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref )
  107. {
  108. *d0Ref = (v & 0x3f80) >> 7;
  109. *d1Ref = v & 0x7f;
  110. }
  111. int cmMidiToPbend( cmMidiByte_t d0, cmMidiByte_t d1 )
  112. {
  113. int v = cmMidiTo14Bits(d0,d1);
  114. return v - 8192;
  115. }
  116. void cmMidiSplitPbend( int v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref )
  117. {
  118. unsigned uv = v + 8192;
  119. cmMidiSplit14Bits(uv,d0Ref,d1Ref);
  120. }
  121. //====================================================================================================
  122. const char* cmMidiToSciPitch( cmMidiByte_t pitch, char* label, unsigned labelCharCnt )
  123. {
  124. static char buf[ kMidiSciPitchCharCnt ];
  125. if( label == NULL || labelCharCnt == 0 )
  126. {
  127. label = buf;
  128. labelCharCnt = kMidiSciPitchCharCnt;
  129. }
  130. assert( labelCharCnt >= kMidiSciPitchCharCnt );
  131. if( /*pitch < 0 ||*/ pitch > 127 )
  132. {
  133. label[0] = 0;
  134. return label;
  135. }
  136. assert( labelCharCnt >= 5 && /*pitch >= 0 &&*/ pitch <= 127 );
  137. char noteV[] = { 'C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B' };
  138. char shrpV[] = { ' ', '#', ' ', '#', ' ', ' ', '#', ' ', '#', ' ', '#', ' ' };
  139. int octave = (pitch / 12)-1;
  140. unsigned noteIdx = pitch % 12;
  141. char noteCh = noteV[ noteIdx ];
  142. char sharpCh = shrpV[ noteIdx ];
  143. unsigned idx = 1;
  144. label[labelCharCnt-1] = 0;
  145. label[0] = noteCh;
  146. if( sharpCh != ' ' )
  147. {
  148. label[1] = sharpCh;
  149. idx = 2;
  150. }
  151. assert( -1 <= octave && octave <= 9);
  152. snprintf(label+idx,kMidiSciPitchCharCnt-idx-1,"%i",octave);
  153. return label;
  154. }
  155. cmMidiByte_t cmSciPitchToMidi( const char* sciPitchStr )
  156. {
  157. const char* cp = sciPitchStr;
  158. bool sharpFl = false;
  159. bool flatFl = false;
  160. int octave;
  161. int idx = -1;
  162. if( sciPitchStr==NULL || strlen(sciPitchStr) > 5 )
  163. return kInvalidMidiPitch;
  164. switch(tolower(*cp))
  165. {
  166. case 'a': idx = 9; break;
  167. case 'b': idx = 11; break;
  168. case 'c': idx = 0; break;
  169. case 'd': idx = 2; break;
  170. case 'e': idx = 4; break;
  171. case 'f': idx = 5; break;
  172. case 'g': idx = 7; break;
  173. default:
  174. return kInvalidMidiPitch;
  175. }
  176. ++cp;
  177. if( !(*cp) )
  178. return kInvalidMidiPitch;
  179. if((sharpFl = *cp=='#') == true )
  180. ++idx;
  181. else
  182. if((flatFl = *cp=='b') == true )
  183. --idx;
  184. if( sharpFl || flatFl )
  185. {
  186. ++cp;
  187. if( !(*cp) )
  188. return kInvalidMidiPitch;
  189. }
  190. if( isdigit(*cp) == false && *cp!='-' )
  191. return kInvalidMidiPitch;
  192. octave = atoi(cp);
  193. unsigned rv = (octave*12) + idx + 12;
  194. if( 0 <= rv && rv <= 127 )
  195. return rv;
  196. return kInvalidMidiPitch;
  197. }