Browse Source

cmMidiFile.h/c : Added cmMidiFileInsertMsg() Also rearranged code to isolate

cmMidiTrackMsg_t allocation.  These changes are not yet tested.
master
kevin 7 years ago
parent
commit
5cde332add
2 changed files with 185 additions and 72 deletions
  1. 181
    72
      cmMidiFile.c
  2. 4
    0
      cmMidiFile.h

+ 181
- 72
cmMidiFile.c View File

@@ -19,8 +19,6 @@
19 19
 #define mfSwap32(v)  cmSwap32(v)
20 20
 #endif
21 21
 
22
-
23
-
24 22
 typedef struct
25 23
 {
26 24
   unsigned          cnt;   // count of track records
@@ -160,10 +158,25 @@ cmMfRC_t _cmMidiFileReadVarLen( _cmMidiFile_t* mfp, unsigned* p )
160 158
   return kOkMfRC; 
161 159
 }
162 160
 
163
-cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status, cmMidiTrackMsg_t** trkMsgPtrPtr )
161
+cmMidiTrackMsg_t* _cmMidiFileAllocMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status )
164 162
 {
165 163
   cmMidiTrackMsg_t* tmp = (cmMidiTrackMsg_t*)_cmMidiFileMalloc(mfp, sizeof(cmMidiTrackMsg_t) );
166
-  
164
+
165
+  // set the generic track record fields
166
+  tmp->dtick     = dtick;
167
+  tmp->status   = status;
168
+  tmp->metaId   = kInvalidMetaMdId;
169
+  tmp->trkIdx   = trkIdx;
170
+  tmp->byteCnt  = 0;
171
+  tmp->uid      = mfp->nextUid++;
172
+
173
+  return tmp;
174
+}
175
+
176
+cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, unsigned dtick, cmMidiByte_t status, cmMidiTrackMsg_t** trkMsgPtrPtr )
177
+{
178
+  cmMidiTrackMsg_t* tmp = _cmMidiFileAllocMsg( mfp, trkIdx, dtick, status );
179
+    
167 180
   // link new record onto track record chain
168 181
   if( mfp->trkV[trkIdx].base == NULL )
169 182
     mfp->trkV[trkIdx].base = tmp;
@@ -174,12 +187,6 @@ cmMfRC_t _cmMidiFileAppendTrackMsg( _cmMidiFile_t* mfp, unsigned short trkIdx, u
174 187
   mfp->trkV[trkIdx].cnt++;
175 188
 
176 189
 
177
-  // set the generic track record fields
178
-  tmp->dtick     = dtick;
179
-  tmp->status   = status;
180
-  tmp->metaId   = kInvalidMetaMdId;
181
-  tmp->trkIdx   = trkIdx;
182
-  tmp->byteCnt  = 0;
183 190
   *trkMsgPtrPtr = tmp;
184 191
 
185 192
   return kOkMfRC;
@@ -521,6 +528,43 @@ cmMfRC_t _cmMidiFileClose( _cmMidiFile_t* mfp )
521 528
   
522 529
 }
523 530
 
531
+void _cmMidiFileLinearize( _cmMidiFile_t* mfp )
532
+{
533
+  unsigned trkIdx,i,j;
534
+  
535
+  // get the total trk msg count
536
+  mfp->msgN = 0;
537
+  for(trkIdx=0; trkIdx<mfp->trkN; ++trkIdx)
538
+    mfp->msgN += mfp->trkV[ trkIdx ].cnt;
539
+
540
+  // allocate the trk msg index vector: msgV[]
541
+  mfp->msgV = cmMemResizeZ(cmMidiTrackMsg_t*, mfp->msgV, mfp->msgN);
542
+
543
+  // store a pointer to every trk msg in msgV[]
544
+  for(i=0,j=0; i<mfp->trkN; ++i)
545
+  {
546
+    cmMidiTrackMsg_t* m = mfp->trkV[i].base;
547
+    
548
+    for(; m!=NULL; m=m->link)
549
+    {
550
+      assert( j < mfp->msgN );
551
+      
552
+      mfp->msgV[j++] = m;
553
+    }
554
+  }
555
+
556
+
557
+  // set the atick value in each msg
558
+  _cmMidiFileSetAccumulateTicks(mfp);
559
+    
560
+  // sort msgV[] in ascending order on atick
561
+  qsort( mfp->msgV, mfp->msgN, sizeof(cmMidiTrackMsg_t*), _cmMidiFileSortFunc );
562
+
563
+  // set the amicro value in each msg
564
+  _cmMidiFileSetAbsoluteTime(mfp);
565
+  
566
+}
567
+
524 568
 
525 569
 cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
526 570
 {
@@ -528,7 +572,6 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
528 572
   _cmMidiFile_t* mfp    = NULL;
529 573
   unsigned short trkIdx = 0;
530 574
   cmErr_t        err;
531
-  unsigned i,j;
532 575
 
533 576
   if( cmMidiFileIsValid(*hPtr) )
534 577
     if((rc = _cmMidiFileClose(_cmMidiFileHandleToPtr(*hPtr))) != kOkMfRC )
@@ -538,7 +581,7 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
538 581
 
539 582
   // allocate the midi file object 
540 583
   if(( mfp = cmMemAllocZ( _cmMidiFile_t, 1)) == NULL )
541
-    return rc = cmErrMsg(&err,kMemAllocFailMfRC,"MIDI file memory allocation failed.");
584
+    return rc                                 = cmErrMsg(&err,kMemAllocFailMfRC,"MIDI file memory allocation failed.");
542 585
 
543 586
   cmErrClone(&mfp->err,&err);
544 587
 
@@ -562,7 +605,7 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
562 605
   
563 606
   while( !cmFileEof(mfp->fh) && trkIdx < mfp->trkN )
564 607
   {
565
-    unsigned chkId=0,chkN=0;
608
+    unsigned chkId = 0,chkN=0;
566 609
 
567 610
     // read the chunk id
568 611
     if((rc = _cmMidiFileRead32(mfp,&chkId)) != kOkMfRC )
@@ -591,43 +634,12 @@ cmMfRC_t cmMidiFileOpen( cmCtx_t* ctx, cmMidiFileH_t* hPtr, const char* fn )
591 634
     }
592 635
   }
593 636
 
594
-  // get the total trk msg count
595
-  mfp->msgN = 0;
596
-  for(trkIdx=0; trkIdx<mfp->trkN; ++trkIdx)
597
-    mfp->msgN += mfp->trkV[ trkIdx ].cnt;
598
-
599
-  // allocate the trk msg index vector: msgV[]
600
-  mfp->msgV = cmMemAllocZ(cmMidiTrackMsg_t*, mfp->msgN);
601
-
602
-  mfp->nextUid = 0;
603
-
604
-  // store a pointer to every trk msg in msgV[]  and set 'uid'  
605
-  for(i=0,j=0; i<mfp->trkN; ++i)
606
-  {
607
-    cmMidiTrackMsg_t* m = mfp->trkV[i].base;
608
-    
609
-    for(; m!=NULL; m=m->link)
610
-    {
611
-      assert( j < mfp->msgN );
612
-      
613
-      mfp->msgV[j++] = m;
614
-      m->uid         = mfp->nextUid++;
615
-    }
616
-  }
617
-
618
-  mfp->fn = _cmMidiFileMalloc(mfp,strlen(fn)+1);
637
+  // store the file name
638
+  mfp->fn          = _cmMidiFileMalloc(mfp,strlen(fn)+1);
619 639
   assert( mfp->fn != NULL );
620 640
   strcpy(mfp->fn,fn);
621
-
622
-
623
-  // set the atick value in each msg
624
-  _cmMidiFileSetAccumulateTicks(mfp);
625
-    
626
-  // sort msgV[] in ascending order on atick
627
-  qsort( mfp->msgV, mfp->msgN, sizeof(cmMidiTrackMsg_t*), _cmMidiFileSortFunc );
628
-
629
-  // set the amicro value in each msg
630
-  _cmMidiFileSetAbsoluteTime(mfp);
641
+  
642
+  _cmMidiFileLinearize(mfp);
631 643
   
632 644
   hPtr->h = mfp;
633 645
 
@@ -682,11 +694,11 @@ cmMfRC_t _cmMidiFileWrite16( _cmMidiFile_t* mfp, unsigned short v )
682 694
 
683 695
 cmMfRC_t _cmMidiFileWrite24( _cmMidiFile_t* mfp, unsigned v )
684 696
 {
685
-  cmMfRC_t rc   = kOkMfRC;
697
+  cmMfRC_t rc = kOkMfRC;
686 698
   unsigned mask = 0xff0000;
687 699
   int      i;
688 700
 
689
-  for(i=2; i>=0; --i)
701
+  for(i = 2; i>=0; --i)
690 702
   {
691 703
     unsigned char c = (v & mask) >> (i*8);
692 704
     mask >>= 8;
@@ -727,7 +739,7 @@ cmMfRC_t _cmMidiFileWriteRecd( _cmMidiFile_t* mfp, const void* v, unsigned byteC
727 739
 
728 740
 cmMfRC_t _cmMidiFileWriteVarLen( _cmMidiFile_t* mfp, unsigned v )
729 741
 {
730
-  cmMfRC_t rc = kOkMfRC;
742
+  cmMfRC_t rc  = kOkMfRC;
731 743
   unsigned buf = v & 0x7f;
732 744
  
733 745
   while((v >>= 7) > 0 )
@@ -786,7 +798,7 @@ cmMfRC_t _cmMidiFileWriteHdr( _cmMidiFile_t* mfp )
786 798
   else
787 799
   {
788 800
     // ... otherwise the division field was given in smpte
789
-    v  = mfp->smpteFmtId << 8;
801
+    v = mfp->smpteFmtId << 8;
790 802
     v += mfp->smpteTicksPerFrame;    
791 803
   }
792 804
 
@@ -800,7 +812,7 @@ cmMfRC_t _cmMidiFileWriteHdr( _cmMidiFile_t* mfp )
800 812
 
801 813
 cmMfRC_t _cmMidiFileWriteSysEx( _cmMidiFile_t* mfp, cmMidiTrackMsg_t* tmp )
802 814
 {
803
-  cmMfRC_t     rc = kOkMfRC;
815
+  cmMfRC_t rc = kOkMfRC;
804 816
 
805 817
   if((rc = _cmMidiFileWrite8(mfp,kSysExMdId)) != kOkMfRC )
806 818
     goto errLabel;
@@ -814,8 +826,8 @@ cmMfRC_t _cmMidiFileWriteSysEx( _cmMidiFile_t* mfp, cmMidiTrackMsg_t* tmp )
814 826
 
815 827
 cmMfRC_t _cmMidiFileWriteChannelMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp, cmMidiByte_t* runStatus )
816 828
 {
817
-  cmMfRC_t     rc     = kOkMfRC;
818
-  unsigned     byteN  = cmMidiStatusToByteCount(tmp->status);
829
+  cmMfRC_t     rc    = kOkMfRC;
830
+  unsigned     byteN = cmMidiStatusToByteCount(tmp->status);
819 831
   cmMidiByte_t status = tmp->status + tmp->u.chMsgPtr->ch;
820 832
 
821 833
   if( status != *runStatus )
@@ -839,7 +851,7 @@ cmMfRC_t _cmMidiFileWriteChannelMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t*
839 851
 
840 852
 cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tmp )
841 853
 {
842
-  cmMfRC_t     rc;
854
+  cmMfRC_t rc;
843 855
 
844 856
   if((rc = _cmMidiFileWrite8(mfp,kMetaStId)) != kOkMfRC )
845 857
     return rc;
@@ -852,7 +864,7 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
852 864
   {
853 865
     case kSeqNumbMdId:
854 866
       if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.sVal))) == kOkMfRC )
855
-        rc = _cmMidiFileWrite16(mfp,tmp->u.sVal);
867
+        rc                                                  = _cmMidiFileWrite16(mfp,tmp->u.sVal);
856 868
       break;
857 869
 
858 870
     case kTempoMdId:
@@ -862,27 +874,27 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
862 874
 
863 875
     case kSmpteMdId:
864 876
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiSmpte_t))) == kOkMfRC )
865
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.smptePtr,sizeof(cmMidiSmpte_t));
877
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.smptePtr,sizeof(cmMidiSmpte_t));
866 878
         break;
