cmMidiFile.h/c Added cmMIdiFileTickToSamples()

This commit is contained in:
kevin 2012-11-17 17:32:21 -08:00
parent bf8fceead1
commit 37c2599982
2 changed files with 165 additions and 137 deletions

View File

@ -796,6 +796,30 @@ void cmMidiFileTickToMicros( cmMidiFileH_t h )
} }
void cmMidiFileTickToSamples( cmMidiFileH_t h, double srate, bool absFl )
{
_cmMidiFile_t* p;
unsigned mi;
//bool fl = true;
if((p = _cmMidiFileHandleToPtr(h)) == NULL )
return;
cmMidiFileTickToMicros(h);
unsigned absSmp = 0;
for(mi=0; mi<p->msgN; ++mi)
{
cmMidiTrackMsg_t* mp = p->msgV[mi];
unsigned delta = floor((mp->dtick*srate)/1000000.0);
mp->dtick = absFl ? absSmp : delta;
absSmp += delta;
}
}
typedef struct _cmMidiVoice_str typedef struct _cmMidiVoice_str
{ {
const cmMidiTrackMsg_t* mp; const cmMidiTrackMsg_t* mp;

View File

@ -5,63 +5,63 @@
extern "C" { extern "C" {
#endif #endif
// MIDI file timing: // MIDI file timing:
// Messages in the MIDI file are time tagged with a delta offset in 'ticks' // Messages in the MIDI file are time tagged with a delta offset in 'ticks'
// from the previous message in the same track. // from the previous message in the same track.
// //
// A 'tick' can be converted to microsends as follows: // A 'tick' can be converted to microsends as follows:
// //
// microsecond per tick = micros per quarter note / ticks per quarter note // microsecond per tick = micros per quarter note / ticks per quarter note
// //
// MpT = MpQN / TpQN // MpT = MpQN / TpQN
// //
// TpQN is given as a constant in the MIDI file header. // TpQN is given as a constant in the MIDI file header.
// MpQN is given as the value of the MIDI file tempo message. // MpQN is given as the value of the MIDI file tempo message.
// //
// See cmMidiFileSeekUSecs() for an example of converting ticks to milliseconds. // See cmMidiFileSeekUSecs() for an example of converting ticks to milliseconds.
// //
// As part of the file reading process, the status byte of note-on messages // 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(). // with velocity=0 are is changed to a note-off message. See _cmMidiFileReadChannelMsg().
typedef cmHandle_t cmMidiFileH_t; typedef cmHandle_t cmMidiFileH_t;
typedef unsigned cmMfRC_t; typedef unsigned cmMfRC_t;
typedef struct typedef struct
{ {
cmMidiByte_t hr; cmMidiByte_t hr;
cmMidiByte_t min; cmMidiByte_t min;
cmMidiByte_t sec; cmMidiByte_t sec;
cmMidiByte_t frm; cmMidiByte_t frm;
cmMidiByte_t sfr; cmMidiByte_t sfr;
} cmMidiSmpte_t; } cmMidiSmpte_t;
typedef struct typedef struct
{ {
cmMidiByte_t num; cmMidiByte_t num;
cmMidiByte_t den; cmMidiByte_t den;
cmMidiByte_t metro; cmMidiByte_t metro;
cmMidiByte_t th2s; cmMidiByte_t th2s;
} cmMidiTimeSig_t; } cmMidiTimeSig_t;
typedef struct typedef struct
{ {
cmMidiByte_t key; cmMidiByte_t key;
cmMidiByte_t scale; cmMidiByte_t scale;
} cmMidiKeySig_t; } cmMidiKeySig_t;
typedef struct typedef struct
{ {
cmMidiByte_t ch; cmMidiByte_t ch;
cmMidiByte_t d0; cmMidiByte_t d0;
cmMidiByte_t d1; cmMidiByte_t d1;
unsigned durTicks; // note duration calc'd by unsigned durTicks; // note duration calc'd by
} cmMidiChMsg_t; } cmMidiChMsg_t;
typedef struct cmMidiTrackMsg_str typedef struct cmMidiTrackMsg_str
{ {
unsigned dtick; // delta ticks unsigned dtick; // delta ticks
cmMidiByte_t status; // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch) cmMidiByte_t status; // ch msg's have the channel value removed (it is stored in u.chMsgPtr->ch)
cmMidiByte_t metaId; // cmMidiByte_t metaId; //
@ -82,10 +82,10 @@ typedef struct cmMidiTrackMsg_str
const cmMidiChMsg_t* chMsgPtr; const cmMidiChMsg_t* chMsgPtr;
const cmMidiByte_t* sysExPtr; const cmMidiByte_t* sysExPtr;
} u; } u;
} cmMidiTrackMsg_t; } cmMidiTrackMsg_t;
enum enum
{ {
kOkMfRC = cmOkRC, // 0 kOkMfRC = cmOkRC, // 0
kSysFopenFailMfRC, // 1 kSysFopenFailMfRC, // 1
kSysFreadFailMfRC, // 2 kSysFreadFailMfRC, // 2
@ -100,73 +100,77 @@ enum
kInvalidHandleMfRC, // 11 kInvalidHandleMfRC, // 11
kMissingNoteOffMfRC, // 12 kMissingNoteOffMfRC, // 12
kInvalidStatusMfRC // 13 kInvalidStatusMfRC // 13
}; };
extern cmMidiFileH_t cmMidiFileNullHandle; extern cmMidiFileH_t cmMidiFileNullHandle;
cmMfRC_t cmMidiFileOpen( const char* fn, cmMidiFileH_t* hPtr, cmCtx_t* ctx ); cmMfRC_t cmMidiFileOpen( const char* fn, cmMidiFileH_t* hPtr, cmCtx_t* ctx );
cmMfRC_t cmMidiFileClose( cmMidiFileH_t* hp ); cmMfRC_t cmMidiFileClose( cmMidiFileH_t* hp );
// Returns track count or kInvalidCnt if 'h' is invalid. // Returns track count or kInvalidCnt if 'h' is invalid.
unsigned cmMidiFileTrackCount( cmMidiFileH_t h ); unsigned cmMidiFileTrackCount( cmMidiFileH_t h );
// Return midi file format id (0,1,2) or kInvalidId if 'h' is invalid. // Return midi file format id (0,1,2) or kInvalidId if 'h' is invalid.
unsigned cmMidiFileType( cmMidiFileH_t h ); 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. // 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 ); unsigned cmMidiFileTicksPerQN( cmMidiFileH_t h );
// The file name used in an earlier call to midiFileOpen() or NULL if this // The file name used in an earlier call to midiFileOpen() or NULL if this
// midi file did not originate from an actual file. // midi file did not originate from an actual file.
const char* cmMidiFileName( cmMidiFileH_t h ); 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. // 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 ); 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. // 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 ); cmMidiByte_t cmMidiFileSmpteFormatId( cmMidiFileH_t h );
// Returns count of records in track 'trackIdx' or kInvalidCnt if 'h' is invalid. // Returns count of records in track 'trackIdx' or kInvalidCnt if 'h' is invalid.
unsigned cmMidiFileTrackMsgCount( cmMidiFileH_t h, unsigned trackIdx ); unsigned cmMidiFileTrackMsgCount( cmMidiFileH_t h, unsigned trackIdx );
// Returns base of record chain from track 'trackIdx' or NULL if 'h' is invalid. // Returns base of record chain from track 'trackIdx' or NULL if 'h' is invalid.
const cmMidiTrackMsg_t* cmMidiFileTrackMsg( cmMidiFileH_t h, unsigned trackIdx ); 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(). // 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. // Return kInvalidCnt if 'h' is invalid.
unsigned cmMidiFileMsgCount( cmMidiFileH_t h ); 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 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. // Returns NULL if 'h' is invalid.
const cmMidiTrackMsg_t** cmMidiFileMsgArray( cmMidiFileH_t h ); const cmMidiTrackMsg_t** cmMidiFileMsgArray( cmMidiFileH_t h );
// Return a pointer to the first msg at or after 'usecsOffs' or kInvalidIdx if no // 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 // msg exists after 'usecsOffs'. Note that 'usecOffs' is an offset from the beginning
// of the file. // of the file.
// On return *'msgUsecsPtr' is set to the actual time of the msg. // On return *'msgUsecsPtr' is set to the actual time of the msg.
// (which will be equal to or greater than 'usecsOffs'). // (which will be equal to or greater than 'usecsOffs').
unsigned cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned usecsOffs, unsigned* msgUsecsPtr, unsigned* newMicrosPerTickPtr ); unsigned cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned usecsOffs, unsigned* msgUsecsPtr, unsigned* newMicrosPerTickPtr );
double cmMidiFileDurSecs( cmMidiFileH_t h ); double cmMidiFileDurSecs( cmMidiFileH_t h );
// Convert the track message 'dtick' field to delta-microseconds. // Convert the track message 'dtick' field to delta-microseconds.
void cmMidiFileTickToMicros( cmMidiFileH_t h ); void cmMidiFileTickToMicros( cmMidiFileH_t h );
// Calculate Note Duration // Convert the track message 'dtick' field to samples.
void cmMidiFileCalcNoteDurations( cmMidiFileH_t h ); // If the absFl is set then the delta times are converted to absolute time.
void cmMidiFileTickToSamples( cmMidiFileH_t h, double srate, bool absFl );
// Set the delay prior to the first non-zero msg. // Calculate Note Duration
void cmMidiFileSetDelay( cmMidiFileH_t h, unsigned ticks ); void cmMidiFileCalcNoteDurations( cmMidiFileH_t h );
// This function packs a track msg into a single consecutive // Set the delay prior to the first non-zero msg.
// block of memory buf[ bufByteCnt ]. Call cmMidiFilePackTracMsgBufByteCount() void cmMidiFileSetDelay( cmMidiFileH_t h, unsigned ticks );
// 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 cmMidiFilePrint( cmMidiFileH_t h, unsigned trkIdx, cmRpt_t* rpt ); // This function packs a track msg into a single consecutive
bool cmMidiFileIsNull( cmMidiFileH_t h ); // block of memory buf[ bufByteCnt ]. Call cmMidiFilePackTracMsgBufByteCount()
void cmMidiFileTest( const char* fn, cmCtx_t* ctx ); // 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 cmMidiFilePrint( cmMidiFileH_t h, unsigned trkIdx, cmRpt_t* rpt );
bool cmMidiFileIsNull( cmMidiFileH_t h );
void cmMidiFileTest( const char* fn, cmCtx_t* ctx );
#ifdef __cplusplus #ifdef __cplusplus
} }