cmMidiFile.h/c : Added cmMidiFileInsertMsg() Also rearranged code to isolate
cmMidiTrackMsg_t allocation. These changes are not yet tested.
Dieser Commit ist enthalten in:
Ursprung
21d13a94fd
Commit
5cde332add
253
cmMidiFile.c
253
cmMidiFile.c
@ -19,8 +19,6 @@
|
||||
#define mfSwap32(v) cmSwap32(v)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned cnt; // count of track records
|
||||
@ -160,10 +158,25 @@ cmMfRC_t _cmMidiFileReadVarLen( _cmMidiFile_t* mfp, unsigned* p )
|
||||
return kOkMfRC;
|
||||
}
|
||||
|
||||
cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status, cmMidiTrackMsg_t** trkMsgPtrPtr )
|
||||
cmMidiTrackMsg_t* _cmMidiFileAllocMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status )
|
||||
{
|
||||
cmMidiTrackMsg_t* tmp = (cmMidiTrackMsg_t*)_cmMidiFileMalloc(mfp, sizeof(cmMidiTrackMsg_t) );
|
||||
|
||||
|
||||
// set the generic track record fields
|
||||
tmp->dtick = dtick;
|
||||
tmp->status = status;
|
||||
tmp->metaId = kInvalidMetaMdId;
|
||||
tmp->trkIdx = trkIdx;
|
||||
tmp->byteCnt = 0;
|
||||
tmp->uid = mfp->nextUid++;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status, cmMidiTrackMsg_t** trkMsgPtrPtr )
|
||||
{
|
||||
cmMidiTrackMsg_t* tmp = _cmMidiFileAllocMsg( mfp, trkIdx, dtick, status );
|
||||
|
||||
// link new record onto track record chain
|
||||
if( mfp->trkV[trkIdx].base == NULL )
|
||||
mfp->trkV[trkIdx].base = tmp;
|
||||
@ -174,12 +187,6 @@ cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, u
|
||||
mfp->trkV[trkIdx].cnt++;
|
||||
|
||||
|
||||
// set the generic track record fields
|
||||
tmp->dtick = dtick;
|
||||
tmp->status = status;
|
||||
tmp->metaId = kInvalidMetaMdId;
|
||||
tmp->trkIdx = trkIdx;
|
||||
tmp->byteCnt = 0;
|
||||
*trkMsgPtrPtr = tmp;
|
||||
|
||||
return kOkMfRC;
|
||||
@ -521,6 +528,43 @@ cmMfRC_t _cmMidiFileClose( _cmMidiFile_t* mfp )
|
||||
|
||||
}
|
||||
|
||||
void _cmMidiFileLinearize( _cmMidiFile_t* mfp )
|
||||
{
|
||||
unsigned trkIdx,i,j;
|
||||
|
||||
// get the total trk msg count
|
||||
mfp->msgN = 0;
|
||||
for(trkIdx=0; trkIdx<mfp->trkN; ++trkIdx)
|
||||
mfp->msgN += mfp->trkV[ trkIdx ].cnt;
|
||||
|
||||
// allocate the trk msg index vector: msgV[]
|
||||
mfp->msgV = cmMemResizeZ(cmMidiTrackMsg_t*, mfp->msgV, mfp->msgN);
|
||||
|
||||
// store a pointer to every trk msg in msgV[]
|
||||
for(i=0,j=0; i<mfp->trkN; ++i)
|
||||
{
|
||||
cmMidiTrackMsg_t* m = mfp->trkV[i].base;
|
||||
|
||||
for(; m!=NULL; m=m->link)
|
||||
{
|
||||
assert( j < mfp->msgN );
|
||||
|
||||
mfp->msgV[j++] = m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// set the atick value in each msg
|
||||
_cmMidiFileSetAccumulateTicks(mfp);
|
||||
|
||||
// sort msgV[] in ascending order on atick
|
||||
qsort( mfp->msgV, mfp->msgN, sizeof(cmMidiTrackMsg_t*), _cmMidiFileSortFunc );
|
||||
|
||||
// set the amicro value in each msg
|
||||
_cmMidiFileSetAbsoluteTime(mfp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
|
||||
{
|
||||
@ -528,7 +572,6 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
|
||||
_cmMidiFile_t* mfp = NULL;
|
||||
unsigned short trkIdx = 0;
|
||||
cmErr_t err;
|
||||
unsigned i,j;
|
||||
|
||||
if( cmMidiFileIsValid(*hPtr) )
|
||||
if((rc = _cmMidiFileClose(_cmMidiFileHandleToPtr(*hPtr))) != kOkMfRC )
|
||||
@ -538,7 +581,7 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
|
||||
|
||||
// allocate the midi file object
|
||||
if(( mfp = cmMemAllocZ( _cmMidiFile_t, 1)) == NULL )
|
||||
return rc = cmErrMsg(&err,kMemAllocFailMfRC,"MIDI file memory allocation failed.");
|
||||
return rc = cmErrMsg(&err,kMemAllocFailMfRC,"MIDI file memory allocation failed.");
|
||||
|
||||
cmErrClone(&mfp->err,&err);
|
||||
|
||||
@ -562,7 +605,7 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
|
||||
|
||||
while( !cmFileEof(mfp->fh) && trkIdx < mfp->trkN )
|
||||
{
|
||||
unsigned chkId=0,chkN=0;
|
||||
unsigned chkId = 0,chkN=0;
|
||||
|
||||
// read the chunk id
|
||||
if((rc = _cmMidiFileRead32(mfp,&chkId)) != kOkMfRC )
|
||||
@ -591,43 +634,12 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
|
||||
}
|
||||
}
|
||||
|
||||
// get the total trk msg count
|
||||
mfp->msgN = 0;
|
||||
for(trkIdx=0; trkIdx<mfp->trkN; ++trkIdx)
|
||||
mfp->msgN += mfp->trkV[ trkIdx ].cnt;
|
||||
|
||||
// allocate the trk msg index vector: msgV[]
|
||||
mfp->msgV = cmMemAllocZ(cmMidiTrackMsg_t*, mfp->msgN);
|
||||
|
||||
mfp->nextUid = 0;
|
||||
|
||||
// store a pointer to every trk msg in msgV[] and set 'uid'
|
||||
for(i=0,j=0; i<mfp->trkN; ++i)
|
||||
{
|
||||
cmMidiTrackMsg_t* m = mfp->trkV[i].base;
|
||||
|
||||
for(; m!=NULL; m=m->link)
|
||||
{
|
||||
assert( j < mfp->msgN );
|
||||
|
||||
mfp->msgV[j++] = m;
|
||||
m->uid = mfp->nextUid++;
|
||||
}
|
||||
}
|
||||
|
||||
mfp->fn = _cmMidiFileMalloc(mfp,strlen(fn)+1);
|
||||
// store the file name
|
||||
mfp->fn = _cmMidiFileMalloc(mfp,strlen(fn)+1);
|
||||
assert( mfp->fn != NULL );
|
||||
strcpy(mfp->fn,fn);
|
||||
|
||||
|
||||
// set the atick value in each msg
|
||||
_cmMidiFileSetAccumulateTicks(mfp);
|
||||
|
||||
// sort msgV[] in ascending order on atick
|
||||
qsort( mfp->msgV, mfp->msgN, sizeof(cmMidiTrackMsg_t*), _cmMidiFileSortFunc );
|
||||
|
||||
// set the amicro value in each msg
|
||||
_cmMidiFileSetAbsoluteTime(mfp);
|
||||
|
||||
_cmMidiFileLinearize(mfp);
|
||||
|
||||
hPtr->h = mfp;
|
||||
|
||||
@ -682,11 +694,11 @@ cmMfRC_t _cmMidiFileWrite16( _cmMidiFile_t* mfp, unsigned short v )
|
||||
|
||||
cmMfRC_t _cmMidiFileWrite24( _cmMidiFile_t* mfp, unsigned v )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
unsigned mask = 0xff0000;
|
||||
int i;
|
||||
|
||||
for(i=2; i>=0; --i)
|
||||
for(i = 2; i>=0; --i)
|
||||
{
|
||||
unsigned char c = (v & mask) >> (i*8);
|
||||
mask >>= 8;
|
||||
@ -727,7 +739,7 @@ cmMfRC_t _cmMidiFileWriteRecd( _cmMidiFile_t* mfp, const void* v, unsigned byteC
|
||||
|
||||
cmMfRC_t _cmMidiFileWriteVarLen( _cmMidiFile_t* mfp, unsigned v )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
unsigned buf = v & 0x7f;
|
||||
|
||||
while((v >>= 7) > 0 )
|
||||
@ -786,7 +798,7 @@ cmMfRC_t _cmMidiFileWriteHdr( _cmMidiFile_t* mfp )
|
||||
else
|
||||
{
|
||||
// ... otherwise the division field was given in smpte
|
||||
v = mfp->smpteFmtId << 8;
|
||||
v = mfp->smpteFmtId << 8;
|
||||
v += mfp->smpteTicksPerFrame;
|
||||
}
|
||||
|
||||
@ -800,7 +812,7 @@ cmMfRC_t _cmMidiFileWriteHdr( _cmMidiFile_t* mfp )
|
||||
|
||||
cmMfRC_t _cmMidiFileWriteSysEx( _cmMidiFile_t* mfp, cmMidiTrackMsg_t* tmp )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
|
||||
if((rc = _cmMidiFileWrite8(mfp,kSysExMdId)) != kOkMfRC )
|
||||
goto errLabel;
|
||||
@ -814,8 +826,8 @@ cmMfRC_t _cmMidiFileWriteSysEx( _cmMidiFile_t* mfp, cmMidiTrackMsg_t* tmp )
|
||||
|
||||
cmMfRC_t _cmMidiFileWriteChannelMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp, cmMidiByte_t* runStatus )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
unsigned byteN = cmMidiStatusToByteCount(tmp->status);
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
unsigned byteN = cmMidiStatusToByteCount(tmp->status);
|
||||
cmMidiByte_t status = tmp->status + tmp->u.chMsgPtr->ch;
|
||||
|
||||
if( status != *runStatus )
|
||||
@ -839,7 +851,7 @@ cmMfRC_t _cmMidiFileWriteChannelMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t*
|
||||
|
||||
cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp )
|
||||
{
|
||||
cmMfRC_t rc;
|
||||
cmMfRC_t rc;
|
||||
|
||||
if((rc = _cmMidiFileWrite8(mfp,kMetaStId)) != kOkMfRC )
|
||||
return rc;
|
||||
@ -852,7 +864,7 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
|
||||
{
|
||||
case kSeqNumbMdId:
|
||||
if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.sVal))) == kOkMfRC )
|
||||
rc = _cmMidiFileWrite16(mfp,tmp->u.sVal);
|
||||
rc = _cmMidiFileWrite16(mfp,tmp->u.sVal);
|
||||
break;
|
||||
|
||||
case kTempoMdId:
|
||||
@ -862,27 +874,27 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
|
||||
|
||||
case kSmpteMdId:
|
||||
if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiSmpte_t))) == kOkMfRC )
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.smptePtr,sizeof(cmMidiSmpte_t));
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.smptePtr,sizeof(cmMidiSmpte_t));
|
||||
break;
|
||||
|
||||
case kTimeSigMdId:
|
||||
if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiTimeSig_t))) == kOkMfRC )
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.timeSigPtr,sizeof(cmMidiTimeSig_t));
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.timeSigPtr,sizeof(cmMidiTimeSig_t));
|
||||
break;
|
||||
|
||||
case kKeySigMdId:
|
||||
if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiKeySig_t))) == kOkMfRC )
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.keySigPtr,sizeof(cmMidiKeySig_t));
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.keySigPtr,sizeof(cmMidiKeySig_t));
|
||||
break;
|
||||
|
||||
case kSeqSpecMdId:
|
||||
if((rc = _cmMidiFileWriteVarLen(mfp,sizeof(tmp->byteCnt))) == kOkMfRC )
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.sysExPtr,tmp->byteCnt);
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.sysExPtr,tmp->byteCnt);
|
||||
break;
|
||||
|
||||
case kMidiChMdId:
|
||||
if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.bVal))) == kOkMfRC )
|
||||
rc = _cmMidiFileWrite8(mfp,tmp->u.bVal);
|
||||
rc = _cmMidiFileWrite8(mfp,tmp->u.bVal);
|
||||
break;
|
||||
|
||||
case kEndOfTrkMdId:
|
||||
@ -898,8 +910,8 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
|
||||
case kCuePointMdId:
|
||||
{
|
||||
unsigned n = tmp->u.text==NULL ? 0 : strlen(tmp->u.text);
|
||||
if((rc = _cmMidiFileWriteVarLen(mfp,n)) == kOkMfRC && n>0 )
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.text,n);
|
||||
if((rc = _cmMidiFileWriteVarLen(mfp,n)) == kOkMfRC && n>0 )
|
||||
rc = _cmMidiFileWriteRecd(mfp,tmp->u.text,n);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -915,11 +927,11 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
|
||||
|
||||
cmMfRC_t _cmMidiFileWriteTrack( _cmMidiFile_t* mfp, unsigned trkIdx )
|
||||
{
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
cmMidiTrackMsg_t* tmp = mfp->trkV[trkIdx].base;
|
||||
cmMidiByte_t runStatus = 0;
|
||||
cmMfRC_t rc = kOkMfRC;
|
||||
cmMidiTrackMsg_t* tmp = mfp->trkV[trkIdx].base;
|
||||
cmMidiByte_t runStatus = 0;
|
||||
|
||||
for(; tmp!=NULL; tmp=tmp->link)
|
||||
for(; tmp != NULL; tmp=tmp->link)
|
||||
{
|
||||
// write the msg tick count
|
||||
if((rc = _cmMidiFileWriteVarLen(mfp,tmp->dtick)) != kOkMfRC )
|
||||
@ -968,8 +980,8 @@ cmMfRC_t cmMidiFileWrite( cmMidiFileH_t h, const char* fn )
|
||||
|
||||
for(i=0; i < mfp->trkN; ++i )
|
||||
{
|
||||
unsigned chkId='MTrk';
|
||||
long offs0,offs1;
|
||||
unsigned chkId = 'MTrk';
|
||||
long offs0,offs1;
|
||||
|
||||
// write the track chunk id ('MTrk')
|
||||
if((rc = _cmMidiFileWrite32(mfp,chkId)) != kOkMfRC )
|
||||
@ -1124,14 +1136,14 @@ cmMidiTrackMsg_t* _cmMidiFileUidToMsg( _cmMidiFile_t* mfp, unsigned uid )
|
||||
cmMfRC_t cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel )
|
||||
{
|
||||
cmMidiTrackMsg_t* r;
|
||||
_cmMidiFile_t* mfp = _cmMidiFileHandleToPtr(h);
|
||||
_cmMidiFile_t* mfp = _cmMidiFileHandleToPtr(h);
|
||||
|
||||
assert( mfp != NULL );
|
||||
|
||||
if((r = _cmMidiFileUidToMsg(mfp,uid)) == NULL )
|
||||
return cmErrMsg(&mfp->err,kUidNotFoundMfRC,"The MIDI file uid %i could not be found.",uid);
|
||||
|
||||
if( cmMidiIsNoteOn(r->status)==false && cmMidiIsNoteOff(r->status,0)==false )
|
||||
if( cmMidiIsNoteOn(r->status) == false && cmMidiIsNoteOff(r->status,0)==false )
|
||||
return cmErrMsg(&mfp->err,kUidNotANoteMsgMfRC,"Cannot set velocity on a non-Note-On/Off msg.");
|
||||
|
||||
cmMidiChMsg_t* chm = (cmMidiChMsg_t*)r->u.chMsgPtr;
|
||||
@ -1141,6 +1153,103 @@ cmMfRC_t cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel
|
||||
return kOkMfRC;
|
||||
}
|
||||
|
||||
// Returns NULL if uid is not found or if it the first msg on the track.
|
||||
cmMidiTrackMsg_t* _cmMidiFileMsgBeforeUid( _cmMidiFile_t* p, unsigned uid )
|
||||
{
|
||||
cmMidiTrackMsg_t* m;
|
||||
|
||||
if((m = _cmMidiFileUidToMsg(p,uid)) == NULL )
|
||||
return NULL;
|
||||
|
||||
assert( m->trkIdx < p->trkN );
|
||||
|
||||
cmMidiTrackMsg_t* m0 = NULL;
|
||||
cmMidiTrackMsg_t* m1 = p->trkV[ m->trkIdx ].base;
|
||||
for(; m1!=NULL; m1 = m1->link)
|
||||
{
|
||||
if( m1->uid == uid )
|
||||
break;
|
||||
m0 = m1;
|
||||
}
|
||||
|
||||
return m0;
|
||||
}
|
||||
|
||||
unsigned _cmMidiFileIsMsgFirstOnTrack( _cmMidiFile_t* p, unsigned uid )
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<p->trkN; ++i)
|
||||
if( p->trkV[i].base!=NULL && p->trkV[i].base->uid == uid )
|
||||
return i;
|
||||
|
||||
return cmInvalidIdx;
|
||||
}
|
||||
|
||||
|
||||
cmMfRC_t cmMidiFileInsertMsg( cmMidiFileH_t h, unsigned uid, int dtick, cmMidiByte_t ch, cmMidiByte_t status, cmMidiByte_t d0, cmMidiByte_t d1 )
|
||||
{
|
||||
_cmMidiFile_t* mfp = _cmMidiFileHandleToPtr(h);
|
||||
assert( mfp != NULL );
|
||||
cmMidiTrackMsg_t* ref = NULL;
|
||||
unsigned trkIdx = cmInvalidIdx;
|
||||
|
||||
// if dtick is positive ...
|
||||
if( dtick >= 0 )
|
||||
{
|
||||
ref = _cmMidiFileUidToMsg(mfp,uid); // ... then get the ref. msg.
|
||||
trkIdx = ref->trkIdx;
|
||||
}
|
||||
else // if dtick is negative ...
|
||||
{
|
||||
// ... get get the msg before the ref. msg.
|
||||
if((ref = _cmMidiFileMsgBeforeUid(mfp,uid)) == NULL )
|
||||
{
|
||||
// ... the ref. msg was first in the track so there is no msg before it
|
||||
trkIdx = _cmMidiFileIsMsgFirstOnTrack(mfp,uid);
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the reference msg was found
|
||||
if( trkIdx == cmInvalidIdx )
|
||||
return cmErrMsg(&mfp->err,kUidNotFoundMfRC,"The UID (%i) reference note could not be located.",uid);
|
||||
|
||||
assert( trkIdx < mfp->trkN );
|
||||
|
||||
// complete the msg setup
|
||||
_cmMidiTrack_t* trk = mfp->trkV + trkIdx;
|
||||
cmMidiTrackMsg_t* m = _cmMidiFileAllocMsg(mfp, trkIdx, abs(dtick), status );
|
||||
cmMidiChMsg_t* c = (cmMidiChMsg_t*)m->u.chMsgPtr; // cast away const
|
||||
c->ch = ch;
|
||||
c->d0 = d0;
|
||||
c->d1 = d1;
|
||||
|
||||
// if 'm' is prior to the first msg in the track
|
||||
if( ref == NULL )
|
||||
{
|
||||
// ... then make 'm' the first msg in the first msg
|
||||
m->link = trk->base;
|
||||
trk->base = m;
|
||||
// 'm' is before ref and the track cannot be empty (because ref is in it) 'm'
|
||||
// can never be the last msg in the list
|
||||
}
|
||||
else // ref is the msg before 'm'
|
||||
{
|
||||
m->link = ref->link;
|
||||
ref->link = m;
|
||||
|
||||
// if ref was the last msg in the trk ...
|
||||
if( trk->last == ref )
|
||||
trk->last = m; //... then 'm' is now the last msg in the trk
|
||||
}
|
||||
|
||||
trk->cnt += 1;
|
||||
|
||||
_cmMidiFileLinearize(mfp);
|
||||
|
||||
return kOkMfRC;
|
||||
|
||||
}
|
||||
|
||||
unsigned cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned long long offsUSecs, unsigned* msgUsecsPtr, unsigned* microsPerTickPtr )
|
||||
{
|
||||
_cmMidiFile_t* p;
|
||||
|
@ -161,6 +161,10 @@ extern "C" {
|
||||
// Set the velocity of a note-on/off msg identified by 'uid'.
|
||||
cmMfRC_t cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel );
|
||||
|
||||
// Insert a MIDI message relative to the reference msg identified by 'uid'.
|
||||
// If dtick is positive/negative then the new msg is inserted after/before the reference msg.
|
||||
cmMfRC_t cmMidiFileInsertMsg( cmMidiFileH_t h, unsigned uid, int dtick, cmMidiByte_t ch, cmMidiByte_t status, cmMidiByte_t d0, cmMidiByte_t d1 );
|
||||
|
||||
// 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.
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren