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.

cmMidiFile.h 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #ifndef cmMidiFile_h
  2. #define cmMidiFile_h
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. // MIDI file timing:
  7. // Messages in the MIDI file are time tagged with a delta offset in 'ticks'
  8. // from the previous message in the same track.
  9. //
  10. // A 'tick' can be converted to microsends as follows:
  11. //
  12. // microsecond per tick = micros per quarter note / ticks per quarter note
  13. //
  14. // MpT = MpQN / TpQN
  15. //
  16. // TpQN is given as a constant in the MIDI file header.
  17. // MpQN is given as the value of the MIDI file tempo message.
  18. //
  19. // See cmMidiFileSeekUSecs() for an example of converting ticks to milliseconds.
  20. //
  21. // As part of the file reading process, the status byte of note-on messages
  22. // with velocity=0 are is changed to a note-off message. See _cmMidiFileReadChannelMsg().
  23. typedef cmHandle_t cmMidiFileH_t;
  24. typedef unsigned cmMfRC_t;
  25. typedef struct
  26. {
  27. cmMidiByte_t hr;
  28. cmMidiByte_t min;
  29. cmMidiByte_t sec;
  30. cmMidiByte_t frm;
  31. cmMidiByte_t sfr;
  32. } cmMidiSmpte_t;
  33. typedef struct
  34. {
  35. cmMidiByte_t num;
  36. cmMidiByte_t den;
  37. cmMidiByte_t metro;
  38. cmMidiByte_t th2s;
  39. } cmMidiTimeSig_t;
  40. typedef struct
  41. {
  42. cmMidiByte_t key;
  43. cmMidiByte_t scale;
  44. } cmMidiKeySig_t;
  45. typedef struct
  46. {
  47. cmMidiByte_t ch;
  48. cmMidiByte_t d0;
  49. cmMidiByte_t d1;
  50. unsigned durTicks; // note duration calc'd by
  51. } cmMidiChMsg_t;
  52. typedef struct cmMidiTrackMsg_str
  53. {
  54. unsigned dtick; // delta ticks
  55. cmMidiByte_t status; // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch)
  56. cmMidiByte_t metaId; //
  57. unsigned short trkIdx; //
  58. unsigned byteCnt; // length of data pointed to by u.voidPtr (or any other pointer in the union)
  59. struct cmMidiTrackMsg_str* link; // link to next record in this track
  60. union
  61. {
  62. cmMidiByte_t bVal;
  63. unsigned iVal;
  64. unsigned short sVal;
  65. const char* text;
  66. const void* voidPtr;
  67. const cmMidiSmpte_t* smptePtr;
  68. const cmMidiTimeSig_t* timeSigPtr;
  69. const cmMidiKeySig_t* keySigPtr;
  70. const cmMidiChMsg_t* chMsgPtr;
  71. const cmMidiByte_t* sysExPtr;
  72. } u;
  73. } cmMidiTrackMsg_t;
  74. enum
  75. {
  76. kOkMfRC = cmOkRC, // 0
  77. kSysFopenFailMfRC, // 1
  78. kSysFreadFailMfRC, // 2
  79. kSysFseekFailMfRC, // 3
  80. kSysFtellFailMfRC, // 4
  81. kSysFcloseFailMfRC, // 5
  82. kNotAMidiFileMfRC, // 6
  83. kMemAllocFailMfRC, // 7
  84. kFileCorruptMfRC, // 8
  85. kMissingEoxMfRC, // 9
  86. kUnknownMetaIdMfRC, // 10
  87. kInvalidHandleMfRC, // 11
  88. kMissingNoteOffMfRC, // 12
  89. kInvalidStatusMfRC // 13
  90. };
  91. extern cmMidiFileH_t cmMidiFileNullHandle;
  92. cmMfRC_t cmMidiFileOpen( const char* fn, cmMidiFileH_t* hPtr, cmCtx_t* ctx );
  93. cmMfRC_t cmMidiFileClose( cmMidiFileH_t* hp );
  94. bool cmMidiFileIsValid( cmMidiFileH_t h );
  95. // Returns track count or kInvalidCnt if 'h' is invalid.
  96. unsigned cmMidiFileTrackCount( cmMidiFileH_t h );
  97. // Return midi file format id (0,1,2) or kInvalidId if 'h' is invalid.
  98. unsigned cmMidiFileType( cmMidiFileH_t h );
  99. // Returns ticks per quarter note or kInvalidMidiByte if 'h' is invalid or 0 if file uses SMPTE ticks per frame time base.
  100. unsigned cmMidiFileTicksPerQN( cmMidiFileH_t h );
  101. // The file name used in an earlier call to midiFileOpen() or NULL if this
  102. // midi file did not originate from an actual file.
  103. const char* cmMidiFileName( cmMidiFileH_t h );
  104. // Returns SMPTE ticks per frame or kInvalidMidiByte if 'h' is invalid or 0 if file uses ticks per quarter note time base.
  105. cmMidiByte_t cmMidiFileTicksPerSmpteFrame( cmMidiFileH_t h );
  106. // Returns SMPTE format or kInvalidMidiByte if 'h' is invalid or 0 if file uses ticks per quarter note time base.
  107. cmMidiByte_t cmMidiFileSmpteFormatId( cmMidiFileH_t h );
  108. // Returns count of records in track 'trackIdx' or kInvalidCnt if 'h' is invalid.
  109. unsigned cmMidiFileTrackMsgCount( cmMidiFileH_t h, unsigned trackIdx );
  110. // Returns base of record chain from track 'trackIdx' or NULL if 'h' is invalid.
  111. const cmMidiTrackMsg_t* cmMidiFileTrackMsg( cmMidiFileH_t h, unsigned trackIdx );
  112. // Returns the total count of records in the midi file and the number in the array returned by cmMidiFileMsgArray().
  113. // Return kInvalidCnt if 'h' is invalid.
  114. unsigned cmMidiFileMsgCount( cmMidiFileH_t h );
  115. // Returns a pointer to the base of an array of pointers to each record in the file sorted in ascending time order.
  116. // Returns NULL if 'h' is invalid.
  117. const cmMidiTrackMsg_t** cmMidiFileMsgArray( cmMidiFileH_t h );
  118. // Return a pointer to the first msg at or after 'usecsOffs' or kInvalidIdx if no
  119. // msg exists after 'usecsOffs'. Note that 'usecOffs' is an offset from the beginning
  120. // of the file.
  121. // On return *'msgUsecsPtr' is set to the actual time of the msg.
  122. // (which will be equal to or greater than 'usecsOffs').
  123. unsigned cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned usecsOffs, unsigned* msgUsecsPtr, unsigned* newMicrosPerTickPtr );
  124. double cmMidiFileDurSecs( cmMidiFileH_t h );
  125. // Convert the track message 'dtick' field to delta-microseconds.
  126. void cmMidiFileTickToMicros( cmMidiFileH_t h );
  127. // Convert the track message 'dtick' field to samples.
  128. // If the absFl is set then the delta times are converted to absolute time.
  129. void cmMidiFileTickToSamples( cmMidiFileH_t h, double srate, bool absFl );
  130. // Calculate Note Duration
  131. void cmMidiFileCalcNoteDurations( cmMidiFileH_t h );
  132. // Set the delay prior to the first non-zero msg.
  133. void cmMidiFileSetDelay( cmMidiFileH_t h, unsigned ticks );
  134. // This function packs a track msg into a single consecutive
  135. // block of memory buf[ bufByteCnt ]. Call cmMidiFilePackTracMsgBufByteCount()
  136. // to get the required buffer length for any given cmMidiTrackMsg_t instance.
  137. cmMidiTrackMsg_t* cmMidiFilePackTrackMsg( const cmMidiTrackMsg_t* m, void* buf, unsigned bufByteCnt );
  138. unsigned cmMidiFilePackTrackMsgBufByteCount( const cmMidiTrackMsg_t* m );
  139. void cmMidiFilePrint( cmMidiFileH_t h, unsigned trkIdx, cmRpt_t* rpt );
  140. bool cmMidiFileIsNull( cmMidiFileH_t h );
  141. void cmMidiFileTest( const char* fn, cmCtx_t* ctx );
  142. #ifdef __cplusplus
  143. }
  144. #endif
  145. #endif