libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmMidi.c 6.2KB

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