867 879
           
868 880
     case kTimeSigMdId:
869 881
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiTimeSig_t))) == kOkMfRC )
870
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.timeSigPtr,sizeof(cmMidiTimeSig_t));
882
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.timeSigPtr,sizeof(cmMidiTimeSig_t));
871 883
         break;
872 884
 
873 885
     case kKeySigMdId:
874 886
         if((rc = _cmMidiFileWrite8(mfp,sizeof(cmMidiKeySig_t))) == kOkMfRC )
875
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.keySigPtr,sizeof(cmMidiKeySig_t));
887
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.keySigPtr,sizeof(cmMidiKeySig_t));
876 888
         break;
877 889
 
878 890
     case kSeqSpecMdId:
879 891
         if((rc = _cmMidiFileWriteVarLen(mfp,sizeof(tmp->byteCnt))) == kOkMfRC )
880
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.sysExPtr,tmp->byteCnt);
892
+          rc   = _cmMidiFileWriteRecd(mfp,tmp->u.sysExPtr,tmp->byteCnt);
881 893
         break;
882 894
 
883 895
     case kMidiChMdId: 
884 896
         if((rc = _cmMidiFileWrite8(mfp,sizeof(tmp->u.bVal))) == kOkMfRC )
885
-          rc = _cmMidiFileWrite8(mfp,tmp->u.bVal);
897
+          rc                                                  = _cmMidiFileWrite8(mfp,tmp->u.bVal);
886 898
         break;
