libcm is a C development framework with an emphasis on audio signal processing applications.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #ifndef cmMidi_h
  4. #define cmMidi_h
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif
  8. //( { file_desc:"MIDI utility constants and functions." kw:[midi]}
  9. enum
  10. {
  11. kMidiChCnt = 16,
  12. kInvalidMidiByte = 128,
  13. kMidiNoteCnt = kInvalidMidiByte,
  14. kMidiCtlCnt = kInvalidMidiByte,
  15. kMidiPgmCnt = kInvalidMidiByte,
  16. kInvalidMidiPitch = kInvalidMidiByte,
  17. kInvalidMidiVelocity = kInvalidMidiByte,
  18. kInvalidMidiCtl = kInvalidMidiByte,
  19. kInvalidMidiPgm = kInvalidMidiByte,
  20. kMidiSciPitchCharCnt = 5 // A#-1
  21. };
  22. // MIDI status bytes
  23. enum
  24. {
  25. kInvalidStatusMdId = 0x00,
  26. kNoteOffMdId = 0x80,
  27. kNoteOnMdId = 0x90,
  28. kPolyPresMdId = 0xa0,
  29. kCtlMdId = 0xb0,
  30. kPgmMdId = 0xc0,
  31. kChPresMdId = 0xd0,
  32. kPbendMdId = 0xe0,
  33. kSysExMdId = 0xf0,
  34. kSysComMtcMdId = 0xf1,
  35. kSysComSppMdId = 0xf2,
  36. kSysComSelMdId = 0xf3,
  37. kSysComUndef0MdId = 0xf4,
  38. kSysComUndef1MdId = 0xf5,
  39. kSysComTuneMdId = 0xf6,
  40. kSysComEoxMdId = 0xf7,
  41. kSysRtClockMdId = 0xf8,
  42. kSysRtUndef0MdId = 0xf9,
  43. kSysRtStartMdId = 0xfa,
  44. kSysRtContMdId = 0xfb,
  45. kSysRtStopMdId = 0xfc,
  46. kSysRtUndef1MdId = 0xfd,
  47. kSysRtSenseMdId = 0xfe,
  48. kSysRtResetMdId = 0xff,
  49. kMetaStId = 0xff,
  50. kSeqNumbMdId = 0x00,
  51. kTextMdId = 0x01,
  52. kCopyMdId = 0x02,
  53. kTrkNameMdId = 0x03,
  54. kInstrNameMdId = 0x04,
  55. kLyricsMdId = 0x05,
  56. kMarkerMdId = 0x06,
  57. kCuePointMdId = 0x07,
  58. kMidiChMdId = 0x20,
  59. kEndOfTrkMdId = 0x2f,
  60. kTempoMdId = 0x51,
  61. kSmpteMdId = 0x54,
  62. kTimeSigMdId = 0x58,
  63. kKeySigMdId = 0x59,
  64. kSeqSpecMdId = 0x7f,
  65. kInvalidMetaMdId = 0x80,
  66. kSustainCtlMdId = 0x40,
  67. kPortamentoCtlMdId = 0x41,
  68. kSostenutoCtlMdId = 0x42,
  69. kSoftPedalCtlMdId = 0x43,
  70. kLegatoCtlMdId = 0x44
  71. };
  72. typedef unsigned char cmMidiByte_t;
  73. //===============================================================================================
  74. // Utility Functions
  75. //
  76. #define cmMidiIsStatus( s ) (kNoteOffMdId <= (s) /*&& ((unsigned)(s)) <= kSysRtResetMdId*/ )
  77. #define cmMidiIsChStatus( s ) (kNoteOffMdId <= (s) && (s) < kSysExMdId)
  78. #define cmMidiIsNoteOn( s ) ( kNoteOnMdId <= (s) && (s) < (kNoteOnMdId + kMidiChCnt) )
  79. #define cmMidiIsNoteOff( s, d1 ) ( (cmMidiIsNoteOn(s) && (d1)==0) || (kNoteOffMdId <= (s) && (s) < (kNoteOffMdId + kMidiChCnt)) )
  80. #define cmMidiIsCtl( s ) ( kCtlMdId <= (s) && (s) < (kCtlMdId + kMidiChCnt) )
  81. #define cmMidiIsSustainPedal( s, d0 ) ( kCtlMdId <= (s) && (s) <= (kCtlMdId + kMidiChCnt) && (d0)== kSustainCtlMdId )
  82. #define cmMidiIsSustainPedalDown( s, d0, d1) ( cmMidiIsSustainPedal(s,d0) && (d1)>=64 )
  83. #define cmMidiIsSustainPedalUp( s, d0, d1) ( cmMidiIsSustainPedal(s,d0) && (d1)<64 )
  84. #define cmMidiIsSostenutoPedal( s, d0 ) ( kCtlMdId <= (s) && (s) <= (kCtlMdId + kMidiChCnt) && (d0)== kSostenutoCtlMdId )
  85. #define cmMidiIsSostenutoPedalDown( s, d0, d1) ( cmMidiIsSostenutoPedal(s,d0) && (d1)>=64 )
  86. #define cmMidiIsSostenutoPedalUp( s, d0, d1) ( cmMidiIsSostenutoPedal(s,d0) && (d1)<64 )
  87. #define cmMidiIsPedal( s, d0 ) ( kCtlMdId <= (s) && (s) <= (kCtlMdId + kMidiChCnt) && (d0)>=kSustainCtlMdId && (d0)<=kLegatoCtlMdId )
  88. #define cmMidiIsPedalDown( s, d0, d1 ) ( cmMidiIsPedal(s,d0) && (d1)>=64 )
  89. #define cmMidiIsPedalUp( s, d0, d1 ) ( cmMidiIsPedal(s,d0) && (d1)<64 )
  90. const char* cmMidiStatusToLabel( cmMidiByte_t status );
  91. const char* cmMidiMetaStatusToLabel( cmMidiByte_t metaStatus );
  92. const char* cmMidiPedalLabel( cmMidiByte_t d0 );
  93. // Returns kInvalidMidiByte if status is not a valid status byte
  94. cmMidiByte_t cmMidiStatusToByteCount( cmMidiByte_t status );
  95. unsigned cmMidiTo14Bits( cmMidiByte_t d0, cmMidiByte_t d1 );
  96. void cmMidiSplit14Bits( unsigned v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref );
  97. int cmMidiToPbend( cmMidiByte_t d0, cmMidiByte_t d1 );
  98. void cmMidiSplitPbend( int v, cmMidiByte_t* d0Ref, cmMidiByte_t* d1Ref );
  99. //===============================================================================================
  100. // MIDI Communication data types
  101. //
  102. typedef struct
  103. {
  104. //unsigned deltaUs; // time since last MIDI msg in microseconds
  105. cmTimeSpec_t timeStamp;
  106. cmMidiByte_t status; // midi status byte
  107. cmMidiByte_t d0; // midi data byte 0
  108. cmMidiByte_t d1; // midi data byte 1
  109. cmMidiByte_t pad;
  110. } cmMidiMsg;
  111. typedef struct
  112. {
  113. void* cbDataPtr; // application supplied reference value from mdParserCreate()
  114. unsigned devIdx; // the device the msg originated from
  115. unsigned portIdx; // the port index on the source device
  116. cmMidiMsg* msgArray; // pointer to an array of 'msgCnt' mdMsg records or NULL if sysExMsg is non-NULL
  117. cmMidiByte_t* sysExMsg; // pointer to a sys-ex msg or NULL if msgArray is non-NULL (see note below)
  118. unsigned msgCnt; // count of mdMsg records or sys-ex bytes
  119. } cmMidiPacket_t;
  120. // Notes: If the sys-ex message can be contained in a single msg then
  121. // then the first msg byte is kSysExMdId and the last is kSysComEoxMdId.
  122. // If the sys-ex message is broken into multiple pieces then only the
  123. // first will begin with kSysExMdId and the last will end with kSysComEoxMdId.
  124. // If label is NULL or labelCharCnt==0 then a pointer to an internal static
  125. // buffer is returned. If label[] is given the it
  126. // should have at least 5 (kMidiPitchCharCnt) char's (including the terminating zero).
  127. // If 'pitch' is outside of the range 0-127 then a blank string is returned.
  128. const char* cmMidiToSciPitch( cmMidiByte_t pitch, char* label, unsigned labelCharCnt );
  129. // Convert a scientific pitch to MIDI pitch. acc == 1 == sharp, acc == -1 == flat.
  130. // The pitch character must be in the range 'A' to 'G'. Upper or lower case is valid.
  131. // Return kInvalidMidiPitch if the arguments are not valid.
  132. cmMidiByte_t cmSciPitchToMidiPitch( cmChar_t pitch, int acc, int octave );
  133. // Scientific pitch string: [A-Ga-g][#b][#] where # may be -1 to 9.
  134. // Return kInvalidMidiPitch if sciPtichStr does not contain a valid
  135. // scientific pitch string. This function will convert C-1 to G9 to
  136. // valid MIDI pitch values 0 to 127. Scientific pitch strings outside
  137. // of this range will be returned as kInvalidMidiPitch.
  138. cmMidiByte_t cmSciPitchToMidi( const char* sciPitchStr );
  139. //)
  140. #ifdef __cplusplus
  141. }
  142. #endif
  143. #endif