123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- #ifndef cmMidiFile_h
- #define cmMidiFile_h
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- //( { file_desc:"MIDI file reader and writer." kw:[midi file]}
- // MIDI file timing:
- // Messages in the MIDI file are time tagged with a delta offset in 'ticks'
- // from the previous message in the same track.
- //
- // A 'tick' can be converted to microsends as follows:
- //
- // microsecond per tick = micros per quarter note / ticks per quarter note
- //
- // MpT = MpQN / TpQN
- //
- // TpQN is given as a constant in the MIDI file header.
- // MpQN is given as the value of the MIDI file tempo message.
- //
- // See cmMidiFileSeekUSecs() for an example of converting ticks to milliseconds.
- //
- // As part of the file reading process, the status byte of note-on messages
- // with velocity=0 are is changed to a note-off message. See _cmMidiFileReadChannelMsg().
- //)
-
- //(
- typedef cmHandle_t cmMidiFileH_t;
- typedef unsigned cmMfRC_t;
-
- typedef struct
- {
- cmMidiByte_t hr;
- cmMidiByte_t min;
- cmMidiByte_t sec;
- cmMidiByte_t frm;
- cmMidiByte_t sfr;
- } cmMidiSmpte_t;
-
- typedef struct
- {
- cmMidiByte_t num;
- cmMidiByte_t den;
- cmMidiByte_t metro;
- cmMidiByte_t th2s;
- } cmMidiTimeSig_t;
-
- typedef struct
- {
- cmMidiByte_t key;
- cmMidiByte_t scale;
- } cmMidiKeySig_t;
-
- typedef struct
- {
- cmMidiByte_t ch;
- cmMidiByte_t d0;
- cmMidiByte_t d1;
- unsigned durTicks; // note duration calc'd by cmMidiFileCalcNoteDurations();
- } cmMidiChMsg_t;
-
-
- typedef struct cmMidiTrackMsg_str
- {
- unsigned uid; // uid's are unique among all msg's in the file
- unsigned dtick; // delta ticks
- unsigned atick; // accumulated ticks
- cmMidiByte_t status; // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch)
- cmMidiByte_t metaId; //
- unsigned short trkIdx; //
- unsigned byteCnt; // length of data pointed to by u.voidPtr (or any other pointer in the union)
- struct cmMidiTrackMsg_str* link; // link to next record in this track
-
- union
- {
- cmMidiByte_t bVal;
- unsigned iVal;
- unsigned short sVal;
- const char* text;
- const void* voidPtr;
- const cmMidiSmpte_t* smptePtr;
- const cmMidiTimeSig_t* timeSigPtr;
- const cmMidiKeySig_t* keySigPtr;
- const cmMidiChMsg_t* chMsgPtr;
- const cmMidiByte_t* sysExPtr;
- } u;
- } cmMidiTrackMsg_t;
-
- enum
- {
- kOkMfRC = cmOkRC, // 0
- kFileFailMfRC, // 1
- kNotAMidiFileMfRC, // 2
- kMemAllocFailMfRC, // 3
- kFileCorruptMfRC, // 4
- kMissingEoxMfRC, // 5
- kUnknownMetaIdMfRC, // 6
- kInvalidHandleMfRC, // 7
- kMissingNoteOffMfRC, // 8
- kInvalidStatusMfRC, // 9
- kSustainPedalMfRC // 10
- };
-
- extern cmMidiFileH_t cmMidiFileNullHandle;
-
- cmMfRC_t cmMidiFileOpen( const char* fn, cmMidiFileH_t* hPtr, cmCtx_t* ctx );
- cmMfRC_t cmMidiFileClose( cmMidiFileH_t* hp );
-
- cmMfRC_t cmMidiFileWrite( cmMidiFileH_t h, const char* fn );
-
- bool cmMidiFileIsValid( cmMidiFileH_t h );
-
- // Returns track count or kInvalidCnt if 'h' is invalid.
- unsigned cmMidiFileTrackCount( cmMidiFileH_t h );
-
- // Return midi file format id (0,1,2) or kInvalidId if 'h' is invalid.
- unsigned cmMidiFileType( cmMidiFileH_t h );
-
- // Returns ticks per quarter note or kInvalidMidiByte if 'h' is invalid or 0 if file uses SMPTE ticks per frame time base.
- unsigned cmMidiFileTicksPerQN( cmMidiFileH_t h );
-
- // The file name used in an earlier call to midiFileOpen() or NULL if this
- // midi file did not originate from an actual file.
- const char* cmMidiFileName( cmMidiFileH_t h );
-
- // Returns SMPTE ticks per frame or kInvalidMidiByte if 'h' is invalid or 0 if file uses ticks per quarter note time base.
- cmMidiByte_t cmMidiFileTicksPerSmpteFrame( cmMidiFileH_t h );
-
- // Returns SMPTE format or kInvalidMidiByte if 'h' is invalid or 0 if file uses ticks per quarter note time base.
- cmMidiByte_t cmMidiFileSmpteFormatId( cmMidiFileH_t h );
-
- // Returns count of records in track 'trackIdx' or kInvalidCnt if 'h' is invalid.
- unsigned cmMidiFileTrackMsgCount( cmMidiFileH_t h, unsigned trackIdx );
-
- // Returns base of record chain from track 'trackIdx' or NULL if 'h' is invalid.
- const cmMidiTrackMsg_t* cmMidiFileTrackMsg( cmMidiFileH_t h, unsigned trackIdx );
-
- // Returns the total count of records in the midi file and the number in the array returned by cmMidiFileMsgArray().
- // Return kInvalidCnt if 'h' is invalid.
- unsigned cmMidiFileMsgCount( cmMidiFileH_t h );
-
- // Returns a pointer to the base of an array of pointers to each record in the file sorted in ascending time order.
- // Returns NULL if 'h' is invalid.
- const cmMidiTrackMsg_t** cmMidiFileMsgArray( cmMidiFileH_t h );
-
- // Return a pointer to the first msg at or after 'usecsOffs' or kInvalidIdx if no
- // msg exists after 'usecsOffs'. Note that 'usecOffs' is an offset from the beginning
- // of the file.
- // On return *'msgUsecsPtr' is set to the actual time of the msg.
- // (which will be equal to or greater than 'usecsOffs').
- unsigned cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned usecsOffs, unsigned* msgUsecsPtr, unsigned* newMicrosPerTickPtr );
-
- double cmMidiFileDurSecs( cmMidiFileH_t h );
-
- // Convert the track message 'dtick' field to delta-microseconds.
- void cmMidiFileTickToMicros( cmMidiFileH_t h );
-
- // Convert the track message 'dtick' field to samples.
- // If the absFl is set then the delta times are converted to absolute time.
- void cmMidiFileTickToSamples( cmMidiFileH_t h, double srate, bool absFl );
-
- // Calculate Note Duration
- void cmMidiFileCalcNoteDurations( cmMidiFileH_t h );
-
- // Set the delay prior to the first non-zero msg.
- void cmMidiFileSetDelay( cmMidiFileH_t h, unsigned ticks );
-
- // This function packs a track msg into a single consecutive
- // block of memory buf[ bufByteCnt ]. Call cmMidiFilePackTracMsgBufByteCount()
- // to get the required buffer length for any given cmMidiTrackMsg_t instance.
- cmMidiTrackMsg_t* cmMidiFilePackTrackMsg( const cmMidiTrackMsg_t* m, void* buf, unsigned bufByteCnt );
- unsigned cmMidiFilePackTrackMsgBufByteCount( const cmMidiTrackMsg_t* m );
-
- void cmMidiFilePrintMsgs( cmMidiFileH_t h, cmRpt_t* rpt );
- void cmMidiFilePrintTrack( cmMidiFileH_t h, unsigned trkIdx, cmRpt_t* rpt );
- bool cmMidiFileIsNull( cmMidiFileH_t h );
- void cmMidiFileTest( const char* fn, cmCtx_t* ctx );
-
- //)
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif
|