887 899
 
888 900
     case kEndOfTrkMdId:  
@@ -898,8 +910,8 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
898 910
     case kCuePointMdId:  
899 911
       {
900 912
         unsigned n = tmp->u.text==NULL ? 0 : strlen(tmp->u.text);
901
-        if((rc = _cmMidiFileWriteVarLen(mfp,n)) == kOkMfRC && n>0 )
902
-          rc = _cmMidiFileWriteRecd(mfp,tmp->u.text,n);
913
+        if((rc     = _cmMidiFileWriteVarLen(mfp,n)) == kOkMfRC && n>0 )
914
+          rc       = _cmMidiFileWriteRecd(mfp,tmp->u.text,n);
903 915
       }
904 916
       break;
905 917
 
@@ -915,11 +927,11 @@ cmMfRC_t _cmMidiFileWriteMetaMsg( _cmMidiFile_t* mfp, const cmMidiTrackMsg_t* tm
915 927
 
916 928
 cmMfRC_t _cmMidiFileWriteTrack( _cmMidiFile_t* mfp, unsigned trkIdx )
917 929
 {
918
-  cmMfRC_t           rc        = kOkMfRC;
919
-  cmMidiTrackMsg_t*  tmp       = mfp->trkV[trkIdx].base;
920
-  cmMidiByte_t       runStatus = 0;
930
+  cmMfRC_t          rc        = kOkMfRC;
931
+  cmMidiTrackMsg_t* tmp       = mfp->trkV[trkIdx].base;
932
+  cmMidiByte_t      runStatus = 0;
921 933
 
922
-  for(; tmp!=NULL; tmp=tmp->link)
934
+  for(; tmp != NULL; tmp=tmp->link)
923 935
   {
924 936
     // write the msg tick count
925 937
     if((rc = _cmMidiFileWriteVarLen(mfp,tmp->dtick)) != kOkMfRC )
@@ -968,8 +980,8 @@ cmMfRC_t   cmMidiFileWrite( cmMidiFileH_t h, const char* fn )
968 980
 
969 981
   for(i=0; i < mfp->trkN; ++i )
970 982
   {
971
-    unsigned chkId='MTrk';
972
-    long offs0,offs1;
983
+    unsigned chkId = 'MTrk';
984
+    long     offs0,offs1;
973 985
 
974 986
     // write the track chunk id ('MTrk')
975 987
     if((rc = _cmMidiFileWrite32(mfp,chkId)) != kOkMfRC )
@@ -1124,14 +1136,14 @@ cmMidiTrackMsg_t*  _cmMidiFileUidToMsg( _cmMidiFile_t* mfp, unsigned uid )
1124 1136
 cmMfRC_t cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel )
1125 1137
 {
1126 1138
   cmMidiTrackMsg_t* r;
1127
-  _cmMidiFile_t* mfp = _cmMidiFileHandleToPtr(h);
1139
+  _cmMidiFile_t*    mfp = _cmMidiFileHandleToPtr(h);
1128 1140
 
1129 1141
   assert( mfp != NULL );
1130 1142
 
1131 1143
   if((r = _cmMidiFileUidToMsg(mfp,uid)) == NULL )
1132 1144
     return cmErrMsg(&mfp->err,kUidNotFoundMfRC,"The MIDI file uid %i could not be found.",uid);
1133 1145
 
1134
-  if( cmMidiIsNoteOn(r->status)==false && cmMidiIsNoteOff(r->status,0)==false )
1146
+  if( cmMidiIsNoteOn(r->status) == false && cmMidiIsNoteOff(r->status,0)==false )
1135 1147
     return cmErrMsg(&mfp->err,kUidNotANoteMsgMfRC,"Cannot set velocity on a non-Note-On/Off msg.");
1136 1148
   
1137 1149
   cmMidiChMsg_t* chm = (cmMidiChMsg_t*)r->u.chMsgPtr;
@@ -1141,6 +1153,103 @@ cmMfRC_t cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel
1141 1153
   return kOkMfRC;
1142 1154
 }
1143 1155
 
1156
+// Returns NULL if uid is not found or if it the first msg on the track.
1157
+cmMidiTrackMsg_t*  _cmMidiFileMsgBeforeUid( _cmMidiFile_t* p, unsigned uid )
1158
+{
1159
+  cmMidiTrackMsg_t* m;
1160
+  
1161
+  if((m = _cmMidiFileUidToMsg(p,uid)) == NULL )
1162
+    return NULL;
1163
+
1164
+  assert( m->trkIdx < p->trkN );
1165
+
1166
+  cmMidiTrackMsg_t* m0 = NULL;
1167
+  cmMidiTrackMsg_t* m1 = p->trkV[ m->trkIdx ].base;
1168
+  for(; m1!=NULL; m1 = m1->link)
1169
+  {
1170
+    if( m1->uid == uid )
1171
+      break;
1172
+    m0 = m1;
1173
+  }
1174
+
1175
+  return m0;
1176
+}
1177
+
1178
+unsigned _cmMidiFileIsMsgFirstOnTrack( _cmMidiFile_t* p, unsigned uid )
1179
+{
1180
+  unsigned i;
1181
+  for(i=0; i<p->trkN; ++i)
1182
+    if( p->trkV[i].base!=NULL && p->trkV[i].base->uid == uid )
1183
+      return i;
1184
+  
1185
+  return cmInvalidIdx;   
1186
+}
1187
+
1188
+
1189
+cmMfRC_t cmMidiFileInsertMsg( cmMidiFileH_t h, unsigned uid, int dtick, cmMidiByte_t ch, cmMidiByte_t status, cmMidiByte_t d0, cmMidiByte_t d1 )
1190
+{
1191
+  _cmMidiFile_t*    mfp    = _cmMidiFileHandleToPtr(h);
1192
+  assert( mfp != NULL );
1193
+  cmMidiTrackMsg_t* ref    = NULL;
1194
+  unsigned          trkIdx = cmInvalidIdx;
1195
+
1196
+  // if dtick is positive ...
1197
+  if( dtick >= 0 )
1198
+  {
1199
+    ref    = _cmMidiFileUidToMsg(mfp,uid); // ... then get the ref. msg.
1200
+    trkIdx = ref->trkIdx;
1201
+  }
1202
+  else // if dtick is negative ...
1203
+  {
1204
+    // ... get get the msg before the ref. msg.
1205
+    if((ref = _cmMidiFileMsgBeforeUid(mfp,uid)) == NULL )
1206
+    {
1207
+      // ... the ref. msg was first in the track so there is no msg before it
1208
+      trkIdx = _cmMidiFileIsMsgFirstOnTrack(mfp,uid);
1209
+    }
1210
+  }
1211
+
1212
+  // verify that the reference msg was found
1213
+  if( trkIdx == cmInvalidIdx )
1214
+    return cmErrMsg(&mfp->err,kUidNotFoundMfRC,"The UID (%i) reference note could not be located.",uid);
1215
+
1216
+  assert( trkIdx < mfp->trkN );
1217
+
1218
+  // complete the msg setup
1219
+  _cmMidiTrack_t* trk   = mfp->trkV + trkIdx;
1220
+  cmMidiTrackMsg_t* m   = _cmMidiFileAllocMsg(mfp, trkIdx, abs(dtick), status );
1221
+  cmMidiChMsg_t*    c   = (cmMidiChMsg_t*)m->u.chMsgPtr; // cast away const
1222
+  c->ch   = ch;
1223
+  c->d0   = d0;
1224
+  c->d1   = d1;
1225
+
1226
+  // if 'm' is prior to the first msg in the track
1227
+  if( ref == NULL )
1228
+  {
1229
+    // ... then make 'm' the first msg in the first msg
1230
+    m->link = trk->base;
1231
+    trk->base = m;
1232
+    // 'm' is before ref and the track cannot be empty (because ref is in it) 'm'
1233
+    // can never be the last msg in the list
1234
+  } 
1235
+  else // ref is the msg before 'm'
1236
+  {
1237
+    m->link   = ref->link;
1238
+    ref->link = m;
1239
+    
1240
+    // if ref was the last msg in the trk ...
1241
+    if( trk->last == ref )
1242
+      trk->last = m;  //... then 'm' is now the last msg in the trk
1243
+  }
1244
+
1245
+  trk->cnt += 1;
1246
+
1247
+  _cmMidiFileLinearize(mfp);
1248
+
1249
+  return kOkMfRC;
1250
+
1251
+}
1252
+
1144 1253
 unsigned  cmMidiFileSeekUsecs( cmMidiFileH_t h, unsigned long long offsUSecs, unsigned* msgUsecsPtr, unsigned* microsPerTickPtr )
1145 1254
 {
1146 1255
   _cmMidiFile_t* p;

+ 4
- 0
cmMidiFile.h View File

@@ -161,6 +161,10 @@ extern "C" {
161 161
   // Set the velocity of a note-on/off msg identified by 'uid'.
162 162
   cmMfRC_t             cmMidiFileSetVelocity( cmMidiFileH_t h, unsigned uid, cmMidiByte_t vel );
163 163
 
164
+  // Insert a MIDI message relative to the reference msg identified by 'uid'.
165
+  // If dtick is positive/negative then the new msg is inserted after/before the reference msg.  
166
+  cmMfRC_t             cmMidiFileInsertMsg( cmMidiFileH_t h, unsigned uid, int dtick, cmMidiByte_t ch, cmMidiByte_t status, cmMidiByte_t d0, cmMidiByte_t d1 );
167
+  
164 168
   // Return a pointer to the first msg at or after 'usecsOffs' or kInvalidIdx if no
165 169
   // msg exists after 'usecsOffs'.  Note that 'usecOffs' is an offset from the beginning
166 170
   // of the file.

Loading…
Cancel
Save